92
第一回 ROS 勉強会@ 東京 2014年4月12日 千葉工業大学 工学部 4年 ロボット設計・制御研究室 前川大輝

ROS JAPAN Users Group Meetup 01

Embed Size (px)

DESCRIPTION

source code : https://github.com/ros-users/marker_publisher

Citation preview

Page 1: ROS JAPAN Users Group Meetup 01

第一回 ROS勉強会@東京

2014年4月12日 千葉工業大学 工学部 4年 ロボット設計・制御研究室 前川大輝

Page 2: ROS JAPAN Users Group Meetup 01

目次

1.自己紹介2.この勉強会について3.ROSとは4.ディストリビューション5.ROSの歴史6.通信の基本モデル7.ROSのノードについて理解する8.ROSのトピックを理解する9.RVizで図形を可視化しよう10.URDF

Page 3: ROS JAPAN Users Group Meetup 01

自己紹介

■ロボカップの開発チーム「CITBrains」のリーダー → ロボカップヒューマノイドリーグに参加

■ロボカップ → ロボットと人工知能の新たな標準問題 → 「2050年までにヒューマノイドロボットで ワールドカップ・チャンピオンに勝つ」

■ロボカップヒューマノイドリーグ → 人間以上の機能を制限 → すべてのリーグの困難な要素を集約 → 40近くの国や地域が参加

Page 4: ROS JAPAN Users Group Meetup 01

世界大会の様子

Page 5: ROS JAPAN Users Group Meetup 01

■ロボカップ 2013 世界大会(オランダ) KIDサイズ:3on3サッカー4位 KIDサイズ:テクニカルチャレンジ1位 TEENサイズ:3on3サッカー 準優勝 TEENサイズ:テクニカルチャレンジ2位

■ロボカップ 2013 ジャパンオープン 5連覇(殿堂入り)

■ロボカップ 2012 世界大会(メキシコ) KIDサイズ:ベストヒューマノイド(総合世界一) KIDサイズ:3on3サッカー 準優勝 KIDサイズ:テクニカルチャレンジ1位 TEENサイズ:3on3サッカー 準優勝 TEENサイズ:テクニカルチャレンジ 2位

Page 6: ROS JAPAN Users Group Meetup 01

■教育用マイコンボードの開発プロジェクトのリーダー → 2011 ~ 2012年、ソフトウェアのライブラリ開発

■農場用メータの自動読み取り技術に関して 企業と共同で開発中

■今年からつくばチャレンジにアドバイザとして参加

■OSSの活動にも積極的

日本Qtユーザー会、ROS JAPAN Users Groupに所属

Page 7: ROS JAPAN Users Group Meetup 01

自己紹介は以上

これから勉強会の話に移ります

Page 8: ROS JAPAN Users Group Meetup 01

この勉強会について

初心者にやさしい勉強会を目指す!

■開催目的

もっと多くの人にROSの魅力を伝えたい

■ポリシー

Page 9: ROS JAPAN Users Group Meetup 01

本日の勉強会の流れ

■13:50 ~ 15:50 ROSの概要解説(前川)

■16:00 ~ 17:30 ROS+Gazeboによるロボットシミュレーション入門(akio)

■17:40 ~ 18:20 Turtlebot2について(株式会社アールティ)

Page 10: ROS JAPAN Users Group Meetup 01

 

毎回登壇者を募集します

 紹介したい話題等をお持ちの方大歓迎です

みんなで作る勉強会

Page 11: ROS JAPAN Users Group Meetup 01

勉強会の資料はネットに公開予定

Page 12: ROS JAPAN Users Group Meetup 01

問い合わせ(ROS JAPAN Users Group)

https://groups.google.com/group/ros-japan-users

Page 13: ROS JAPAN Users Group Meetup 01

Q : 何から勉強するの?

A : まずは本家のチュートリアルをこなしましょう

これを続けるかどうかは今日の様子次第

Page 14: ROS JAPAN Users Group Meetup 01

本家チュートリアル

