前の回の最後に、ロボットに正方形を歩かせると、戻ってきた位置がずれることを確かめました。ロボットが「どこに何があるか」を扱うには、データに 2 つの情報が欠かせません。どの座標系で測ったかと、いつ測ったかです。
この回は、その 2 つを /scan(LiDAR の距離データ)で調べます。その前に、データが届くかどうかを決める約束ごと、QoS を試します。
- QoS の組み合わせで、届くか届かないかが変わることを確かめる(実験 1、ロボットなし)
- 実物の
/scanの QoS を読む(実験 2) - LiDAR の座標系をたどり、RViz で点を表示する(実験 3・4・5)
- データに付いた時刻と、届くまでの遅れを測る(実験 6)
この回は、ロボットを机の上に置いたまま動かしません。
どの実験も、コマンドを打つ前に「どうなるか」の予想をノートに書いてください。何を予想すればよいかは、次の表のとおりです。各実験の結果の画面と説明は、「結果を見る」をクリックすると開きます。予想を書き、自分で実行してから開いてください。
| 実験 | 予想すること |
|---|---|
| 1. QoS の組み合わせ | 送る側と受ける側の Reliability の組み合わせ 4 通り(A〜D)のそれぞれで、届くか届かないか |
| 2. 実物の /scan の QoS | LiDAR の /scan は、reliable と best_effort のどちらで送られているか |
| 3. LiDAR の座標系 | LiDAR は、ロボットの体の基準(base_link)から見て、前・左・上のどちらへ何 cm くらいのところにあるか |
| 5. LiDAR の 0° の向き | ロボットの正面に置いた箱の点が、RViz で正面(赤い矢印の先)に出るか |
| 6. 時刻と遅れ | ros2 topic delay /scan の平均は、#07 で測った往復の時間(20 ms ほど)より大きいか小さいか |
予想は外れてかまいません。点になるのは、予想と結果が違ったときに「なぜ違ったか」を考えて書くところです。分からないときも空欄にせず、「分からない」と書いて、手がかりにしたことを 1 つ書きます。実験 4 は RViz で表示するための準備なので、予想はいりません。
授業で受ける人は、この回の記録を実習レポート(Word)の「第 7 回」のシートに書きます。スクリーンショットは、シートの中の「画面:」の欄(実験や記録の表のすぐ下)に貼ります。ひとりで学ぶ人も、予想と結果を同じ形でノートに残しておくと、あとで見返せます。
この回で撮っておく画面
動画は撮りません。そのかわり、下の画面を撮って残します。授業で受ける人は、実習レポートの「第 7 回」の、それぞれの「画面:」の欄に貼ります。ひとりで学ぶ人も、同じ画面を残しておくと、あとで値を見直せます。最初の 1 枚は、実習を始める前に端末で TZ=Asia/Tokyo date と打ち、日付と時刻が出た画面です。授業の日に実習したことの記録になります。講義用の環境の時計は世界標準時(UTC)なので、TZ=Asia/Tokyo を付けて日本時間で出します。
TZ=Asia/Tokyo dateと、つないだ直後のrobot-status- QoS の組み合わせで届かなかったときの、受ける側の端末
ros2 topic info -v /scan(Reliability・History・Durability)ros2 run tf2_ros tf2_echo base_link laser_frameros2 run tf2_tools view_framesで作った TF の木- 箱を正面に置いたときの RViz
ros2 topic delay /scanの平均・最小・最大
この回で使うもの
| もの | 使うところ |
|---|---|
| 講義用の環境(#00 で準備したもの) | すべての実験 |
| ロボット(机の上に置いたまま動かさない) | 実験 2〜6 |
| 段ボール箱など、LiDAR に映る箱 1 つ | 実験 5 |
実験 1 QoS:名前も型も合っているのに届かない
QoS(Quality of Service)は、トピックをどう届けるかの約束ごとです。いちばんよく使うのが Reliability(信頼性)で、次の 2 種類があります。
| Reliability | 届け方 |
|---|---|
reliable | 届かなかったら送り直す。確実に届くが、送り直す分だけ遅れることがある |
best_effort | 送りっぱなし。届かなかったものは捨てる |
送る側と受ける側は、それぞれ自分の QoS を決めます。組み合わせによって届くかどうかを、ロボットを使わずに PC の中だけで試します。この実験は、次の順に進めます。
- 4 通りの組み合わせについて、届くか届かないかを予想して表に書く
- A と B を試す(送る側 1 つに、受ける側 2 つを同時につなぐ)
- C と D を試す(送る側を
reliableに替える) - 結果を表に書き、予想と違ったところの理由を考える
予想する
次の表の「予想」の欄を、自分のノートかレポートに書きます。手がかりは、上の表の「届け方」です。reliable の受ける側は「届かなかったら送り直してほしい」と求めます。送る側がそれに応えられるかどうかを、1 行ずつ考えてください。
| 番号 | 送る側 | 受ける側 | 予想(届く? 届かない?) | 結果 |
|---|---|---|---|---|
| A | best_effort | reliable | ||
| B | best_effort | best_effort | ||
| C | reliable | best_effort | ||
| D | reliable | reliable |
A と B を試す
端末を 3 つ開き、上から順に実行します。--qos-reliability で、そのコマンドの Reliability を指定します。
# 端末 1(送る側:best_effort で 1 秒に 2 回送る)
ros2 topic pub --rate 2 --qos-reliability best_effort /qos_test std_msgs/msg/String "{data: 'hello'}"
# 端末 2(受ける側:reliable)
ros2 topic echo --qos-reliability reliable /qos_test
# 端末 3(受ける側:best_effort)
ros2 topic echo --qos-reliability best_effort /qos_test
端末 2 と端末 3 に何が出るかを見て、表の A(端末 2)と B(端末 3)の「結果」を書きます。何も出ないときは、黄色の警告が出ていないかも見てください。
結果を見る(予想を書き、自分で実行してから開く)
端末 2 の警告は「新しい送り手を見つけたが、QoS が合わない。この送り手からは何も受け取らない。合わなかったのは RELIABILITY」という意味です。トピック名 /qos_test も型 std_msgs/msg/String も合っているのに、1 つも届きません。
確かめたら、3 つの端末をすべて Ctrl+C で止めます。止めずに次へ進むと、best_effort の送り手が残ったままになり、C と D の結果が読めなくなります。
C と D を試す
今度は送る側を reliable にして、best_effort で受ける端末(C)と、reliable で受ける端末(D)を同時につなぎます。
# 端末 1(送る側:reliable)
ros2 topic pub --rate 2 --qos-reliability reliable /qos_test std_msgs/msg/String "{data: 'hello'}"
# 端末 2(受ける側:best_effort)
ros2 topic echo --qos-reliability best_effort /qos_test
# 端末 3(受ける側:reliable)
ros2 topic echo --qos-reliability reliable /qos_test
端末 2 が C、端末 3 が D の結果です。表の「結果」を書いたら、3 つの端末をすべて Ctrl+C で止めます。
結果を見る(予想を書き、自分で実行してから開く)
| 番号 | 結果 | 理由 |
|---|---|---|
| A | 届かない | 受ける側が「送り直してほしい」と求めているのに、送る側は送り直さない |
| B | 届く | どちらも送りっぱなしでよいと決めている |
| C | 届く | 送る側は送り直せるが、受ける側はそれを求めていない。求める以上のことをしてくれる相手とは組める |
| D | 届く | 受ける側が求める「送り直し」を、送る側が約束している |
受ける側が求めることを、送る側が約束していれば届きます。反対に、受ける側が送る側より多くを求めると届きません。#03 で「名前と型が合わないと届かない」ことを確かめました。QoS も、同じようにトピックの約束ごとの一部です。
実験 2 実物の /scan の QoS を読む
ロボットにつなぎます(手順は #07 の準備と同じです)。つないだら、robot-status でブリッジが動作中かを確かめ、その画面を回の頭の 1 枚として撮ります。ここでつながっていないと、このあとの実験で何も出ません。
robot-connect
robot-status
robot-connect は、IP を付けないと前回つないだ IP につなぎます。OLED の 2 行目の IP が前回と変わっていたら(ホットスポットを立て直したときなど)、robot-connect 192.168.137.134 のように IP を付けて打ちます。
PC から /scan の QoS を読みます。-v は「くわしく表示する」という指定で、これを付けると送り手・受け手ごとの QoS が出ます。予想(reliable か best_effort か)を書いてから実行してください。手がかりは、#04 の設計シートの説明で「センサーの値のように新しいものが次々に来るものは best effort にする」と書いたことです。
ros2 topic info -v /scan
出てくる QoS の行は、次のように読みます。
| 行 | 意味 |
|---|---|
Reliability | 実験 1 で試した届け方。RELIABLE か BEST_EFFORT |
History (Depth) | まだ渡していないデータを何件までためておくか。KEEP_LAST (10) なら、新しいほうから 10 件だけ残し、古いものは捨てる |
Durability | あとから来た受け手に、前に送ったデータを渡すかどうか。VOLATILE は渡さない(受け手がつないだあとのデータだけが届く) |
結果を見る(予想を書き、自分で実行してから開く)
PC から見える送り手はブリッジです。ロボットの中で本当に /scan を送っているノードの QoS は、ロボットの中で調べると、次のようになっていました(2026 年 9 月に測定)。
$ ros2 topic info -v /scan
Type: sensor_msgs/msg/LaserScan
Publisher count: 1
Node name: MS200
Node namespace: /
Topic type: sensor_msgs/msg/LaserScan
Endpoint type: PUBLISHER
QoS profile:
Reliability: RELIABLE
History (Depth): KEEP_LAST (10)
Durability: VOLATILE
LiDAR のノード MS200 も RELIABLE で送っています。
考える:センサーのデータを best_effort で受けるのはなぜか
ROS 2 では、センサーのデータは best_effort で送ったり受けたりすることがよくあります。次の回(#10)と第 5 週で使うサンプル scan_monitor も、/scan を best_effort で受けています。この LiDAR は RELIABLE で送っているのに、なぜ受ける側は best_effort にしておくのでしょうか。実験 1 の結果を使って考えてください。
考え方の例(自分の考えを書いてから開く)
- LiDAR は 1 秒に 10 回、新しい距離を測り直す。0.1 秒前のデータを送り直してもらっても、そのころにはもう新しいデータが届いている。センサーのデータは、古いものを確実に受け取るより、新しいものを早く受け取るほうが役に立つ。
- 実験 1 の C のとおり、
best_effortで受けるノードは、送り手がreliableでもbest_effortでも受け取れる。LiDAR を別の機種に替えて送り手の QoS が変わっても、そのまま動く。 - 反対に
reliableで受けるノードを書くと、best_effortで送る LiDAR からは何も届かない(実験 1 の A)。
実験 3 LiDAR の座標系をたどる
ロボットには、体の中心、LiDAR、カメラ、脚の関節など、たくさんの「基準の場所」があります。それぞれの場所に付けた座標系と、座標系どうしの位置関係をまとめて TF と呼びます。ROS 2 では、TF が /tf(脚のように動くもの)と /tf_static(LiDAR の取り付け位置のように動かないもの)の 2 つのトピックで流れています。
この実験は、次の順に進めます。
view_framesで、座標系のつながりを PDF の図にする- PDF を開き、
base_linkとlaser_frameの親子関係を読む tf2_echoで、LiDAR が体の基準からどこにあるかを数字で見る
座標系のつながりを図にする
作業用のフォルダを作って移動し、view_frames を実行します。5 秒間 TF を集めて、つながりを PDF に書き出します。view_frames は、コマンドを打った場所(いまいるフォルダ)にファイルを作るので、先に専用のフォルダへ移動しておきます。mkdir -p の -p は「すでにあってもエラーにしない」、&& は「左が成功したら、続けて右を実行する」という意味です(#04 の「4. ビルドして動かす」と同じ)。最後の ls で、PDF ができたかを確かめます。
mkdir -p ~/tf_check && cd ~/tf_check
ros2 run tf2_tools view_frames
ls
PDF は、ファイル マネージャーでダブルクリックするか、次のコマンドで開きます。atril は、この環境に入っている PDF を見るためのソフトです。* は「ここは何文字でもよい」という意味で、日付の部分を打たずに済みます。
atril frames_*.pdf
矢印は「親 → 子」の向きです。base_link(ロボットの体の基準)の子として、laser_frame、camera_link、imu_link、4 本の脚の付け根(lf_hip_link など)がつながっています。
laser_link という似た名前もあります。どれが /scan の座標系かは、データ自身に書いてあります(実験 6 で確かめます)。
atril を端末から開いている間、その端末は次のコマンドを受け付けません。PDF を読み終えたら、atril の窓を閉じてから次へ進みます。
LiDAR は体の中心からどこにあるか
2 つの座標系の位置関係を数字で見ます。打つ前に、机の上のロボットを見て、LiDAR が体のまん中から前・左・上のどちらへ何 cm くらいのところにあるかを予想してください。
tf2_echo は、1 つめの座標系(base_link)から見た 2 つめの座標系(laser_frame)の位置と向きを、くり返し表示し続けます。表示の中の Translation が位置で、3 つの数は x(前)、y(左)、z(上)の順、単位は m です。Rotation が向きです。数字が何回か出たら、Ctrl+C で止めます。
ros2 run tf2_ros tf2_echo base_link laser_frame
結果を見る(予想を書き、自分で実行してから開く)
[0.000, 0.000, 0.180] なので、LiDAR は体の基準からまっすぐ上に 18 cm の位置にあります。Rotation が回っていない値なので、LiDAR の向きは体と同じとして登録されています。
実験 4 RViz で /scan の点を表示する
RViz を起動します。
rviz2
rviz2 を打った端末は、RViz を閉じるまでほかのコマンドを受け付けません。RViz は実験 5 が終わるまで開いたままにし、実験 6 のコマンドは新しい端末で打ちます。
左の Displays パネルで、次の順に設定します。
- Global Options の Fixed Frame を
base_linkにする(表示の基準にする座標系)。 - 左下の Add を押し、By display type の中から RobotModel を選んで OK。Description Topic を
/robot_descriptionにする。 - 同じように Add から TF を追加する。
- Add から LaserScan を追加し、Topic を
/scanにする。Topic の左の三角を開き、Reliability Policy を実験 2 で読んだ QoS に合わせる。
点の色は、光がどれだけ強く返ってきたか(intensity)を表しています。距離ではありません。
LaserScan の Status がエラーになるとき
- Fixed Frame が
base_linkになっているか。つづりを 1 文字でも間違えると、点を置く場所が決められない。 robot-statusでブリッジが動作中か。- Reliability Policy を変えた直後は、表示されるまで数秒かかることがある。
RViz の設定は、File → Save Config As で保存しておくと、次の回に rviz2 -d ファイル名 で同じ表示から始められます。
実験 5 LiDAR の 0° はロボットの正面か
ロボットの正面、30 cm ほど先に箱を置き(LiDAR はロボットの背中の上にあるので、LiDAR より背の高い箱を使います。低い箱は点に出ません)、RViz のどこに箱の点が出るかを見ます。
TF の赤い矢印(base_link の x)の向きが、ロボットの正面です。箱の点が赤い矢印の先に出れば、LiDAR の 0° とロボットの正面は一致しています。
箱を置く前に、点が赤い矢印の先に出るかを予想してください。手がかりは、実験 3 の tf2_echo です。Rotation は「LiDAR の向きは体と同じ」として登録されていました。ただし、これは登録した値です。実物の LiDAR が本当にその向きで付いているかは、この実験で初めて分かります。
ずれていたときは、赤い矢印から左回りか右回りか、およそ何度かを読みます。時計の文字盤を上から見るつもりで、赤い矢印を 12 時とし、1 時間分(30°)を目安にするとおおよその角度を読めます。
| 記録すること | 結果 |
|---|---|
| 箱の点は、赤い矢印に対してどちらに出たか(先・左・右・後ろ) | |
| ずれていたら、およそ何度か |
この結果は第 5 週で使います。障害物をよける判断は「前にあるか」で決めるので、前がどちらかを間違えると、よけるつもりでぶつかりに行きます。
実験 6 データに付いている時刻と遅れ
/scan のメッセージには、中身の距離データとは別に、header(見出し)が付いています。RViz は開いたままで、新しい端末を開き、header だけを表示します。
ros2 topic echo /scan --field header
--field は、「メッセージ全部ではなく、この部分だけを表示して」という指定です。/scan は距離データが何百個も並ぶので、そのまま表示すると画面が流れてしまいます。中に入っているものの名前は、ros2 interface show sensor_msgs/msg/LaserScan で確かめられます。
何回分か表示されたら Ctrl+C で止め、同じ端末で PC の今の時刻を、header の stamp と同じ形で表示します。+%s.%N は、「1970 年 1 月 1 日からの秒数(%s)と、その秒の中の 10 億分の 1 秒の数(%N)を、点でつないで出して」という書式の指定です。
date +%s.%N
表示された header の中の frame_id が、実験 3 で tf2_echo に使った座標系と同じかを確かめてください。
結果を見る(予想を書き、自分で実行してから開く)
frame_id: laser_frameが、実験 3 で「データ自身に書いてある」と言った座標系です。stampが測った時刻です。secは 1970 年 1 月 1 日からの秒数、nanosecはその秒の中の 10 億分の 1 秒の単位です。- 続けて届いた stamp の差を見ると、0.956 → 1.156 → 1.356 秒のように約 0.2 秒ずつ進んでいます。PC に届く
/scanは 5 Hz でした(#07)。
最後の date との差は、Ctrl+C を押してコマンドを打つまでの時間も含むので、遅れの測定には使えません。遅れは次のコマンドで測ります。ros2 topic delay は、「PC が受け取った時刻 − ロボットが付けた stamp」を、届くたびに計算して平均します。何行か表示されたら Ctrl+C で止め、最後の行の平均(average delay)・最小(min)・最大(max)を書きます。
打つ前に、平均が #07 で測った往復の時間(latency_probe の平均、20 ms ほど)より大きいか小さいかを予想してください。手がかりは、stamp が「測った時刻」だということです。測ってから PC に届くまでに、どんな段階を通るかを考えます。
ros2 topic delay /scan
結果を見る(予想を書き、自分で実行してから開く)
ロボットの中で同じコマンドを実行した結果はこうでした(2026 年 9 月に測定)。
$ ros2 topic delay /scan
average delay: 0.100
min: 0.099s max: 0.102s std dev: 0.00124s window: 9
average delay: 0.100
min: 0.099s max: 0.102s std dev: 0.00122s window: 19
(中略)
average delay: 0.100
min: 0.098s max: 0.102s std dev: 0.00129s window: 69
ロボットの中で受け取っても、約 0.1 秒の遅れがあります。
| 測ったもの | 値 |
|---|---|
往復にかかる時間(#07 の latency_probe) | 平均 18.1 ms |
ros2 topic delay /scan(ロボットの中) | 平均 0.100 秒 |
ros2 topic delay /scan(PC) | 平均 0.214 秒 |
本質の問い
授業の最後に、次の 2 つに答えてください。
/scanの 1 つの点について「その点はロボットのどこにあるか」を答えるには、どんな情報が必要か。3 つ挙げ、それぞれ今日どのコマンドで見たかも書く。- PC で測った
ros2 topic delayの平均(0.2 秒ほど)は、#07 の往復時間(20 ms ほど)よりずっと大きい。どこで差が生まれていそうか。考えられることを 2 つ以上書く。
1 つめの手がかりは、実験 3(座標系)と実験 6(header)です。2 つめは、ロボットの中で測った delay(約 0.1 秒)と PC で測った delay の差がどこから来たかを考えます。
考え方の例(答えを書いてから開く)
1 つめ:① その点の距離と角度(ranges の値と、何番目の点か)、② laser_frame と base_link の関係(TF。この LiDAR は 18 cm 上)、③ いつ測ったか(stamp)。ロボットが歩いていると、同じ距離と角度でも、測った時刻によって部屋の中での場所が変わります。
- ロボットの中ですでに約 0.1 秒ある。LiDAR が 1 回転するのにかかる時間(
scan_time、この LiDAR では約 0.1 秒)と近いので、1 回転を測り始めた時刻を stamp にして、測り終えてから送っていると考えると合う。 - 残りの 0.1 秒ほどは、ブリッジと Wi-Fi の区間。ロボット側のブリッジは
/scanを 10 Hz から 5 Hz に間引いていて、どの回を通すかでも遅れが変わりそう。 - PC とロボットの時計がずれていると、その分だけ delay が増えたり減ったりする。往復時間は PC の時計だけで測るので、時計のずれの影響を受けない。
つまずきやすい点
| 症状 | 見るところ |
|---|---|
ros2 topic echo に何も出ず、黄色の警告だけが出る | 警告の最後の「Last incompatible policy」。QoS の組み合わせ(実験 1 の A) |
view_frames の PDF に base_link しか出ない | robot-status でブリッジが動作中か。つないでから数秒待ってから実行する |
tf2_echo が「frame does not exist」と出し続ける | 座標系の名前のつづり。最初の数回はまだ TF が集まっていないだけのこともある |
| RViz に点が出ない | Fixed Frame のつづりと、LaserScan の Topic。Status の行を開くとエラーの理由が書いてある |
ros2 topic delay がマイナスや数秒になる | PC とロボットの時計がずれている。授業では自分で直そうとせず、先生に伝える。ひとりで学ぶ人は、PC とロボットの両方で date を実行して時刻を比べる |
まとめ
| 確かめたこと | わかったこと |
|---|---|
| QoS の組み合わせ(実験 1) | 名前と型が合っていても、受ける側が送る側より多くを求めると届かない |
| 実物の /scan(実験 2) | この LiDAR は RELIABLE で送っている。受ける側を best_effort にしておけば、送り手の QoS によらず受け取れる |
| 座標系(実験 3・4・5) | /scan は laser_frame で測っていて、laser_frame は base_link の 18 cm 上。0° が正面かは実物で確かめる |
| 時刻(実験 6) | データには測った時刻が付いている。受け取るまでの遅れは、ロボットの中の分とその先の分に分けて考える |
次の回は、今日表示した /scan を rosbag で記録し、ロボットにつながずに再生しながらノードを作ります。










