概要
ROS2をDocker上で動かして複数の端末間での通信を実現するまで、色々手間取ったのでその手順や発生した事象についてここに記す。
なお、ここではROS2 Jazzyを使用することを前提とする。
別のバージョンをセットアップする場合は適宜jazzyとなっているところを読み替えること。
環境構築手順
Raspberry Pi 4B
Raspbianのインストール
Raspberry Pi Imagerを使ってmicroSDカードにOSをインストールする。
今回はRaspberry Pi OS(Raspbian)をインストールする。1
(Ubuntu 24.04LTSを使用するつもりだったが後述する事象を回避するためにやむなく変更した)
Imagerを使えばwifiとかsshの設定は完了しているはずなので、あとはとりあえずupdate & upgradeを叩く。
sudo apt update
sudo apt upgrade
Dockerのインストール
下記のコマンドでDockerをインストールする。2
最新の方法があればそちらを使用するほうが良い。(今ならComposeは不要かも)
sudo apt install docker.io docker-compose
またdockerコマンドのたびにsudoを打たなくていいよう、管理者権限の設定をする。3
(前者はすでにあると言われたらスルーでOK)
sudo groupadd docker
sudo usermod -aG docker <ユーザー名>
Dockerコンテナ構築
ROS公式の手順に従いDocker Imageを持ってくる。4
ただしこの後demoプログラムをビルドしやすいよう、ros-coreではなくros-baseを持ってくる。
docker pull ros:jazzy-ros-base
コンテナを作る。その際、外部との通信がしやすいようホストOSと同じIPを使えるよう設定をする。また同様にメモリ共有も有効にする。さらにコンテナを触りやすいよう適当な名前を付ける。5今回は適当にrp4n1-1とした
これを実行するとコンテナの中に入る。
docker run --net host --ipc host --name rp4n1-1 -it ros:jazzy-ros-base
コンテナの内部で、動作確認用のデモ用プログラムをインストールする。6
またrosdep updateでaptのリポジトリを参照するようなので、事前にupdateをかける。
環境変数はすでに設定されているので省略。
またros2_wsは適宜好きな名前にするとよい。(ROS2前提ならwsだけでもいいかも)
$ cd ~
~$ apt update
~$ source /opt/ros/dashing/setup.bash
~$ sudo rosdep init
~$ rosdep update
~$ mkdir ros2_ws
~$ cd ros2_ws
~/ros2_ws$ mkdir src
~/ros2_ws$ cd src
~/ros2_ws/src$ git clone https://github.com/ros2/demos.git
~/ros2_ws/src$ cd demos
~/ros2_ws/src/demo$ git checkout jazzy
~/ros2_ws/src/demo$ cd ../..
~/ros2_ws$ rosdep install --from-paths src --ignore-src -r -y
~/ros2_ws$ colcon build
以上の手順が終わって動作確認出来たらコンテナを抜ける。
そして、コンテナを終了したのち環境を再利用しやすいようローカルのリポジトリにImageを追加する。7
イメージ名は仮に「kikukou/ros:jazzy-ros-demos」とした。(正確には<イメージ名:タグ>になっている)
docker commit rp4n1-1 kikukou/ros:jazzy-ros-demos
また、Zero 2Wに環境を移植するためイメージを圧縮して持ち運べる形にしておく。8
docker save -o image.tar kikukou/ros:jazzy-ros-demos
Raspberry Pi Zero 2W
Raspbianのインストール
Raspberry Pi 4Bと同じ。
その際、なんかapt upgrageがこけた。記事に従いルーターを再起動したらなんか直った。9
Dockerのインストール
Raspberry Pi 4Bと同じ。8
Dockerコンテナ構築
Raspberry Pi 4Bで構築したイメージを利用する。
(命令セットarm64のものなら多分同じようにできるはず)
scp等を用いて持ってきたイメージの圧縮ファイルを読み込む。
docker load -i image.tar
あとはraspberry Pi 4Bと同じようにrunすればOK。
Beelink MINI-S
Ubuntuのインストール
Ubuntu 24.04.1LTSのイメージをダウンロードしてくる。10
適当なUSBメモリにRufusあたりを使ってLiveUSBを作る。11
用意したPCにUSBメモリを挿して電源を入れる。LiveUSBが立ち上がったらOSをインストールする。
Dockerのインストール
Raspberry Pi 4Bと同じ。
Dockerコンテナ構築
ROS2の公式に従いコンテナを引っ張ってくる。12
docker pull osrf/ros:jazzy-desktop
コンテナを作る。その際、外部との通信がしやすいようホストOSと同じIPを使えるよう設定をする。また同様にメモリ共有も有効にする。さらにコンテナを触りやすいよう適当な名前を付ける。5今回は適当にn100n1-1とした。
これを実行するとコンテナの中に入る。
docker run --net host --ipc host --name n100n1-1 -it osrf/ros:jazzy-desktop
このイメージはすでにDemoプログラムがビルドされているので省略する。
コンテナ間通信テスト
Raspberry Pi 4B上で2つコンテナを建てて通信してみる。
1つ目のターミナルで以下を実行する。
docker run --net host --ipc host --name rp4n1-2 -it ros:jazzy-ros-base
コンテナに入ったら以下を実行。6
1つ目のコマンドは毎回うつのが面倒なら.bashrcあたりに記載しておくとよい。
source ~/ros2_ws/install/setup.bash
ros2 demo_nodes_cpp listener
2つ目のターミナルで以下を実行する。
docker run --net host --ipc host --name rp4n1-1 -it ros:jazzy-ros-base
コンテナに入ったら以下を実行。6
1つ目のコマンドは毎回うつのが面倒なら.bashrcあたりに記載しておくとよい。
source ~/ros2_ws/install/setup.bash
ros2 demo_nodes_cpp talker
これでtalkerから出したメッセージがlistenerで表示されてればOK。
端末間通信テスト
同じように端末間で通信する。
Raspberry Pi 4B上のターミナルで以下を実行する。
docker run --net host --ipc host --name rp4n1-1 -it ros:jazzy-ros-base
コンテナに入ったら以下を実行。6
1つ目のコマンドは毎回うつのが面倒なら.bashrcあたりに記載しておくとよい。
source ~/ros2_ws/install/setup.bash
ros2 demo_nodes_cpp listener
Raspberry Pi 4B上のターミナルで以下を実行する。
また、Raspberry Zewo 2W上のターミナルで以下を実行する。
docker run --net host --ipc host --name rpz2wn1-1 -it ros:jazzy-ros-base
コンテナに入ったら以下を実行。6
1つ目のコマンドは毎回うつのが面倒なら.bashrcあたりに記載しておくとよい。
source ~/ros2_ws/install/setup.bash
ros2 demo_nodes_cpp listener
Beelink MINI-S上のターミナルで以下を実行する。
docker run --net host --ipc host --name n100n1-1 -it ros:jazzy-ros-base
コンテナに入ったら以下を実行。6
ros2 demo_nodes_cpp talker
これでtalkerから出したメッセージがlistenerで表示されてればOK。
なおtalkerとlistenerを色々入れ替えても動く。
ただし、talkerとlistenerがどちらもwifiのみで接続されている場合、メッセージをlistenerが受け取れない。(今後解消が必要なら調査する予定)
端末間通信の失敗とその対策
発生事象
最初にRaspberry Pi 4BへUbuntuServer 24.04LTS、Beelink MINI-SへUbuntu 24.04LTSをそれぞれインストールし、Docker上で環境を構築して端末間通信テストをした際、上手くトピックの送受信ができなかった。また、マルチキャストの通信もうまくいかなかった。
対策1
ファイアウォールをすべて無効化、無線接続とした結果、マルチキャストでの通信はできるようになったが、トピックの送受信に関する事象は解決しなかった。マルチキャストを用いたデータの送受信ができることはpythonでコードを書いて確認した。その際のコードは以下のリポジトリに配置した。
またこの時、tcpdumpコマンドを用いてパケットを確認したところ、対向の端末からのUDPパケット及びマルチキャストのUDPパケットが届いていることが確認できた。また同じネットワーク上にあるWindows端末でWireSharkを用いてパケットを確認したところ、通信開始及び終了時にIGMPv3パケットが出力されていないことが確認できた。
上記のことから、通信開始のコネクションが上手くできていないことが原因と考えられる。
対策2
下記のリンクの対策を試したが効果が無かった。
対策3
異なるOSを持ってきてOSの再インストールを実施した。(本記事の環境構築)
⇒事象が改善した。
詳しい原因は不明なままだが、正常に動作するようになったため詳しい原因の追究は実施していない。
まとめ
色々あったが、とりあえずROS2 on Dockerで複数の端末間で通信できる環境を構築することができた。
wifiのみでの通信に関してはルーターの問題もありそうなので、時間があればもう1台端末を用意して自作ルーターを建てて調査をしてみようかと思う。