初級1.ROS環境のインストールとセットアップ2.ROSのファイルシステムを学ぶ3.ROSパッケージを作る4.ROSのパッケージをビルドする5.ROSのノードを理解する6.ROSのトピックを理解する7.ROSのサービスとパラメータを理解する8.rqt_consoleとroslaunchを使う9.ROSでrosedを使ってファイルを編集する10.ROSのメッセージやサービスなどを作る11.シンプルなパブリッシャとサブスクライバを書く12.データを記録し、リプレイをする

中級

他のライブラリのチュートリアルその他

Page 15: ROS JAPAN Users Group Meetup 01

初級1.ROS環境のインストールとセットアップ2.ROSのファイルシステムを学ぶ3.ROSパッケージを作る4.ROSのパッケージをビルドする5.ROSのノードを理解する6.ROSのトピックを理解する7.ROSのサービスとパラメータを理解する8.rqt_consoleとroslaunchを使う9.ROSでrosedを使ってファイルを編集する10.ROSのメッセージやサービスなどを作る11.シンプルなパブリッシャとサブスクライバを書く12.データを記録し、リプレイをする

中級

他のライブラリのチュートリアルその他

本日の学習範囲

本家チュートリアル

Page 16: ROS JAPAN Users Group Meetup 01

ROS(Robot Operating System)とは

■オープンソースで提供されるロボット向けのメタ・オペレーティングシステム

■ロボット制御用のミドルウェア → ソースをコンパイルするためのビルドシステム → プロセス間通信のための通信ライブラリ

■ロボット工学分野の研究・開発におけるコードの”再利用”を 支援することが目的

ROS = 通信 + ツール群 + 機能群 + エコシステム

Page 17: ROS JAPAN Users Group Meetup 01

ディストリビューション

■ー年周期のリリース(五月にIndigo)

■ーつのリリースの開発(現在はHydro)

■二つのリリースのサポート

Page 18: ROS JAPAN Users Group Meetup 01

ROSの歴史

■2007年 Stanford大学のAI Labが開発

■2008年 WillowGarageが開発を引き継ぎ

■2013年2月からOSRF(Open Source Robotics Foundation)が開発

Page 19: ROS JAPAN Users Group Meetup 01

通信の基本モデル

Page 20: ROS JAPAN Users Group Meetup 01

■ソフトウェアの単位: ノード

■ロボットのセンサやアクチュエータ等を別々のノードとして定義 → それを組み合わせ分散システムを構築

Node A

Node B

Node C

Page 21: ROS JAPAN Users Group Meetup 01

■出版-購読型のメッセージング

■異なるプログラミング言語で記述されたノードでもやりとりが可能

Node ANode C

Publish

SubscribePublish

TopicA

Publisher Publisher

Node BSubscriber

Page 22: ROS JAPAN Users Group Meetup 01

■サービス (リモート関数呼び出し)

■利用側(多くはノード)からリクエストを受け取ると特定の処理を行うもの

Client Service

Arguments

Return Values

Page 23: ROS JAPAN Users Group Meetup 01

■パラメータ

■トピック以外のデータを送受信するための仕組み

■パラメータサーバがデータを保持 → 他のノードからの変更は通知される

Page 24: ROS JAPAN Users Group Meetup 01

■マスター

■ノードやトピックの管理を行う

■roscoreというプロセスにより提供される

Page 25: ROS JAPAN Users Group Meetup 01

■パッケージ

■機能毎に分類されたノードやライブラリの単位のこと

■パッケージを管理するための便利なコマンドが多数提供されている

■ロボット用のオープンソースパッケージが多数公開されている

Page 26: ROS JAPAN Users Group Meetup 01

ROSのノードについて理解する

Page 27: ROS JAPAN Users Group Meetup 01

■ROSを使用する際に一番初めにroscoreを起動する

$ roscore

Page 28: ROS JAPAN Users Group Meetup 01

■rosrunを用いてパッケージに含まれるノードを起動

$ rosrun turtlesim turtlesim_node

Page 29: ROS JAPAN Users Group Meetup 01

■ノードの一覧を表示

$ rosnode list

/rosout/turtlesim

Ctrl - Cでノードを停止

Page 30: ROS JAPAN Users Group Meetup 01

■リマップでコマンドラインから名前を変更

$ rosrun turtlesim turtlesim_node __name := my_turtle

rosnode list

/rosout/my_turtle

Page 31: ROS JAPAN Users Group Meetup 01

■ノードが起動しているか確認

