DDS 通信の仕組みを整理
ROS2 Humble で環境構築を進めている際,ノード同士が通信できない問題に遭遇した.調べてみると,原因は DDS の不一致にあった.
ROS2 初学者にとって,DDS はブラックボックスになりがちだが,DDS の仕組みと選び方を理解することは,通信トラブルの解決に直結する.
筆者はROS2を使い始めて半年ほどの未熟者なので間違いがあった際にはご指摘をお願いいたします.お手柔らかに.
はじめに
ROS2通信の中心にあるのが DDS (Data Distribution Service) である.
この記事では以下の4点を順を追って解説する.
- ROS 2 通信の内部構造
- DDS とは何か
- 使用しているDDSを確認する方法
- DDSを切り替える方法
1. ROS2 通信の内部構造
ROS2通信を行うための通信レイヤは以下のように構造化されている。
| レイヤ | 役割 |
|---|---|
| rclcpp / rclpy | ユーザが使う ROS 2 ノード・Publish/Subscribe API |
| rcl (ROS 2 Client Library) | 言語差を吸収する C ベース共通インターフェース(C層) |
| rmw (ROS Middleware Interface) | DDS などのミドルウェアを隠蔽する抽象化レイヤ |
| DDS ミドルウェア | Fast DDS / Cyclone DDS / Connext などの実際の通信エンジン |
| UDP/TCP/IP | OSのネットワーク通信 |
ROS2 で publish() が呼ばれたとき、内部では次のように処理が進む。
1. rclcpp / rclpy(ユーザー層)
ユーザーはC++やPythonでプログラムを書いて実行する.
2. rcl(C層)
rclcpp / rclpy層で実行された出力は言語によって異なるが,その言語差を吸収し、rmw へ橋渡しをする。この層はC++で実装してもPythonで実装してもROS2を使用できるようにするための層といえる.
3. rmw
DDS 実装に依存しない抽象化レイヤである.のちに記載するがDDSも rclcpp / rclpy 層でプログラミング言語を選べるのと同じように選択することができる.そのDDSの差を吸収する層である.
4. DDS ミドルウェア
rmw層で生成された出力をネットワークで送受信できる形式に変換し、ネットワーク層(UDP/TCP)へ渡す役割を担う。
5. ネットワーク層(UDP / TCP)
OS が最終的なデータ通信を担当する。
ROS2の通信構造が明らかになったので,以降は DDS 通信について深堀りする.
2.DDSとは何か
DDSは、ROS2 の通信の心臓部となる層であり,Pub/Sub通信の基盤処理を行っている.具体的には,ノードの相互発見(Discovery)をしたり,QoS(Quality of Service)の適用,つまり通信ルールの適用をしたりしている.
余談だが,ROS2はROS1とは違い中央管理サーバ不要の分散型通信を実現している.この変更の根幹をなしているのはDDSである.
先ほども述べたが,DDS ミドルウェアには複数の種類があり,ROS2 は標準で以下をサポートしている.
-Fast DDS(eProsima)
-Cyclone DDS(Eclipse Foundation)
-Connext DDS(RTI)
-GurumDDS(Gurum Networks)
通信品質や安定性は DDS の性能に大きく左右される.通信のニーズによって変更する必要がある.よくある例として,既製品を自分の環境と通信して動かすときには,自分のROS2環境のDDSを変更する必要がある.
3.使用しているDDSを確認する方法
例えば,ROS2を使用しているPCと複数台やり取りするとき,PCによってDDSが異なると不具合やエラーの原因になる.そのため,使用するDDSを統一することが望ましい.
まずは,現在使用しているDDSの確認をしてみよう.ROS2を使えるように
source /opt/ros/${DISTRO}/setup.bash
をしたうえで,以下のコマンドで、現在使用している DDSを確認できる。
ros2 doctor --report
ちなみに,ROS2の各ディストリビューション(Foxy, Hubmle, Jazzy)では,いずれも eProsima’s Fast DDS がデフォルトである.
4. DDSを切り替える方法
DDSを変更するためにはLinuxの環境変数であるRMW_IMPLEMENTATIONを変更すればよい.
例えば,Cyclone DDSを使用したいとき,以下の手順を踏めばよい.
まず初めに,適当な場所にcyclonedds_wsを作る.
mkdir -p ~/cyclonedds_ws/src
次に,cycloneddsのgitからgit clone をしてビルドする.branchは適宜変更する必要がある(下記はhumbleを指定).
cd ~/cyclonedds_ws/src
git clone https://github.com/ros2/rmw_cyclonedds.git -b humble
環境変数を設定すれば完了.
source ~/cyclonedds_ws/install/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
以上を実施したうえで再度,DDSを確認すればcycloneddsが使用できていることが確認できるだろう.永続化したい場合には~/.bashrcに記載する.
最後に
今回は,主題をDDSにおいて初心者にはブラックボックスとされがちなROS2の通信の内部構造について触れた. 今後もROS2に詳しくなりたいと思う.