ROS 2 実践コース|#05 turtlesim で 3 つの通信パターンを試す

第 1 週はトピックだけを使いました。ROS 2 には、ほかにサービスとアクションという通信の形があります。この回では、ROS 2 に付いてくるシミュレーター turtlesim の亀を相手に、3 つを順に試して違いを確かめます。

3 つの通信パターン。この回の実験 1〜4 で、それぞれを実際に使います
3 つの通信パターン。この回の実験 1〜4 で、それぞれを実際に使います
パターン向いていることたとえると
トピックセンサーの値や速度指令のように、流し続けるものラジオの放送
サービス設定を 1 回頼む、情報を 1 回問い合わせる窓口で聞く
アクション時間のかかる仕事を頼み、途中経過を見ながら待つ。取り消せる出前を頼む(今どこか分かり、キャンセルもできる)

第 1 週と同じく、コマンドを打つ前に予想をノートに書いてから試してください。何を予想すればよいかは、次の表のとおりです。各実験の結果の画面と説明は、「結果を見る」をクリックすると開きます。予想を書き、自分で実行してから開いてください。

実験予想すること手がかり
1. キーボードで動かす↑ キーや ← キーを押したとき、/turtle1/cmd_vel のどの数が変わるか。キーを離したとき、0 のメッセージが送られるか上の表の「トピック」。速度指令は、前に進む速さと回る速さでできています
2. 速度を流し続ける同じ速度指令を送り続けると、亀はどんな線を描くか。送るのを止めると、亀は止まるか、動き続けるか#03 の実験 6(送る側が止まっても、受ける側はエラーを出さない)
3. サービスを呼ぶ/spawn を呼んだとき、端末に何が返ってくるか。呼んだあと、コマンドはすぐ終わるか上の表の「サービス」(窓口で 1 回聞いて、1 回答えが返る)
4. アクションを呼び、取り消す途中経過の「残りの角度」がどう変わるか。途中で取り消すと、亀はどの向きで止まるか上の表の「アクション」(途中経過が分かり、キャンセルできる)
5. パラメータを変える背景の色は、パラメータを変えた直後に変わるか、/clear を呼んだあとに変わるかパラメータは、動いているノードの設定値です。変えたときにどう動くかは、ノードの作り次第です
6. 名前空間を付けて 2 つ動かすros2 node list と ros2 topic list に、どんな名前が出るか。2 つの名前はぶつかるか#03 の実験 3 で、--ros-args -r でノードの名前を変えました

予想は外れてかまいません。点になるのは、予想と結果が違ったときに「なぜ違ったか」を考えて書くところです。分からないときも空欄にせず、「分からない」と書いて、手がかりにしたことを 1 つ書きます。

授業で受ける人は、この回の記録を実習レポート(Word)の「第 3 回」のシートに書きます。スクリーンショットは、シートの中の「画面:」の欄(実験や記録の表のすぐ下)に貼ります。ひとりで学ぶ人も、予想と結果を同じ形でノートに残しておくと、あとで見返せます。

この回で撮っておく画面

動画は撮りません。そのかわり、下の画面を撮って残します。授業で受ける人は、実習レポートの「第 3 回」の、それぞれの「画面:」の欄に貼ります。ひとりで学ぶ人も、同じ画面を残しておくと、あとで値を見直せます。最初の 1 枚は、実習を始める前に端末で TZ=Asia/Tokyo date と打ち、日付と時刻が出た画面です。授業の日に実習したことの記録になります。講義用の環境の時計は世界標準時(UTC)なので、TZ=Asia/Tokyo を付けて日本時間で出します。

  • TZ=Asia/Tokyo date の画面
  • キーを押しているときの ros2 topic echo /turtle1/cmd_vel
  • ros2 topic pub を Ctrl+C で止めた直後の turtlesim の画面
  • /spawn を呼んだ端末の応答
  • アクションのフィードバックと、取り消した直後の表示
  • 背景色が変わった turtlesim の画面
  • turtlesim を 2 つ起動したときの ros2 node list

実験 1 キーボードで動かし、流れているメッセージを見る

端末を 3 つ使います。1 つめで亀の画面を開き、2 つめでキーボード操作のノードを動かし、3 つめで速度指令のトピックを表示します。

  1. 端末 1 で turtlesim_node(亀の画面)を起動する
  2. 端末 2 で turtle_teleop_key(キーボードで速度指令を送るノード)を起動する
  3. 端末 3 で、速度指令のトピック /turtle1/cmd_vel に流れているメッセージを表示する
  4. 端末 2 をクリックしてから矢印キーを押し、端末 3 の表示を見る。キーを押したときと、離したときの両方を見る