$ rosnode ping my_turtle

rosnode: node is [/my_turtle]pinging /my_turtle with a timeout of 3.0sxmlrpc reply from http://daikimaekawa-ThinkPad-X230:58887/ time=0.523806msxmlrpc reply from http://daikimaekawa-ThinkPad-X230:58887/ time=1.019001msxmlrpc reply from http://daikimaekawa-ThinkPad-X230:58887/ time=1.125097ms

Page 32: ROS JAPAN Users Group Meetup 01

ROSのトピックを理解する

Page 33: ROS JAPAN Users Group Meetup 01

■キーボードによる亀の操作$ rosrun turtlesim turtle_teleop_key

Page 34: ROS JAPAN Users Group Meetup 01

■システムの進行状況・挙動を示すグラフの生成$ rqt_graph

ROSのノードやトピックがハイライトされる

Page 35: ROS JAPAN Users Group Meetup 01

■rostopicはトピックの詳細を調べるコマンド$ rostopic echo /turtle1/cmd_vel

linear: x: 0.0 y: 0.0 z: 0.0angular: x: 0.0 y: 0.0 z: 2.0---linear: x: 2.0 y: 0.0 z: 0.0angular: x: 0.0 y: 0.0 z: 0.0---

Page 36: ROS JAPAN Users Group Meetup 01

■rostopicが /turtle1/cmd_velを購読していることを 確認してみよう

$rqt_graph

Page 37: ROS JAPAN Users Group Meetup 01

■配信者と購読者が通信するためには同じ型のメッセージ を送受信する必要がある

■トピックの型は配信されるメッセージの型により定義される

■rostopicを使って簡単に調べることが可能

Page 38: ROS JAPAN Users Group Meetup 01

■配信-購読されているトピックとその型の情報を調べる

$ rostopic list -v

Published topics: * /turtle1/color_sensor [turtlesim/Color] 1 publisher * /turtle1/cmd_vel [geometry_msgs/Twist] 1 publisher * /rosout [rosgraph_msgs/Log] 3 publishers * /rosout_agg [rosgraph_msgs/Log] 1 publisher * /turtle1/pose [turtlesim/Pose] 1 publisher

Subscribed topics: * /turtle1/cmd_vel [geometry_msgs/Twist] 2 subscribers * /rosout [rosgraph_msgs/Log] 1 subscriber

Page 39: ROS JAPAN Users Group Meetup 01

■rostopic typeで特定のトピックのメッセージ型を調べる

$ rostopic type /turtle1/cmd_vel

geometry_msgs/Twist

Page 40: ROS JAPAN Users Group Meetup 01

■rosmsgを使用してメッセージの詳細を調べる

$ rosmsg show geometry_msgs/Twist

geometry_msgs/Vector3 linear float64 x float64 y float64 zgeometry_msgs/Vector3 angular float64 x float64 y float64 z

Page 41: ROS JAPAN Users Group Meetup 01

■rostopic pubはトピックへデータを配信します

■turtlesimを直線速度2.0, 角速度1.8で移動させる

$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

rostopic pub [topic] [msg_type] [args]

Page 42: ROS JAPAN Users Group Meetup 01

■亀は動き続けるために定期的な1Hzのコマンドが必要

$ rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

Page 43: ROS JAPAN Users Group Meetup 01

■何が起こっているかはrqt_graphでも可視化できる

■rostopic pub node と rostopic echo nodeが通信

$ rqt_graph

Page 44: ROS JAPAN Users Group Meetup 01

■rostopic hzは配信されたデータの更新頻度を調べる

■/turtle1/poseを購読して, turtlesim_nodeの速さがど  の程度か見てみよう

$ rostopic hz /turtle1/pose

subscribed to [/turtle1/pose]average rate: 62.489 min: 0.016s max: 0.016s std dev: 0.00011s window: 62average rate: 62.491 min: 0.016s max: 0.016s std dev: 0.00009s window: 125average rate: 62.496 min: 0.016s max: 0.016s std dev: 0.00009s window: 187

データの更新頻度は60Hz

Page 45: ROS JAPAN Users Group Meetup 01

■コマンドを組み合わせて便利に使える

■rostopic type と rosmsg showを結合して使ってみよう → 普通にパイプが使える

