目的
ROSで採用されている代表的な通信方法には,トピック通信の他にサービス通信があります.多数のノード間で連続的に通信するトピック通信とは異なり,サービス通信は1対1の双方向型の非連続的な通信です.特定の条件下で処理する際に利用されることが多いサービス通信を学ぶことで,より柔軟なシステムを構築することが可能です.ここでは,ROSのサービスに関するコマンドラインツールを用いて,サービスによる通信の仕組みを理解します.なお,学習が容易となるように,本内容はロボットシミュレータturtlesimを使用します.
ROSのコマンドラインを用いたサービスの理解
サービスはノード間で通信を行うための1つの方法です.ノードは,通信を依頼する役割と依頼を受ける役割の2つに分けられます.通信を依頼するノードをクライアント,通信を受けるノードをサーバと呼びます.また,クライアントからサーバに対する依頼をリクエスト,サーバからクライアントへ送る結果をレスポンスと呼びます.
1. ノードの起動
トピック通信と同様に,まずはマスターを立ち上げます.
$ roscore
次に,ノードを起動します.今回もturtlesimを使用します.
$ rosrun turtlesim turtlesim_node
2. サービス通信に関するコマンドラインツールの一覧
ターミナルでrosserviceと入力すると,サービス通信に関連するコマンドの一覧が表示されます.
yuu@vb:~$ rosservice Commands: rosservice args print service arguments rosservice call call the service with the provided args rosservice find find services by service type rosservice info print information about service rosservice list list active services rosservice type print service type rosservice uri print service ROSRPC uri Type rosservice <command> -h for more detailed usage, e.g. 'rosservice call -h'
サービス通信に関連したコマンドは7つ用意されています.ここでは,使用頻度のが高い幾つかのコマンドについて説明します.
2. サービスとノード
サービスを呼び出す前に,利用可能なサービスの一覧を取得します.現在,起動しているノードは下記の2つです.
yuu@vb:~$ rosnode list /rosout /turtlesim
2つのノードが利用可能なサービスの一覧を下記のように取得します.
yuu@vb:~$ 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
上記のリストからは,どのサービスがどのノードで利用できるかわかりません.例えば./spawnがどのノードから利用できるかを知るためには下記のコマンドを実行します.
yuu@vb:~$ rosservice info /spawn Node: /turtlesim URI: rosrpc://vb:43736 Type: turtlesim/Spawn Args: x y theta name
サービスである/spawnは,/turtlesimのノードで利用可能であることがわかります.また,ノード以外の情報として,URIや型,引数の情報も出力します.上記は,サービスから関連するノードを表示していましたが,逆に/turtlesimのノードから関連するサービスを表示するためには,下記のコマンドを実行します.
yuu@VB:~$ rosnode info /turtlesim -------------------------------------------------------------------------------- Node [/turtlesim] Publications: * /turtle1/color_sensor [turtlesim/Color] * /rosout [rosgraph_msgs/Log] * /turtle1/pose [turtlesim/Pose] Subscriptions: * /turtle1/cmd_vel [unknown type] Services: * /turtle1/teleport_absolute * /turtlesim/get_loggers * /turtlesim/set_logger_level * /reset * /spawn * /clear * /turtle1/set_pen * /turtle1/teleport_relative * /kill contacting node http://VB:52980/ ... Pid: 2514 Connections: * topic: /rosout * to: /rosout * direction: outbound * transport: TCPROS
ハイライトされた行に注目すると,ノードである/turtlesimが利用可能なサービスの一覧が表示されていることがわかります.
3. サービスを呼び出す
上記の処理で,どのノードがどのサービスを呼び出せるかを調べることができました.次に,サービスを使用して通信します.今回はノードである/turtlesimが利用できる/spawnというサービスを使用します.サービスにより通信するために,下記のコマンドを使用してサービスの型を調べます.
yuu@vb:~$ rosservice type /spawn turtlesim/Spawn
サービスの型が分かったので,下記のコマンドを使用してturtlesim/Spawnの引数と返り値を調べます.
yuu@vb:~$ rossrv show turtlesim/Spawn float32 x float32 y float32 theta string name --- string name
上記の出力のうち,「– – –」よりも上の部分が引数,下の部分が返り値を表しています.既存のサービスであれば,ROS.orgのwikiにサービスの処理内容や引数,返り値についての説明があります.例えば,turtlesimではこのページを参考にしましょう.2.1.3 Servicesのspawnを見ると,(x,y,theta,name)を与えて亀を生成し,亀の名前を返すとあります.試しにspawnを利用して亀を生成しましょう.サービスを呼び出すためには,下記のようにrosservice callを利用します.
yuu@vb:~$ rosservice call /spawn 1.0 1.0 3.14 turtle2
上記を実行すると,下記のように出力されると同時に新しい亀が現れます.
name: turtle2
上記の例では,xを1.0,yを1.0,thetaを3.14,nameをturtle2としてサービスを呼び出しました.なお,サービスを呼び出す際,サービス名まで入力して「tab」キーを入力すると引数が補完されるため便利です.
課題
- turtlesimのサービスspawnを用いて,turtle1, turtle2, turtle3という名前の亀を生成しなさい.
- rosnode list及びrostopic listを用いて,ノードとトピックを確認しなさい.
- rostopic pubでturtle2を前進させなさい.
- turtlesimパッケージに含まれるturtle_teleop_keyノードを起動し,turtle2を動かしなさい.
- ノード/turtlesimのサービスである/resetをサービスの型を調べ,rosservice callを用いて呼び出しなさい.
- トピック通信やサービス通信に関連するコマンドラインツールを使用し,下記の図のように/turtlesimを動かしなさい.