# 端末 1
ros2 run turtlesim turtlesim_node
# 端末 2
ros2 run turtlesim turtle_teleop_key
# 端末 3
ros2 topic echo /turtle1/cmd_vel

ros2 topic echo は、トピックに流れてくるメッセージを、届くたびに表示するコマンドです。キーは、必ず端末 2 をクリックしてから押してください。亀の画面や端末 3 をクリックしたまま押しても、キーボード操作のノードにはキーが届かず、亀は動きません。

結果を見る(予想を書き、自分で実行してから開く)
端末 2(右上)をクリックしてから矢印キーを押すと亀が動き、端末 3(右下)に送られた速度指令が表示されます
端末 2(右上)をクリックしてから矢印キーを押すと亀が動き、端末 3(右下)に送られた速度指令が表示されます

↑ キーで linear.x(前に進む速さ)、← → キーで angular.z(回る速さ)が入った geometry_msgs/msg/Twist 型のメッセージが送られています。Twist は、まっすぐ進む速さ(linear)と回る速さ(angular)を、それぞれ x・y・z の 3 つの数で表す型です。平面を動く亀が使うのは、このうち linear.x と angular.z だけです。

キーを押すたびに 1 つ送られ、亀はそれを受け取ったあと少しの間だけ動きます。キーを離すと新しいメッセージは表示されなくなります。0 の速度を送って止めているわけではありません。

実験 2 コマンドから速度を流し続けて、円を描かせる

実験 1 では、キーを押したときだけ指令が送られました。今度は、コマンドで同じ指令を送り続けたらどうなるか、送るのを止めたらどうなるかを調べます。

  1. 端末 2 の teleop と端末 3 の echo を Ctrl+C で止める(端末 1 の亀の画面は動かしたままにする)
  2. 端末 2 で ros2 topic pub を使い、1 秒に 10 回、同じ速度指令を送り続ける
  3. 亀の動きを見る
  4. 亀が動いている途中で、ros2 topic pub の端末で Ctrl+C を押し、亀がどうなるかを見る
ros2 topic pub --rate 10 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 1.0}, angular: {z: 1.0}}"

ros2 topic pub は、#03 の実験 4 で整数を送ったときと同じコマンドです。--rate 10 は「1 秒に 10 回送る」という意味です。"{linear: {x: 1.0}, angular: {z: 1.0}}" は、実験 1 で見た Twist の中身の書き方で、前に進む速さを 1.0、回る速さを 1.0 にしています。書かなかった数(linear.y など)は 0 になります。

結果を見る(予想を書き、自分で実行してから開く)
前に進みながら回る指令を送り続けると、亀は円を描き続けます
前に進みながら回る指令を送り続けると、亀は円を描き続けます
送るのを止めると、亀もすぐに止まります
送るのを止めると、亀もすぐに止まります

turtlesim は、最後に届いた指令を約 1 秒だけ使い、それより新しい指令が来なければ止まるように作られています。「指令が届かなくなったら止まる」かどうかは受ける側の作り次第で、ROS 2 が自動でしてくれるわけではありません。#03 の実験 6 を思い出してください。

実験 3 サービスで亀を増やし、画面を消す

ここからはサービスです。トピックと違い、サービスは「頼んだら 1 回答えが返ってくる」形です。次の順で進めます。

  1. 亀の画面を開き直す(端末 1 で Ctrl+C を押し、もう一度 ros2 run turtlesim turtlesim_node を実行する)
  2. 端末 2 で ros2 run turtlesim turtle_teleop_key を実行し、亀を少し動かして軌跡(亀が通った線)を付ける
  3. 端末 3 で /spawn を呼び、亀を 1 匹増やす
  4. 続けて /clear を呼び、軌跡を消す

/spawn は、指定した場所に亀を増やすサービスです。亀の画面は、左下が (0, 0)、右上がおよそ (11, 11) の座標になっています。

ros2 service call /spawn turtlesim/srv/Spawn "{x: 2.0, y: 2.0, theta: 0.0, name: 'turtle2'}"