$ rostopic type /turtle1/cmd_vel | rosmsg show

geometry_msgs/Vector3 linear float64 x float64 y float64 zgeometry_msgs/Vector3 angular float64 x float64 y float64 z

Page 46: ROS JAPAN Users Group Meetup 01

■rqt_plotはトピックで配信されている データの時間図を表示する

$ rqt_plot 任意のトピックを追加

Page 47: ROS JAPAN Users Group Meetup 01

■/turtle1/pose/xと/turtle1/pose/yを可視化

Page 48: ROS JAPAN Users Group Meetup 01

■-ボタンで非表示にできる

■/turtle1/pose/thetaを追加

Page 49: ROS JAPAN Users Group Meetup 01

■rosservice listでアクティブなサービスの情報を表示

$ rosservice list

/clear/kill/reset/rosout/get_loggers/rosout/set_logger_level/spawn/turtle1/set_pen/turtle1/teleport_absolute/turtle1/teleport_relative/turtlesim/get_loggers/turtlesim/set_logger_level

Page 50: ROS JAPAN Users Group Meetup 01

■rosservice type でサービスの型を表示します

$ rosservice type clear

std_srvs/Empty

リクエストの作成にデータを送らないレスポンスの受け取りにデータを受け取らない

Page 51: ROS JAPAN Users Group Meetup 01

■rosservice callでサービスを呼び出す

■turtlesimをクリアしよう

$ rosservice call clear

Page 52: ROS JAPAN Users Group Meetup 01

■サービスが引数をとる場合を考えましょう

■spawnサービスは新しい亀を誕生させる

$ rosservice type spawn | rossrv show

float32 xfloat32 yfloat32 thetastring name---string name

Page 53: ROS JAPAN Users Group Meetup 01

■位置と向きを与えて新しい亀を誕生させよう → 名前の指定は任意

$ rosservice call spawn 2 2 0.2 “”

name: turtle2

作成した亀の名前を返す

Page 54: ROS JAPAN Users Group Meetup 01

■rosparamはROSパラメータサーバを用いてデータの 蓄積や操作を実現

$ rosparam list

/background_b/background_g/background_r/rosdistro/roslaunch/uris/host_daikimaekawa_thinkpad_x230__57324/rosversion/run_id

Page 55: ROS JAPAN Users Group Meetup 01

■rosparam setでパラメータの値を変える

$ rosparam set /background_r 255$ rosservice call clear

Page 56: ROS JAPAN Users Group Meetup 01

■rosparam getでパラメータの値を取得する

$ rosparam get /background_r

255

Page 57: ROS JAPAN Users Group Meetup 01

■全てのパラメータサーバの中身を見る

$ rosparam get /

background_b: 255background_g: 86background_r: 255rosdistro: 'hydro

'roslaunch: uris: {host_daikimaekawa_thinkpad_x230__57324: 'http://daikimaekawa-ThinkPad-X230:57324/'}rosversion: '1.10.2

'run_id: 2ec6f1ae-be3f-11e3-986c-b8763fd266b5

Page 58: ROS JAPAN Users Group Meetup 01

■全てのパラメータをファイルに書き出す

$ rosparam dump params.yaml

■yamlファイルをcopyというネームスペース の中に読み込む

$ rosparam load params.yaml copy

■rosparam getで中身を確認する

$ rosparam get copy/background_b

255

Page 59: ROS JAPAN Users Group Meetup 01

RVizで図形を可視化しよう

■通信システムを大まかに理解するためのサンプル

■RVizでデータを3次元マップ上に可視化

■トピックを送信するプログラムを書いてみよう

Page 60: ROS JAPAN Users Group Meetup 01

■ROSのワークスペースを作成(catkin)

$ mkdir -p ~/catkin_ws/src$ cd ~/catkin_ws/src$ catkin_init_workspace

$ cd ~/catkin_ws$ catkin_make

$ echo “source ~/catkin_ws/devel/setup.bash” >> ~/.bashrc

$ source ~/.bashrc

Page 61: ROS JAPAN Users Group Meetup 01

■パッケージ作成

$ cd ~/catkin_ws/src$ catkin_create_pkg marker_publisher roscpp visualization_msgs

Page 62: ROS JAPAN Users Group Meetup 01

