ROS 2とミドルウェア
ROS 2のプログラムの構成と接続の仕組み。ノードグラフ、パラメータ、ローンチとtf2、DDSとZenohを含むrmw層、メッセージを黙って遮断するQoSの規則、ros2_control、micro-ROS、現行のディストリビューションを扱います。
概要
ROS 2はオペレーティングシステムではありません。型付きのメッセージをやり取りするプロセスのグラフとしてロボットソフトウェアを構築するための、ライブラリ・ツール・規約の集まりです。その下にはミドルウェア層があり、ディスカバリと通信を担います。デフォルトのミドルウェアはDDSです。ドライバからMoveIt 2やNav2まで、オープンなロボットソフトウェアの大半はROS 2を前提にしています。このハブは、初めてノードを書くエンジニアや、より大きなシステムの構成を決めようとしているエンジニア向けです。当サイトのコードはROS 2 Jazzy Jalisco(LTS、2024年5月)でテストしています。
重要な考え方
グラフ:ノード・トピック・サービス・アクション
ノードは、カメラドライバやプランナのような1つの計算単位です。ノード間の通信方法は3つあります。トピックは匿名のパブリッシュ・サブスクライブです。パブリッシャもサブスクライバも任意の数を持てますが、メッセージ型は1つです。センサのストリームや状態の配信に向きます。サービスはリクエストとレスポンスの組で、「この地図を読み込む」のような短い呼び出しに使います。アクションはフィードバックとキャンセルを備えた長時間実行のゴールで、「この位置姿勢まで移動する」のような用途に使います。内部はトピックとサービスで構成されています。各ノードは型付きのパラメータも持ち、起動時に設定することも、実行中に変更することもできます。ローンチファイルはPython、XML、YAMLのいずれかで書き、多数のノードをまとめて起動・設定します。tf2はタイムスタンプ付きの座標系のツリーを保持します。そのため、どのノードからでも、任意の時刻における2つの座標系間の変換を問い合わせられます。
ミドルウェア・ディスカバリ・QoS
ROS 2はrmwインターフェースを通じてミドルウェアにアクセスします。Lyricalのサポート対象プラットフォームのページによれば、ROS 2 Lyrical Luthのデフォルト実装はrmw_fastrtps_cpp(eProsima Fast DDS)で、Cyclone DDS、RTI Connext、ZenohもTier 1です。DDSには中央のマスタがありません。ノードはネットワーク上で互いを発見し、同じネットワークを共有するグループはROS_DOMAIN_IDで分離します。Zenohでは、代わりにルータがディスカバリを担います。
すべてのパブリッシャとサブスクライバはQoSプロファイルを持ちます。その項目は、信頼性(reliable または best effort)、耐久性(volatile または transient local)、履歴の深さ、デッドライン、ライブネスです。両端のQoSに互換性がないと、接続は確立されません。ログに警告が出るだけで、メッセージは届きません。reliableのサブスクライバは、best effortのパブリッシャからのデータを受け付けません。これが、センサドライバからノードが「何も受信しない」典型的な原因です。次のコードはJazzyのコンテナで動作し、この現象を示します。
# ros2
import rclpy
from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy
from std_msgs.msg import Int32
def count_received(pub_rel: ReliabilityPolicy, sub_rel: ReliabilityPolicy) -> int:
node = rclpy.create_node("qos_demo")
pub_qos = QoSProfile(depth=10, history=HistoryPolicy.KEEP_LAST, reliability=pub_rel)
sub_qos = QoSProfile(depth=10, history=HistoryPolicy.KEEP_LAST, reliability=sub_rel)
received = []
pub = node.create_publisher(Int32, "counter", pub_qos)
node.create_subscription(Int32, "counter", lambda msg: received.append(msg.data), sub_qos)
for i in range(40):
pub.publish(Int32(data=i))
rclpy.spin_once(node, timeout_sec=0.05)
node.destroy_node()
return len(received)
rclpy.init()
matched = count_received(ReliabilityPolicy.BEST_EFFORT, ReliabilityPolicy.BEST_EFFORT)
mismatched = count_received(ReliabilityPolicy.BEST_EFFORT, ReliabilityPolicy.RELIABLE)
rclpy.shutdown()
print(f"best effort -> best effort: received {matched > 0}")
print(f"best effort -> reliable: received {mismatched} messages")
2つ目のケースは0を出力し、信頼性ポリシーについて互換性のないQoSの警告をログに出します。耐久性も重要です。tf2_rosの静的ブロードキャスタは/tf_staticをtransient localの耐久性でパブリッシュします。そのため、遅れて起動したノードもすべての静的変換を受信できます。
ros2_controlとmicro-ROS
ros2_controlはコントローラとハードウェアを分離します。そのコントローラマネージャは、各コントローラが必要とするコマンドインターフェースと状態インターフェースを、各ハードウェアコンポーネントが提供するものと照合し、競合があればエラーを報告します。ハードウェアはロボットのURDFに記述します。これにより、ros2_controllersリポジトリの同じコントローラを、実機のアーム、シミュレータ、モックのいずれに対しても動かせます。micro-ROSは、rclをベースにしたC APIを通じて、ノード、パブリッシュ・サブスクライブ、サービス、ライフサイクルをマイコン上で使えるようにします。通信にはeProsima Micro XRCE-DDSを使い、より大きなコンピュータ上のエージェントがROS 2グラフの残りの部分との橋渡しをします。FreeRTOS、Zephyr、NuttXに対応しています。
ディストリビューション
ROS 2の新しいディストリビューションは毎年5月にリリースされます。ROS 2のリリーススケジュールによれば、偶数年のリリースはLTSで約5年間、奇数年のリリースは1.5年間サポートされます。2026年11月14日時点で、ROS 2のディストリビューションのページには次のサポート対象リリースが掲載されていました。
| ディストリビューション | リリース日 | サポート終了 | 備考 |
|---|---|---|---|
| Lyrical Luth | 2026年5月22日 | 2031年5月 | LTSで最新のリリース。Ubuntu 26.04とWindows 11でTier 1 |
| Kilted Kaiju | 2025年5月23日 | 2026年12月 | 非LTS |
| Jazzy Jalisco | 2024年5月23日 | 2029年5月 | LTS。Ubuntu 24.04でTier 1。当サイトのコードで使用 |
| Humble Hawksbill | 2022年5月23日 | 2027年5月 | LTS |
| Rolling Ridley | 継続的 | なし | 開発用ディストリビューション |
Lyricalでは、macOSはTier 3プラットフォームです。つまり、ソースからのビルドが必要です。Macでは、Linuxのコンテナまたは仮想マシン上でROS 2を実行してください。
どこから始めるか
Hello ROS 2では、パブリッシャとサブスクライバを書き、Jazzyのコンテナで実行します。ROS 2のtalker・listener・tf2プロジェクトでは、パラメータ、ローンチ、変換を加えます。作業中はROS 2 CLIチートシートを開いておいてください。ロボットの記述についてはURDFとMJCFのリファレンスを参照してください。主なパッケージはROSのプラットフォームページに一覧があります。
ツールとプラットフォーム
| ツール | 用途 | ライセンス |
|---|---|---|
| rclpy・rclcpp | PythonとC++のクライアントライブラリ | Apache-2.0 |
| Fast DDS | デフォルトのDDS実装 | Apache-2.0 |
| Cyclone DDS | 代替のDDS実装 | EPL-2.0またはEDL-1.0 |
| rmw_zenoh | ROS 2向けのZenohベースのミドルウェア | Apache-2.0 |
| ros2_control | コントローラマネージャとハードウェア抽象化 | Apache-2.0 |
| micro-ROS | マイコン上のROS 2 | Apache-2.0 |
| RViz・rosbag2 | 3D可視化、および記録と再生 | BSD-3-Clause-Clear、Apache-2.0 |
| SROS2 | セキュリティツール(鍵、証明書、アクセス制御) | Apache-2.0 |
よくある間違い
- ドライバとサブスクライバの間でQoSが一致していない。
ros2 topic info -vで確認する。 - 同じネットワーク上の2台のロボットが同じ
ROS_DOMAIN_IDを使い、互いのトピックが見えてしまう。 - コールバック内でブロックする。シングルスレッドのエグゼキュータでは、他のすべてのコールバックが止まる。
- 誤ったタイムスタンプで変換をパブリッシュし、tf2の問い合わせが失敗するか外挿になる。
- マシン間でディストリビューションを混在させる。メッセージが一致しないことがある。
- 何年も稼働し続ける必要がある製品を、非LTSリリースで構築する。
さらに深く
- Macenski, Foote, Gerkey, Lalancette, Woodall、Robot Operating System 2: Design, architecture, and uses in the wild、Science Robotics、2022年。
- ROS 2のディストリビューションのページ、リリーススケジュールのソース、REP 2000のROS 2 Releases and Target Platforms。
- Object Management GroupのDDS仕様、バージョン1.4。
- ros2_controlのドキュメントとmicro-ROSのドキュメント。
- ROS 2の設計記事。システムがなぜ現在の形になっているかを説明している。