ros2 service call のあとには、サービスの名前(/spawn)、サービスの型(turtlesim/srv/Spawn)、要求の中身の順に書きます。中身の x・y は亀を置く位置、theta は向き(0 は右向き)、name は新しい亀の名前です。どんな項目があるかは、ros2 interface show turtlesim/srv/Spawn で見られます。--- より上が要求、下が応答の項目です。

ros2 service call /clear std_srvs/srv/Empty
結果を見る(予想を書き、自分で実行してから開く)
左下の (2, 2) に turtle2 が現れ、端末には応答として name='turtle2' が返っています
左下の (2, 2) に turtle2 が現れ、端末には応答として name='turtle2' が返っています
/clear を呼ぶと、描いた軌跡が消えます
/clear を呼ぶと、描いた軌跡が消えます

サービスは、頼む側(Client)が要求(Request)を 1 回送り、答える側(Server)が応答(Response)を 1 回返します。ros2 service call は応答が返るまで待ち、返ってきたら終わります。std_srvs/srv/Empty は、要求にも応答にも中身がない型です。

実験 4 アクションで向きを変え、途中で取り消す

最後の通信パターンはアクションです。時間のかかる仕事を頼み、途中経過を見て、途中で取り消すところまで試します。

  1. 端末 3 で、turtlesim が持っているアクションの一覧を出す(端末 1 の亀の画面と端末 2 の teleop は動かしたままでかまいません)
  2. 亀を 90° の向きまで回すアクションを呼び、途中経過と結果を見る
  3. 反対向きを目標にしてもう一度呼び、亀が回っている途中で Ctrl+C を押して取り消す

向きは、度ではなく rad(ラジアン)という単位で指定します。半周の 180° が約 3.14 rad(円周率 π)なので、90° は約 1.57 rad です。turtlesim では、右向きが 0 で、左回り(反時計回り)が正の向きです。

ros2 action list
ros2 action send_goal --feedback /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"

ros2 action send_goal のあとには、アクションの名前、アクションの型、目標の中身の順に書きます。--feedback を付けると、途中経過も表示されます。

次に、反対向き(-1.57 rad)を目標にして送り、亀が回っている途中で Ctrl+C を押します。回り終わる前に押す必要があるので、Enter を押したら亀の画面を見て、すぐに押してください。

ros2 action send_goal --feedback /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}"
結果を見る(予想を書き、自分で実行してから開く)
Feedback の remaining(残りの角度)が少しずつ 0 に近づき、最後に Result と SUCCEEDED が表示されます
Feedback の remaining(残りの角度)が少しずつ 0 に近づき、最後に Result と SUCCEEDED が表示されます
途中で Ctrl+C を押すと Goal canceled. と表示され、CANCELED で終わります。亀は回りかけの向きで止まります
途中で Ctrl+C を押すと Goal canceled. と表示され、CANCELED で終わります。亀は回りかけの向きで止まります

アクションは、目標(Goal)を送ると、引き受ける側が途中経過(Feedback)を何回も返し、終わったら結果(Result)を返します。途中で取り消し(Cancel)もできます。回転や移動のように時間がかかり、途中で「やっぱりやめて」と言う必要がある仕事に使います。

実験 5 パラメータで背景の色を変える

パラメータは、ノードが持っている設定値です。動いているノードの設定を、外から読んだり変えたりできます。次の順で試します。

  1. 端末 3 で、ros2 param list を使って turtlesim が持っているパラメータの名前を一覧にする
  2. ros2 param set で、背景の赤の強さ background_r を 200 にし、背景の色を見る
  3. /clear を呼び、色が変わるかを見る

背景の色は、赤(background_r)・緑(background_g)・青(background_b)の 3 つの強さを、それぞれ 0〜255 の数で混ぜて作っています。ros2 param set のあとには、ノードの名前、パラメータの名前、新しい値の順に書きます。

ros2 param list /turtlesim
ros2 param set /turtlesim background_r 200

色が変わったかどうかを見てから、/clear を呼びます。

ros2 service call /clear std_srvs/srv/Empty
結果を見る(予想を書き、自分で実行してから開く)
パラメータの一覧に background_r・background_g・background_b があります。background_r を 200 にすると、背景が紫に変わりました
パラメータの一覧に background_r・background_g・background_b があります。background_r を 200 にすると、背景が紫に変わりました
続けて /clear を呼んでも、色はそのままです
続けて /clear を呼んでも、色はそのままです

