potblog

技術メモとかガジェットレビューとか

ROSでserviceによる通信

1. ROSパッケージを作る

cd ~/catkin_ws
catkin_create_pkg test_service rospy

新しくプロジェクトを作成した直後の~/catkin_ws/test_serviceのディレクトリ構成は以下のようなファイル階層だと思われる。

.
├── CMakeLists.txt
├── package.xml
└── src
  • CMakeLists.txt: ビルドシステムその1
  • package.xml: ビルドシステムその2
  • src: ユーザがソースコードを保存する場所

2. サービスを定義する

新しいサービスを作成するには3ステップある。

  1. サービスコールの入出力のためのサービス定義ファイルの作成
  2. ビルドシステム1の変更
  3. ビルドシステム2の変更

1.サービス定義ファイルの作成

gedit ~/catkin_ws/src/test_service/srv/WordCount.srv

以下の文字列を貼り付ける

string words
---
uint32 count

2. ビルドシステム1の変更

CMakeLists.txtを3箇所変更する

find_package(catkin REQUIRED COMPONENTS
  rospy
)
↓
find_package(catkin REQUIRED COMPONENTS
   roscpp
   rospy
   message_generation
)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )
↓
## Generate messages in the 'msg' folder
add_message_files(
  FILES
  WordCount.msg
#   Message2.msg
)

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs  # Or other packages containing msgs
# )
↓
## Generate added messages and services with any dependencies listed here
generate_messages(
  DEPENDENCIES
  std_msgs  # Or other packages containing msgs
)

3. ビルドシステム2の変更

package.xmlの以下のコメントアウトを外す

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

3. サービスの動作確認を行う

プログラムのビルド

cd ~/catkin_ws
catkin_make

サービスコールの定義が期待したとおりかrossrvコマンドを使って確認する

rossrv show WordCount

以下のような出力が期待される

[test_service/WordCount]:
string words
---
uint32 count

次に、サービスのサーバ側のプログラムを作成する

gedit ~/catkin_ws/src/test_service/src/service_server.py

以下のコードをservice_server.pyに貼り付ける

#!/usr/bin/env python
import rospy
from test_service.srv import WordCount,WordCountResponse

# string型の引数を1つ取る
def count_words(request):
    # 符号なし整数型を返す
    return WordCountResponse(len(request.words.split()))

rospy.init_node('service_server')
service = rospy.Service('word_count', WordCount, count_words)
rospy.spin()

次に、サービス単体のテストを行う。 端末を1つ起動してroscoreを起動する

cd ~/catkin_ws
source devel/setup.bash
roscore

もう1つ端末を起動してservice_server.pyを起動する

cd ~/catkin_ws
chmod u+x ~/catkin_ws/src/test_service/src/service_server.py
source devel/setup.bash
rosrun test_service service_server.py

もう1つ端末を起動してservice_server.pyのテストを行う

source devel/setup.bash
rosservice call word_count 'a aa aaa'

以下のような出力が期待される

count: 3

4. サービスをプログラムから利用する

サービスのクライアント側のプログラムを作成する

gedit ~/catkin_ws/src/test_service/src/service_client.py

以下のコードをservice_client.pyに貼り付ける

#!/usr/bin/env python
import rospy
from test_service.srv import WordCount
import sys

rospy.init_node('service_client')
# word_countサービスが公開されるのを待つ
rospy.wait_for_service('word_count')
# ローカルプロキシにサービス名(word_count)と型(WordCount)を設定
word_counter = rospy.ServiceProxy('word_count', WordCount)
words = ' '.join(sys.argv[1:])
# word_counterが呼び出されたときにサービスコールが行われる
word_count = word_counter(words)
print words, '->', word_count.count

プログラムのビルド

cd ~/catkin_ws
catkin_make

端末を1つ起動してroscoreを起動する

cd ~/catkin_ws
source devel/setup.bash
roscore

もう1つ端末を起動してservice_server.pyを起動する

cd ~/catkin_ws
source devel/setup.bash
rosrun test_service service_server.py

もう1つ端末を起動してservice_client.pyを起動する

cd ~/catkin_ws
chmod u+x ~/catkin_ws/src/test_service/src/service_client.py
source devel/setup.bash
rosrun test_service service_client.py hoge poyo hoo bar

以下のような出力が期待される

hoge poyo hoo bar -> 4