サービスの理解

目的

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」キーを入力すると引数が補完されるため便利です.

 

課題
  1. turtlesimのサービスspawnを用いて,turtle1, turtle2, turtle3という名前の亀を生成しなさい.
  2. rosnode list及びrostopic listを用いて,ノードとトピックを確認しなさい.
  3. rostopic pubでturtle2を前進させなさい.
  4. turtlesimパッケージに含まれるturtle_teleop_keyノードを起動し,turtle2を動かしなさい.
  5. ノード/turtlesimのサービスである/resetをサービスの型を調べ,rosservice callを用いて呼び出しなさい.
  6. トピック通信やサービス通信に関連するコマンドラインツールを使用し,下記の図のように/turtlesimを動かしなさい.