この環境の turtlesim(ROS 2 Humble)は、パラメータを変えた時点で背景を塗り直します。古い版の turtlesim では、/clear を呼ぶまで色が変わりませんでした。パラメータを変えたときに何が起きるかはノードの作り方で決まるので、試して確かめる必要があります。

実験 6 同じノードを名前空間で 2 つ動かす

名前空間は、ノードやトピックの名前の前に付ける「住所」のようなものです。同じプログラムを 2 つ動かすと、ふつうは名前がぶつかります。名前空間を付けて分けられるかを試します。

  1. いまの turtlesim と teleop を Ctrl+C で止める
  2. 端末 1 と端末 2 で、名前空間 /sim1 と /sim2 を付けて turtlesim を 1 つずつ起動する
  3. 端末 3 で、ノードとトピックの一覧を出す

--ros-args -r は、#03 の実験 3 でノードの名前を置きかえたときと同じ書き方です。あのときは __node(ノードの名前)を置きかえました。今度は __ns(名前空間)を置きかえます。

# 端末 1
ros2 run turtlesim turtlesim_node --ros-args -r __ns:=/sim1
# 端末 2
ros2 run turtlesim turtlesim_node --ros-args -r __ns:=/sim2
# 端末 3
ros2 node list
ros2 topic list
結果を見る(予想を書き、自分で実行してから開く)
亀の画面が 2 つ開きました。右の端末で、ノードとトピックの一覧を出しています
亀の画面が 2 つ開きました。右の端末で、ノードとトピックの一覧を出しています
ノードは /sim1/turtlesim と /sim2/turtlesim、トピックも /sim1/turtle1/cmd_vel と /sim2/turtle1/cmd_vel のように分かれています
ノードは /sim1/turtlesim と /sim2/turtlesim、トピックも /sim1/turtle1/cmd_vel と /sim2/turtle1/cmd_vel のように分かれています

名前空間を付けると、ノードの名前もトピックの名前も、その名前空間の下に入ります。同じプログラムを 2 つ動かしても名前がぶつかりません。たとえば /sim1/turtle1/cmd_vel に速度指令を送ると、1 つめの亀だけが動きます。次の回は、これを使って 2 匹の亀を別々に動かします。

本質の問い

次の 4 つを、トピック・サービス・アクションのどれで作るのがよいか、理由と一緒に答えてください。理由には、この回のどの実験で見たことを根拠にしたかも書きます(レポートの表にも「根拠にした実験の番号」の欄があります)。

  1. LiDAR(周りの距離を測るセンサー)の距離データを送る
  2. ロボットの号機名を問い合わせる
  3. 「3 m 先まで歩いて」と頼む
  4. 歩く速さの上限を変える(パラメータを使う場合も含めて考える)

考えるときは、「何回やりとりするか(流し続けるか、1 回か)」「終わるまでに時間がかかるか」「途中でやめたくなることがあるか」の 3 つを、はじめの表と見比べてください。

もう 1 つ、実験 4 で取り消しができなかったら、ロボットでは何が困るかを書いてください。

考え方の例(答えを書いてから開く)
  • 1:トピック。1 秒に何回も新しい値が出て、受ける側は最新の値を使い続けるため。
  • 2:サービス。1 回聞いて 1 回答えがあればよく、流し続ける必要がないため。
  • 3:アクション。歩き終わるまで時間がかかり、途中でどこまで進んだかを知りたく、危ないときは取り消したいため。
  • 4:パラメータ(ノードの設定値)が合います。ただし、この講義のロボットでは、安全のための上限はロボット側のノードが持っていて、学生のノードからは変えられないようにしてあります(#08 で扱います)。
  • 取り消し:人や壁に向かって歩き始めたときに、目標に着くまで止められなくなります。

まとめ

トピックサービスアクション
やりとり送りっぱなし要求 1 回・応答 1 回目標・途中経過・結果、取り消し
コマンドros2 topic pub / echoros2 service callros2 action send_goal
この回の例/turtle1/cmd_vel/spawn、/clear/turtle1/rotate_absolute
  • パラメータは、動いているノードの設定を外から変える手段。変えたときの動きはノード次第
  • 名前空間を付けると、同じノードを何個動かしても名前がぶつからない

次の回では、コードを 1 行も変えずに、名前空間と remap とパラメータだけで、2 匹の亀に大きさの違う正方形を描かせます。

トップへ戻る