#プログラミング ROS2< serviceを使う >
はじめに
ROS2(バージョンアップしたROS)を難なく扱えるようになることが目的である.その第4弾として,「serviceを使う」を扱う.
環境
仮想環境
ソフト | VMware Workstation 15 |
実装RAM | 3 GB |
OS | Ubuntu 64 ビット |
isoファイル | ubuntu-20.04.3-desktop-amd64.iso |
コンピュータ
デバイス | MSI |
プロセッサ | Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz 2.50GHz |
実装RAM | 8.00 GB (7.89 GB 使用可能) |
OS | Windows (Windows 10 Home, バージョン:21H1) |
ROS2
Distribution | foxy |
service
serviceにはRequestとResponseがあり,リクエストして待ち続けるという特徴をもち,topicのようにデータを投げ続けるようなものではない.ここでは,turtlesim_nodeにあるspawnサービスにリクエストするようなプログラムを通して,serviceを使うプログラムの作成について学んでいく.
プログラム: turtleを生み出す(spawn)
turtlesimにおけるspawnサービス
まず,serviceを使うにあたって,どのようなserviceを使うのかということを知っておく必要がある.そこで,turtlesim_nodeを立ち上げた際に用意されるserviceをros2 serice list
で確認した.その時の様子を以下に示す.今回の対象を赤線で示している.
この/tutlesim/spawn
という名前のサービスを使う.Typeも知っておく必要があるため,ros2 service type /turtlesim/spawn
で調べた.その結果を以下に示す.
どうやら,turtlesimパッケージにあるSpawnサービスというもののようだ.以降ではこれらの情報を使って,組み立てていく.
カメを生み出すプログラム
import rclpy
from turtlesim.srv import Spawn
def main(args=None):
rclpy.init(args=args)
node = rclpy.create_node('spawn_client') # create a node for service
client = node.create_client(Spawn, 'turtlesim/spawn') # create a client for service
req = Spawn.Request() # set a request to call the service
req.x = 2.0 # set position x
req.y = 2.0 # set position y
req.theta = 0.2 # set pose theta
req.name = 'new_turtle' # new name for turle
while not client.wait_for_service(timeout_sec=1.0):
node.get_logger().info('service not available, waiting again...')
# call the service Asynchronously
future = client.call_async(req)
rclpy.spin_until_future_complete(node, future)
try:
result = future.result()
except Exception as e:
node.get_logger().info(f"Service call failed {e}")
else:
node.get_logger().info(f"Result of x, y, theta, name : {req.x:.3f}, {req.y:.3f}, {req.theta:.3f}, {req.name}")
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
ソースコード内でコメントを書き忘れたが,
while not client.wait_for_service(timeout_sec=1.0):
はclientがサービスを受け取れるまでループするように記述しているが,timeout_sec=1.0
はそのループ間の間隔で,1ループ後1秒待ってまたループというようにすることができる.これにより,「サービスを待っています」というようなログを大量ではなく1秒間隔で表示することができる.
ビルドの準備
setup.pyの編集
基本的にビルドに関する情報はsetup.pyの中に記述されている.
setup.pyの編集
from setuptools import setup
package_name = 'service_lesson'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='Yuya Shimizu',
maintainer_email='yuya@example.com',
description="a package for practice 'service'",
license='BSD',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'spawn = service_lesson.spawnTurtle:main'
],
},
)
ビルド
cd ~/ros2_ws
colcon build
実行コマンド
ros2 launch turtlesim_test myTurtlesim.launch.py
ros2 run service_lesson spawn
実行の様子
今回のプログラムはある座標にカメを一体出現させれば終了というものであるため,サービスのやり取りが一度行われた時点でプログラムは終了している.また,カメの出現座標をソースコード内で1つに決めてしまっているため,連続でプログラムを実行しようとしてももうすでにカメがその座標に存在しているため,turtlesim_node側でエラーだという表示が出てくる.
今回は試していないが,座標の部分を乱数にしたり,ユーザの入力ができるようにすると様々なところにカメを出現させることができる.これを実現することでよりserviceというものの理解を深める練習となるかもしれない.
感想
ROS2でも少しずつ感覚がつかめてきた気がする.もちろん,まだまだではあるが,serviceを少し扱えるようになったことは非常に大きな進歩であるとROS1のとき同様に感じられる.次回はパラメータを使うプログラムについて学ぶ.大まかにはserviceではあるが,パラメータを使うにあたって,serviceをどのように活用していくのかということで,パラメータだけでなくserviceについての理解も深められそうで非常に楽しみである.
参考
- ロボットプログラミングROS2入門 玉川大学 岡田浩之 著,科学情報出版株式会社