■ノードを作成

$ roscd marker_publisher/src$ vi marker_publisher.cpp

Page 63: ROS JAPAN Users Group Meetup 01

■使用するヘッダファイルのインクルード

#include <cmath>#include <ros/ros.h>#include <visualization_msgs/Marker.h>

Page 64: ROS JAPAN Users Group Meetup 01

■初期設定

#define DEFAULT_RATE 20

int main(int argc, char *argv[]){ ros::init(argc, argv, “test”); ros::NodeHandle n; ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>(“visualization_marker”, 10); ・・・

}

Page 65: ROS JAPAN Users Group Meetup 01

■初期設定

int main(int argc, char *argv[]){ ・・・ visualization_msgs::Marker line_strip; line_strip.header.farme_id = “practice”; line_strip.ns = “practice”; line_strip.id = 1; line_strip.type = visualization_msgs::Marker::LINE_STRIP; line_strip.action = visualization_msgs::Marker::ADD; ・・・

}

Page 66: ROS JAPAN Users Group Meetup 01

■初期設定

int main(int argc, char *argv[]){ ・・・ line_strip.scale.x = 0.1; line_strip.color.b = 1.0; line_strip.color.a = 1.0; float phai = 0.0; n.setParam(“/rate”, DEFAULT_RATE); ・・・}

Page 67: ROS JAPAN Users Group Meetup 01

■図形を作成

int main(int argc, char *argv[]){ ・・・ for(int i=0; i <= 10; i++){ const float radius = i % 2 ? 6.0 : 3.0; const float theta = (72.0 * (i/2) + (i%2) * 36.0) * M_PI / 180.0; geometry_msgs::Point vertex; vertex.x = radius * cos(theta); vertex.y = radius * sin(theta); line_strip.points.push_back(vertex); } ・・・}

Page 68: ROS JAPAN Users Group Meetup 01

■図形の回転int main(int argc, char *argv[]){ ・・・ while(ros::ok()){ int val = DEFAULT_RATE; if(n.getParam(“/rate”, val)){ std::cout << “val = ” << val << std::endl; } ros::Rate r(val); line_strip.header.stamp = ros::Time::now(); line_strip.pose.orientation.z = sin(phai / 2); line_strip.pose.orientation.w = cos(phai / 2); ・・・ } return 0;}

Page 69: ROS JAPAN Users Group Meetup 01

■図形の回転

while(ros::ok){ ・・・ marker_pub.publish(line_strip); phai += 0.05; if(phai > 2 * M_PI) phai -= 2 * M_PI; r.sleep();}

Page 70: ROS JAPAN Users Group Meetup 01

■CMakeLists.txtを編集

$ rosed marker_publisher CMakeLists.txt

Page 71: ROS JAPAN Users Group Meetup 01

■CMakeLists.txtを編集

・・・

add_executable(marker_publisher_node src/marker_publisher.cpp)

target_link_libraries(marker_publisher_node ${catkin_LIBRARIES})

・・・

Page 72: ROS JAPAN Users Group Meetup 01

■パッケージをビルド

$ cd ~/catkin_ws$ catkin_make

Page 73: ROS JAPAN Users Group Meetup 01

■ノードを起動

$ rosrun marker_publisher marker_publisher_node

■rostopic echoでframe_idを確認

$ rostopic echo /visualization_marker

・・・ frame_id: practice ・・・

line_strip.header.frame_id = “practice”

Page 74: ROS JAPAN Users Group Meetup 01

■rvizで図形を可視化

Page 75: ROS JAPAN Users Group Meetup 01

■rqt_graphでノード間通信を可視化

$ rqt_graph

Page 76: ROS JAPAN Users Group Meetup 01

■図形の回転速度を変更

$ rosparam set /rate 100

Page 77: ROS JAPAN Users Group Meetup 01

■rosbagでトピックを記録

$ rosbag record /visualization_marker

■marker_publisher_nodeを停止

$ Ctrl - C

■rosbagでバグファイルを再生

$ rosbag play *.bag

rosbagはデバックの強い味方

Page 78: ROS JAPAN Users Group Meetup 01

URDF(Uni f ied Robot Description Format)

■ロボットシミュレーションへの繋ぎ

■XMLフォーマットのロボットモデルの記述

Page 79: ROS JAPAN Users Group Meetup 01

■urdf_tutorial.xmlに記述

$ vi urdf_tutorial.xml

Page 80: ROS JAPAN Users Group Meetup 01

<robot name=”test_robot”> <link name=”link1” /> <link name=”link2” /> <link name=”link3” /> <link name=”link4” /> <link name=”world” />

</robot>

?

リンク間の関係を定義する

Page 81: ROS JAPAN Users Group Meetup 01

<robot name=”test_robot”> ・・・ <joint name=”joint1” type=”continuous”> <parent link=”world”/> <child link=”link1”/> </joint> <joint name=”joint2” type=”continuous”> <parent link=”link1”/> <child link=”link2”/> </joint>  ・・・</robot>

Page 82: ROS JAPAN Users Group Meetup 01

<robot name=”test_robot”> ・・・ <joint name=”joint3” type=”continuous”> <parent link=”link1”/> <child link=”link3”/> </joint> <joint name=”joint4” type=”continuous”> <parent link=”link3”/> <child link=”link4”/> </joint></robot>

Page 83: ROS JAPAN Users Group Meetup 01

■パース可能なのかを確認

$ check_urdf urdf_tutorial.xml

robot name is: test_robot---------- Successfully Parsed XML ---------------root Link: world has 1 child(ren) child(1): link1 child(1): link2 child(2): link3 child(1): link4

Page 84: ROS JAPAN Users Group Meetup 01

■空間を追加

■<origin>でリンクの参照フレームから 子供のジョイントまでのオフセットを与える

 → 位置のオフセットxyz → 姿勢のオフセットrpy

Page 85: ROS JAPAN Users Group Meetup 01

■空間を追加

・・・<joint name=”joint1” type=“continuous”> <parent link=”world”/> <child link=”link1”/><origin xyz=”5 0 0” rpy=”0 0 3.14”/>

</joint><joint name=”joint2” type=“continuous”> <parent link=”link1”/> <child link=”link2”/><origin xyz=”5 2 0” rpy=”0 0 3.14”/>

</joint>・・・

Page 86: ROS JAPAN Users Group Meetup 01

■空間を追加

・・・<joint name=”joint3” type=“continuous”> <parent link=”link1”/> <child link=”link3”/><origin xyz=”5 0.5 0” rpy=”0 0 0”/>

</joint><joint name=”joint4” type=“continuous”> <parent link=”link3”/> <child link=”link4”/><origin xyz=”5 0 0” rpy=”0 0 3.14”/>

</joint>・・・

Page 87: ROS JAPAN Users Group Meetup 01

■ジョイントの回転を定義

■ローカルフレームでの回転軸を指定

 → joint1では<axis xyz=”0 1 0” />

Page 88: ROS JAPAN Users Group Meetup 01

■ジョイントの回転を定義

・・・<joint name=”joint1” type=“continuous”> <parent link=”world”/> <child link=”link1”/><origin xyz=”5 0 0” rpy=”0 0 3.14”/>

 <axis xyz=”0 1 0”/></joint><joint name=”joint2” type=“continuous”> <parent link=”link1”/> <child link=”link2”/><origin xyz=”5 2 0” rpy=”0 0 3.14”/>

<axis xyz=”0.707 0.707 0”/></joint>・・・

Page 89: ROS JAPAN Users Group Meetup 01

■ジョイントの回転を定義

・・・<joint name=”joint3” type=“continuous”> <parent link=”link1”/> <child link=”link3”/><origin xyz=”5 0.5 0” rpy=”0 0 0”/><axis xyz=”0.9 0.15 0”/>

</joint><joint name=”joint4” type=“continuous”> <parent link=”link3”/> <child link=”link4”/><origin xyz=”5 0 0” rpy=”0 0 3.14”/>

<axis xyz=”0.707 0.707 0”/></joint>・・・

Page 90: ROS JAPAN Users Group Meetup 01

■可視化

$ urdf_to_graphiz urdf_tutorial.xml

Page 91: ROS JAPAN Users Group Meetup 01

基礎講義はここまで

ご清聴ありがとうございました

Page 92: ROS JAPAN Users Group Meetup 01

次はシミュレータの解説を行います