ROS2でホスト間かつDockerコンテナ間で通信したい

## はじめに - 経緯あるいは要望

ROS/ROS2に触れたことのない私が、ホスト間かつコンテナ間でROS2ノード同士の通信をする必要にかられて今なお苦しんでいるお話です。
ホスト間かつ Docker コンテナ間で ROS2 ノード同士の通信をするという目標はまだ達成できていません。

タイトルにつられて訪問した方にはタイトル詐欺になっているかもしれません。
各種ホスト・環境の構成や設定は記載するので、単一ホスト・環境に ROS2 をインストールして使いたい方には必要な情報へのポインターになるかもしれません。

あるとき Autoware Open AD Kit を動かしてみようとしました。

https://autowarefoundation.github.io/open-ad-kit-docs/latest/version-2.0/start-guide/installation/

![スクリーンショット 2024-07-23 10.29.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601257/3aa3be87-fc8b-2c65-0976-d45adcb9cbd7.png)

手持ちの Windows PC (x86) と M1 Mac (ARM) で。
だってx86ホストとARMホストで通信する図が載ってるじゃないですか。
……ぜんぜん動きません。
もう少し正確に言うと各ホスト上でコンテナは動きますが通信できません。

確かに Minimum requirements は守ってないし。
「このドキュメントは Open AD Kit version 1.0 から持ってきたもので 2.0 用に更新が必要」とか書いてあるし。
それにしても ROS2 でホスト間コンテナ間で通信するってそんなに難しいの？
と思って意地になって、各種ホスト・環境間の ROS2 通信可否を調べました。

最初の目的はコンテナ上の ROS2 ノード同士で通信させることでしたが、
なかなか疎通できないのでホストで直接 ROS2 ノードを動かすケースも調べました。


### 調べたこと

- Windows (Intel x86 PC), MacBook, Raspberry Pi 4, Raspberry Pi 5 など各種ホストに ROS2 をインストールし、
- ホスト上で直接、または Docker コンテナで ROS2 ノードを動かし、
- 各種ホスト・環境間での通信可否を調べました。


### まだ試してないこと

- クラウド上のホスト（AWS EC2 と Transit Gateway でホスト間通信できたという情報は同僚から聞いています）
- 他のバージョンでの動作確認
- 家庭内LAN・ルーター以外のネットワークでの動作確認


## Autoware Open AD Kit

Autoware Open AD Kit は自動運転を開発するためのオープンソースソフトウェアです。
シミュレーションが動くデモを手持ちのPCで動かしたかったのですが、動かないのを調査していたら ROS のホスト間コンテナ間通信の沼で迷っていました。

https://autowarefoundation.github.io/open-ad-kit-docs/latest/version-2.0/

https://github.com/autowarefoundation/autoware-projects/wiki/Open-AD-Kit-working-group


## ROS/ROS2

ROS はロボットアプリケーション開発するためのオープンソースソフトウェアです。
コンテナで ROS を動かしている人は世の中にたくさんいますし、複数ホスト間で通信させている人もいるようです。
複数ホスト（非コンテナ）間通信であれば私も再現できています。
ですが、複数ホストのコンテナ間で通信させるのでこんなにハマるとは予想していませんでした。
（動くパターンもあるという情報は聞いていますが私はまだ再現していません）

https://www.eureka-box.com/media/column/a33

https://qiita.com/koichi_baseball/items/b15783ced5df8d5e56a6

https://hajimerobot.co.jp/ros/ros2_install/

https://qiita.com/srs/items/5f0d765343ca78f524ed

ROS/ROS2 と Ubuntu の対応バージョンの組み合わせは決まっています。
ROS2　の使用バージョンが決まっているなら Ubuntu のバージョンを合わせる必要があり、 Ubuntu の使用バージョンが決まっているなら ROS2 のバージョンを合わせる必要があります。

| ROS2 バージョン | Ubuntu 対応バージョン |
|---|---|
| ROS2 Jazzy LTS | Ubuntu 24.04 LTS (Noble Numbat) |
| ROS2 Iron | Ubuntu 22.04 LTS (Jammy Jellyfish) |
| ROS2 Humble LTS | Ubuntu 22.04 LTS (Jammy Jellyfish) |
| ROS2 Galactic (EOL) | Ubuntu 20.04 LTS (Focal Fossa) |
| ROS2 Foxy LTS (EOL) | Ubuntu 20.04 LTS (Focal Fossa) |


バージョンの組み合わせをまとめているサイトもありますが、
最新状況は公式サイトを見るのが良いでしょう。
例えば現時点で最新LTSバージョンの ROS2 Jazzy Jalisco のドキュメントには以下のように書かれています。

https://docs.ros.org/en/jazzy/Installation.html

![スクリーンショット 2024-08-28 15.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601257/6170b7cb-ac15-d6d9-f2e5-83f15c0abf4b.png)

見逃しがちですが、この画面の左下に他のバージョンへのリンクがあります。
他のバージョンの対応を見るときはここからたどると良いでしょう。

![スクリーンショット 2024-08-28 15.11.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601257/f4e9f08a-b847-152f-9cee-e3313b8ddd17.png)

余談ですが、いま私が「ROS Mac install」でググると ROS2 Crystal のドキュメントが最上位に出てきます。
ROS2 Crystal は EOL (End Of Life) となっており、対応 Ubuntu バージョンは 16.04 または 18.04 となっています。
古すぎて辛いですね。
私はこれで Google 検索を無条件に信頼する無邪気な純真さを失いました。
ROS 公式サイトが SEO に手が回ってないのだろうと察しますが。

ROS2 Crystal, Dashing, Eloquent, Foxy は macOS へのソースとバイナリの両方のインストールドキュメントがありますが、Galactic, Humble, Iron, Jazzy では macOS へソースからのインストールしかドキュメントがありません。
Mac へのバイナリインストールのサポートは止められたようです。



## ホスト間通信を妨げる落とし穴たち

### ufw, ファイアウォール

`sudo ufw allow 11311` としてポートを許可する設定は ROS1 向けのものです。
ROS1 はマスターノードがポート 11311 で待ち構えていてその他のノードはマスターノードにつなげることで通信できました。
ROS2 ではマスターノードは不要となり IGMP で他ホストのノードを自動的に探します。
IGMP は L3 のプロトコルなのでポート番号では制御できません。

https://panasonic.co.jp/ew/pewnw/product/column/008.html

結論： ufw は無効化 (`sudo ufw disable`) しました。

NOTE: 私はまだ試していませんが、ufw で IGMP を許可する方法はありそうです。

https://einar.slaskete.net/2014/05/03/allow-multicast-and-igmp-with-ufw-for-iptv-to-work/



### Docker Desktop

https://docs.docker.com/engine/network/drivers/host/#limitations

![スクリーンショット 2024-08-30 9.35.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601257/b091caff-6ab0-e443-0b2a-73df89e14be3.png)

Docker Desktop の host ネットワークは L4 で動くので、TCP や UDP より下のプロトコルである IGMP はサポートされません。

Docker Desktop ではなく、Docker Community Edition を使いましょう。



## 各環境の構成と設定

### Mac, Docker Desktop, XQuartz で Open AD Kit を動かす

| 構成 | 備考 |
|---|---|
| MacBook Pro | M1 Max チップ, 64GB メモリ |
| macOS Sonoma 14.6.1 |
| Docker Desktop 4.32.0 | Docker Engine v27.0.3 |
| XQuartz 2.8.5 |
| Autoware Open AD Kit | `ces-demo`ブランチ, containers と visualizer　イメージ |

https://docs.docker.jp/desktop/install/mac-install.html

```shell-session:ターミナルで Open AD Kit containers を実行
$ git clone https://github.com/autowarefoundation/open_ad_kit.git
$ cd open_ad_kit/docker/autoware-openadk/
$ ./run-containers.sh
#### simulator と planning-control が動きます。
```

```shell-session:別のターミナルで Open AD Kit visualizer を実行
$ cd open_ad_kit/docker/autoware-openadk/
$ ./run-visualizer.sh
#### Docker Desktop のエミュレーション機能で x86_64 イメージが動きますが、
#### Mac に X Server を入れていないので異常終了します。
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
qt.qpa.xcb: could not connect to display 
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.

/autoware/scenario-sim/rviz/launch_rviz.sh: line 3:    65 Aborted    rviz2 -d /autoware/scenario-sim/rviz/scenario_simulator_v2.rviz
```

https://www.docker.com/ja-jp/blog/multi-arch-images/

Mac 用の X Server として XQuartz 2.8.5 をダウンロード、インストールします。

https://www.xquartz.org/

XQuartz > 設定 > セキュリティ のタブで、接続を認証 と ネットワーク・クライアントからの接続を許可 の両方にチェックをつけて、XQuartz を再起動します。

![スクリーンショット 2024-08-29 18.07.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601257/99166389-beaa-a51b-186d-ed0b77188013.png)

```shell-session:別のターミナルで Open AD Kit visualizer を実行 の続き
$ xhost + 192.168.xx.xx
#### Mac ホストの IP アドレスから XQuartz への接続を許可します。

$ ./run-visualizer.sh
#### RViz のウィンドウは見えないのですが、何かが動いています。
```


### Mac, Lima

| 構成 | 備考 |
|---|---|
| MacBook Pro | M1 Max チップ, 64GB メモリ |
| macOS Sonoma 14.6.1 |
| Lima　0.22.0 |
| XQuartz 2.8.5 |
| Autoware Open AD Kit | `ces-demo`ブランチ, containers と visualizer　イメージ |

Mac で Docker Desktop ではなく Lima を使ってコンテナを起動します。

https://zenn.dev/matsukaz/articles/31bc31ff1c54b4

https://qiita.com/runeleaf/items/69f7ee6dedcc5dfb7b9e

ROS2 が動いてデスクトップ接続もできるコンテナイメージを使わせていただきます。

https://github.com/Tiryoh/docker-ros2-desktop-vnc/wiki

```shell-session:Macのターミナル
$ brew install lima
$ limactl --version
limactl version 0.22.0
$ curl -O https://raw.githubusercontent.com/lima-vm/lima/master/examples/docker.yaml
$ limactl start docker.yaml
$ limactl list
$ ln -nfs ~/.lima/docker/sock/docker.sock ~/.docker/run/docker.sock
$ docker version
$ docker run --net=host --security-opt seccomp=unconfined --shm-size=512m tiryoh/ros2-desktop-vnc:humble
```

```shell-session:Macの別のターミナル
$ docker exec -it ros2-desktop-vnc bash
# sudo su - ubuntu
$ ros2 run demo_nodes_cpp talker --ros-args --remap __node:=lima_talker
$ ros2 run demo_nodes_cpp listener --ros-args --remap __node:=lima_listener
```
コンテナ内で送信したメッセージをコンテナ内で受信することができます。

```shell-session:Macの別のターミナル
$ conda activate ros_env
$ ros2 run demo_nodes_cpp listener --ros-args --remap __node:=mac_listener
$ ros2 run demo_nodes_cpp talker --ros-args --remap __node:=mac_talker
```
コンテナ内で送信したメッセージをMacホストで受信できません。
Macホストで送信したメッセージをコンテナ内で受信することもできません。
ネットワークの設定がまずいのでしょうか。

https://qiita.com/shunk_jr/items/0ebe96b8ea8f4c93f82b

https://lima-vm.io/docs/config/network/

こちらを試してみます。

```shell-session:Macのターミナル
$ limactl list
NAME      STATUS     SSH                CPUS    MEMORY    DISK
docker    Running    127.0.0.1:60467    4       4GiB      100GiB
$ limactl stop docker
$ limactl delete docker
$ diff -u docker.yaml
 # This template requires Lima v0.8.0 or later
+vmType: "vz"
+networks:
+- vzNAT: true
 images:
$ limactl start docker.yaml 
$ docker run --net=host --security-opt seccomp=unconfined --shm-size=512m tiryoh/ros2-desktop-vnc:humble
```
これで試してもやはりホストとコンテナの間では通信できませんでした。



### Mac ホストで ROS2 Humble を動かす

| 構成 | 備考 |
|---|---|
| MacBook Pro | M1 Max チップ, 64GB メモリ |
| macOS Sonoma 14.6.1 |
| XQuartz 2.8.5 |
| ROS2 Humble |

Mac ホスト環境を汚すのは避けたかったのですが、Docker でホスト間の疎通確認ができないので仕方ありません。
Mac に直接 ROS2 をインストールして疎通してみます。
ROS 公式サイトにソースからのビルド・インストール方法は載っていますが、Qiita の記事で一つ前の LTS バージョンである ROS2 Humble をバイナリインストールする方法が解説されているのでそちらを使います。

https://docs.ros.org/en/jazzy/Installation/Alternatives/macOS-Development-Setup.html

https://qiita.com/Nyanziba/items/d84211e8e9d9654c6253

```shell-session:ターミナル
$ mkdir -p ~/miniconda3
$ curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o ~/miniconda3/miniconda.sh
$ bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
$ rm -rf ~/miniconda3/miniconda.sh
$ ~/miniconda3/bin/conda init bash
$ ~/miniconda3/bin/conda init zsh
$ conda install mamba -c conda-forge
$ mamba init zsh
$ conda create -n ros_env
$ conda activate ros_env
$ conda config --env --add channels conda-forge
$ conda config --env --add channels robostack-staging
$ conda config --env --remove channels defaults
$ conda install ros-humble-desktop
$ conda deactivate
$ conda activate ros_env
$ conda install compilers cmake pkg-config make ninja colcon-common-extensions catkin_tools
$ rviz2
```
macOS で RViz2 が動きました。

```shell-session:別のターミナル
$ conda activate ros_env
$ rqt_graph
```
macOS で rqt_graph が動きました。

```shell-session:また別のターミナル
$ conda activate ros_env
$ git clone https://github.com/autowarefoundation/open_ad_kit.git
$ rviz2 -d open_ad_kit/docker/autoware-openadk/etc/simulation/rviz/scenario_simulator_v2.rviz
[INFO] [1721888082.392052032] [rviz2]: Stereo is NOT SUPPORTED
[INFO] [1721888082.392117990] [rviz2]: OpenGl version: 2.1 (GLSL 1.2)
[INFO] [1721888082.447662237] [rviz2]: Stereo is NOT SUPPORTED
[ERROR] [1721888082.588325781] [rviz2]: PluginlibFactory: The plugin for class 'rviz_plugins/SteeringAngle' failed to load. Error: According to the loaded plugin descriptions the class rviz_plugins/SteeringAngle with base class type rviz_common::Display does not exist. Declared types are  rviz_default_plugins/AccelStamped rviz_default_plugins/Axes rviz_default_plugins/Camera rviz_default_plugins/DepthCloud rviz_default_plugins/Effort rviz_default_plugins/FluidPressure rviz_default_plugins/Grid rviz_default_plugins/GridCells rviz_default_plugins/Illuminance rviz_default_plugins/Image rviz_default_plugins/InteractiveMarkers rviz_default_plugins/LaserScan rviz_default_plugins/Map rviz_default_plugins/Marker rviz_default_plugins/MarkerArray rviz_default_plugins/Odometry rviz_default_plugins/Path rviz_default_plugins/PointCloud rviz_default_plugins/PointCloud2 rviz_default_plugins/PointStamped rviz_default_plugins/Polygon rviz_default_plugins/Pose rviz_default_plugins/PoseArray rviz_default_plugins/PoseWithCovariance rviz_default_plugins/Range rviz_default_plugins/RelativeHumidity rviz_default_plugins/RobotModel rviz_default_plugins/TF rviz_default_plugins/Temperature rviz_default_plugins/TwistStamped rviz_default_plugins/Wrench
```
Open AD Kit visualizer 相当のコマンドを実行してみると RViz2 が起動しましたが、
真っ黒な画面で何が動いているのか分かりません。

```shell-session:ターミナルで talker を動かす
$ conda activate ros_env
$ ros2 run demo_nodes_cpp talker
[INFO] [1722581932.923304764] [talker]: Publishing: 'Hello World: 1'
...
```

Macホストで talker が動きました。

```shell-session:別のターミナルで listener を動かす
$ conda activate ros_env
$ ros2 run demo_nodes_cpp listener
[INFO] [1722581962.922649664] [listener]: I heard: [Hello World: 31]
...
```

Macホスト内で talker のメッセージを listener が受信できました。

```shell-session:また別ターミナル
$ conda activate ros_env
$ ros2 node list
/listener
/talker

$ rqt_graph
```

listener, talker の2ノードと chatter 1トピックの接続グラフが表示されます。




### Windows, Docker Desktop で Open AD Kit を動かす

| 構成 | 備考 |
|---|---|
| DELL Latitude 5530 | Intel i7-1265 CPU, 16GB RAM |
| Windows 10 Enterprise |
| Docker Desktop 4.33.0 | Docker Engine v27.1.1 |
| Autoware Open AD Kit | `ces-demo`ブランチ, containers と visualizer　イメージ |

https://docs.docker.jp/desktop/install/windows-install.html

```shell-session:コマンドプロンプトで Open AD Kit containers を実行
> git clone https://github.com/autowarefoundation/open_ad_kit.git
> cd open_ad_kit\docker\autoware-openadk
> bash run-containers.sh
#### Docker Desktop のエミュレーション機能で aarch64 イメージの simulator と planning-control が動きます。
```

```shell-session:別のコマンドプロンプトで Open AD Kit visualizer を実行
> cd open_ad_kit\docker\autoware-openadk
> bash run-visualizer.sh
#### 一瞬 RViz のウィンドウが表示された直後にエラーで消えます。
MESA: error: ZINK: failed to choose pdev
glx: failed to create drisw screen
failed to load driver: zink
The X11 connection broke: I/O error (code 1)
XIO:  fatal IO error 2 (No such file or directory) on X server ":0"
      after 19 requests (19 known processed) with 0 events remaining.
```

```shell-session:別のコマンドプロンプトで Open AD Kit visualizer を実行 の続き
> docker run -it --net=host -v /dev/shm:/dev/shm -e ROS_DOMAIN_ID=88 -e DISPLAY=192.168.xx.xx:0.0 -v /tmp/.X11-unix/:/tmp/.X11-unix -e XDG_RUNTIME_DIR=/tmp/runtime-root  ghcr.io/oguzkaganozt/autoware-openadk:ces-visualizer-x86_64 /autoware/scenario-sim/rviz/launch_rviz.sh
#### run-visualizer.sh の中のコマンドを書き換えて　Windows ホストの IP アドレス (192.168.xx.xx) を指定すると、先ほどとは異なるエラー (Mac で X Server なしのときと同じエラー) に変わりました。
qt.qpa.xcb: could not connect to display 192.168.xx.xx:0.0
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.

/autoware/scenario-sim/rviz/launch_rviz.sh: line 3:  65 Aborted  rviz2 -d /autoware/scenario-sim/rviz/scenario_simulator_v2.rviz
```



### Windows, WSL, Docker CE で Open AD Kit を動かす

| 構成 | 備考 |
|---|---|
| DELL Latitude 5530 | Intel i7-1265 CPU, 16GB RAM |
| Windows 10 Enterprise |
| WSL 2.1.5.0 |
| Ubuntu 20.04 |
| Docker CE |
| VcXsrv 64.1.20.14.0 |
| Autoware Open AD Kit | `ces-demo`ブランチ, containers と visualizer　イメージ |

https://learn.microsoft.com/ja-jp/windows/wsl/install

```shell-session:管理者権限で起動したPowerShell
> wsl --install -d Ubuntu-20.04
```
WSLのインストール後、Windowsを再起動します。

Docker をインストールします。

https://qiita.com/studio_haneya/items/0bc57d0c21732fc277fd

```shell-session:WSLのターミナル
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
$ docker --version
Docker version 27.1.1, build 6312585
$ docker run hello-world
#### サンプルコンテナが動きます。
```


```shell-session:WSLのターミナル
$ cd open_ad_kit/docker/autoware-openadk
$ ./run-containers.sh
#### x86 ホストで ARM64 イメージの simulator と planning-control は動きません。
```


```shell-session:WSLの別のターミナル
$ git clone https://github.com/autowarefoundation/open_ad_kit.git
$ cd open_ad_kit/docker/autoware-openadk
$ ./run-visualizer.sh
MESA: error: ZINK: failed to choose pdev
glx: failed to create drisw screen
failed to load driver: zink
The X11 connection broke: I/O error (code 1)
XIO:  fatal IO error 2 (No such file or directory) on X server ":0"
      after 19 requests (19 known processed) with 0 events remaining.
#### RViz のウィンドウが一瞬表示された直後にエラーで消えます。
```

Windows 用の X Server として VcXsrv 64.1.20.14.0 をダウンロード、インストールします。

https://sourceforge.net/projects/vcxsrv/

`C:\Program Files\VcXsrv\X0.hosts` に Windows ホストの IP アドレス 192.168.xx.xx を追記します。
もしくは、VcXsrv 起動時のオプション Disable access control にチェックを付けます。

![Extra settings 2024_09_02 11_46_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601257/2ae5064f-6d78-47b3-7848-fc5b3a3cfcc3.png)

```shell-session:WSLの別のターミナル
$ cd open_ad_kit/docker/autoware-openadk
$ ./run-visualizer.sh
#### RViz のウィンドウは見えないのですが、何かが動いています。
```


### Windows ホストで ROS2 Jazzy を動かす

| 構成 | 備考 |
|---|---|
| DELL Latitude 5530 | Intel i7-1265 CPU, 16GB RAM |
| Windows 10 Enterprise |
| ROS2 Jazzy |

https://docs.ros.org/en/jazzy/Installation/Windows-Install-Binary.html

```shell-session:PowerShellを管理者で実行
> Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
> choco install -y python --version 3.8.3
> choco install -y vcredist2013 vcredist140
> choco install -y openssl --version 1.1.1.2100
> setx -m OPENSSL_CONF "C:\Program Files\OpenSSL-Win64\bin\openssl.cfg"
#### 設定 > 環境変数 > Path > C:\Program Files\OpenSSL-Win64\bin を追加しなくても追加されていました。
```

ROS公式サイトには Visual Studio Community 2019 をインストールするとありますが、もう利用できません。
現在だと Visual Studio Community 2022 しかダウンロードできないですね。
ROS2 の動作確認をするのが目的で、ビルドをする予定がないので私はインストールしませんでした。

https://github.com/ros2/ros2/releases/download/opencv-archives

から opencv-3.4.6-vc16.VS2019.zip をダウンロード、すべて展開し、内容を C:\opencvへ移動


```shell-session:PowerShellを管理者で実行 の続き
> setx /m OpenCV_DIR C:\opencv
> choco install -y cmake
```

設定 > 環境変数 > Path > C:\opencv\x64\vc16\bin を追加
設定 > 環境変数 > Path > C:\Program Files\CMake\bin を追加

https://github.com/ros2/choco-packages/releases/tag/2022-03-15

から以下のファイルをダウンロード
asio.1.12.1.nupkg, bullet.3.17.nupkg, cunit.2.1.3.nupkg, eigen.3.3.4.nupkg, log4cxx.0.10.0-2.nupkg, log4cxx.0.10.0.nupkg, tinyxml-usestl.2.6.2.nupkg, tinyxml2.6.0.0.nupkg

```shell-session:PowerShellを管理者で実行 の続き
> choco install -y -s C:\Users\MY_USER_NAME\Downloads asio bullet cunit eigen log4cxx tinyxml-usestl tinyxml2
```

PATH反映のためPowerShellを管理者で再起動

```shell-session:PowerShellを管理者で再起動
> python -m pip install -U pip setuptools==59.6.0
> python -m pip install -U catkin_pkg cryptography empy importlib-metadata jsonschema lark==1.1.1 lxml matplotlib netifaces numpy opencv-python PyQt5 pillow psutil pycairo pydot pyparsing==2.4.7 pytest pyyaml rosdistro
> choco install -y 7zip
```

https://www.zlatkovic.com/pub/libxml/64bit/

から libxml2-2.9.3-win32-x86_64.7z, iconv-1.14-win32-x86_64.7z, zlib-1.2.8-win32-x86_64.7z をダウンロード、C:\xmllintに解凍

設定 > 環境変数 > Path > C:\xmllint\bin を追加

ROS公式サイトには Qt5 をインストールするとありますが、Qt アプリの開発をするつもりがなく ROS デモの疎通確認をするには必要ないので、私はインストールしませんでした。

```shell-session:PowerShell
> choco install -y graphviz
```

設定 > 環境変数 > Path > C:\Program Files\Graphviz\bin を追加

https://github.com/ros2/ros2/releases

から ros2-jazzy-20240705-windows-release-amd64.zip をダウンロード、すべて展開し、展開された内容を C:\dev\ros2へ移動

設定 > 環境変数 > Path > C:\dev\ros2\Scripts を追加

```shell-session:コマンドプロンプト(PowerShellではない)
> call C:\dev\ros2\local_setup.bat
> ros2 run demo_nodes_cpp talker --ros-args --remap __node:=win_talker
...
```

Windows ホストで talker が動きました。

```shell-session:別のコマンドプロンプト
> call C:\dev\ros2\local_setup.bat
> ros2 run demo_nodes_py listener --ros-args --remap __node:=win_listener
```

Windows ホスト内で talker のメッセージを listener が受信できました。

```shell-session:また別のコマンドプロンプト
> call C:\dev\ros2\local_setup.bat
> ros2 node list
> rqt_graph
> rviz2
```

Windows ホスト内でノードリストを見ることができ、接続グラフが表示され、RVizが起動しました。

```shell-session:PowerShellの場合は、一度管理者で起動してファイルのブロックを解除
> Unblock-File C:\dev\ros2\*.ps1
```

```shell-session:PowerShell(その後は一般ユーザーでOK)
> C:\dev\ros2\local_setup.ps1
> ros2 run demo_nodes_cpp talker --ros-args --remap __node:=win_talker
> ros2 run demo_nodes_py listener --ros-args --remap __node:=win_listener
> ros2 node list
> rqt_graph
> rviz2
```


### Windows ホストと WSL Docker コンテナで通信する

| ホスト | コンテナ |
|---|---|
| Windows | Windows, WSL, Ubuntu, Docker CE |

ROS/ROS2 が動いてデスクトップ接続もできるコンテナイメージが公開されているのでありがたく使わせていただきます。

https://memoteki.net/archives/2955

https://github.com/Tiryoh/docker-ros2-desktop-vnc/wiki

```shell-session:WSL Ubuntu のターミナル
$ docker run -p 6080:80 --security-opt seccomp=unconfined --shm-size=512m tiryoh/ros2-desktop-vnc:humble
```

ブラウザで http://127.0.0.1:6080/ を開く > noVNC > 接続 > Terminator
```shell-session:Terminator
$ ros2 run demo_nodes_cpp talker --ros-args --remap __node:=docker_talker
...
```

```shell-session:Windows ホスト PowerShell
> c:\dev\ros2\local_setup.ps1
> ros2 run demo_nodes_cpp listener --ros-args --remap __node:=win_listener
```
この状態ではコンテナ内のメッセージを受信できません。

次に `--net=host` オプションを付けて実行します。
```shell-session:WSL Ubuntu のターミナル
$ docker run --net=host --security-opt seccomp=unconfined --shm-size=512m tiryoh/ros2-desktop-vnc:humble
```
`--net=host` を付けると `-p 6080:80` が無効になり VNC 接続はできなくなります。
```shell-session:WSL Ubuntu の別のターミナル
$ docker exec -it ros2-desktop-vnc bash
# sudo su - ubuntu
$ ros2 run demo_nodes_cpp talker --ros-args --remap __node:=docker_talker
...
```

```shell-session:Windows ホスト PowerShell
> c:\dev\ros2\local_setup.ps1
> ros2 run demo_nodes_cpp listener --ros-args --remap __node:=win_listener
```
コンテナ内のメッセージをホストで受信できました。
逆にホストからのメッセージをコンテナ内で受信することもできました。



### Raspberry Pi 5, Ubuntu 24.04, Docker CE で Open AD Kit を動かす

| 構成 | 備考 |
|---|---|
| Raspberry Pi 5 |
| Ubuntu 24.04 Server |
| Docker CE |
| Autoware Open AD Kit | `ces-demo`ブランチ, containers と visualizer　イメージ |

https://docs.docker.com/engine/install/ubuntu/

```shell-session:ターミナルで Docker をインストール
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
$ sudo apt install -y uidmap
$ dockerd-rootless-setuptool.sh install
```

```shell-session:ターミナルで Open AD Kit containers を実行
$ git clone https://github.com/autowarefoundation/open_ad_kit.git
$ cd open_ad_kit/docker/autoware-openadk
$ ./run-containers.sh
```

```shell-session:別のターミナルで Open AD Kit visualizer を実行
$ cd open_ad_kit/docker/autoware-openadk
$ ./run-visualizer.sh
#### ARM プロセッサで x86 バイナリが動きません。
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
exec /ros_entrypoint.sh: exec format error
```

ROS2 が動いてデスクトップ接続もできるコンテナイメージを使って疎通確認します。

https://github.com/Tiryoh/docker-ros2-desktop-vnc/wiki

```shell-session:ターミナルでコンテナを起動
$ docker run --net=host --security-opt seccomp=unconfined --shm-size=512m tiryoh/ros2-desktop-vnc:humble
```

humble を jazzy に変えても挙動は変わりません。

```shell-session:別のターミナルでコンテナ内 talker を起動
$ docker exec -it $(docker ps -q) bash
# sudo su - ubuntu
$ ros2 run demo_nodes_cpp talker --ros-args --remap __node:=pi5docker_talker
```

```shell-session:また別のターミナルでコンテナ内 listener を起動
$ docker exec -it $(docker ps -q) bash
# sudo su - ubuntu
$ ros2 run demo_nodes_cpp listener --ros-args --remap __node:=pi5docker_listener
```

同じコンテナ内の talker と listener で通信できます。
ラズパイ5ホストとコンテナでは通信できません。
ラズパイ5コンテナと Windows ホストでも通信できません。


### Raspberry Pi 5, Ubuntu 24.04, ROS2 Jazzy

| 構成 | 備考 |
|---|---|
| Raspberry Pi 5 |
| Ubuntu 24.04 Server |
| ROS2 Jazzy |

```shell-session:ターミナルで Ubuntu のバージョンを確認
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04 LTS"
VERSION="24.04 LTS (Noble Numbat)"
```

Ubuntu 24.04 (Noble Numbat) に適合する ROS2 Jazzy LTS をインストールする。

https://docs.ros.org/en/jazzy/How-To-Guides/Installing-on-Raspberry-Pi.html

ラズパイであっても Ubuntu であれば Ubuntu のインストール方法で良いとある。

https://docs.ros.org/en/jazzy/Installation/Ubuntu-Install-Debians.html

```shell-session:ターミナル
$ locale
LANG=C.UTF-8
```
UTF-8なのでそのままでOK。

```shell-session:ターミナル
$ sudo apt install software-properties-common
$ sudo add-apt-repository universe
$ sudo apt update && sudo apt install curl -y
$ sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
$ cat /etc/apt/sources.list.d/ros2.list
deb [arch=arm64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu noble main
```

ROSパッケージのビルドや開発はとりあえずしないので ros-dev-tools のインストールはスキップする。

```shell-session:ターミナル
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install ros-jazzy-ros-base
Pending kernel upgrade!
Running kernel version:
  6.8.0-1004-raspi
Diagnostics:
  The currently running kernel version is not the expected kernel version 6.8.0-1010-raspi.
Restarting the system to load the new kernel will not be handled automatically, so you should consider rebooting.
$ sudo reboot
```
カーネルバージョンアップが保留されてるのでラズパイ5を再起動

```shell-session:ターミナル
$ sudo apt install ros-jazzy-desktop
```

```shell-session:ターミナル
$ source /opt/ros/jazzy/setup.bash
$ ros2 run demo_nodes_cpp talker --ros-args --remap __node:=pi5talker
```

```shell-session:別のターミナル
$ source /opt/ros/jazzy/setup.bash
$ ros2 run demo_nodes_py listener --ros-args --remap __node:=pi5listener
```

ラズパイ5ホスト内で talker と listener が通信できました。
ラズパイ4、ラズパイ5、Windows ホストからのメッセージもそれぞれのホストで受信できました。



### Raspberry Pi 4, Ubuntu 20.04, Docker CE

| 構成 | 備考 |
|---|---|
| Raspberry Pi 4 Model B |
| Ubuntu 20.04.4 Server |
| Docker CE |
| ROS2 Foxy |

https://docs.docker.com/engine/install/ubuntu/

```shell-session:ターミナルで Docker をインストール
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
$ sudo apt install -y uidmap
$ dockerd-rootless-setuptool.sh install
```

ROS2 が動いてデスクトップ接続もできるコンテナイメージを使って疎通確認します。

https://github.com/Tiryoh/docker-ros2-desktop-vnc/wiki

```shell-session:ターミナルでコンテナを起動
$ docker run --net=host --security-opt seccomp=unconfined --shm-size=512m tiryoh/ros2-desktop-vnc:humble
```

```shell-session:別のターミナルでコンテナ内 talker を起動
$ docker exec -it $(docker ps -q) bash
# sudo su - ubuntu
$ ros2 run demo_nodes_cpp talker --ros-args --remap __node:=pi4docker_talker
```

```shell-session:また別のターミナルでコンテナ内 listener を起動
$ docker exec -it $(docker ps -q) bash
# sudo su - ubuntu
$ ros2 run demo_nodes_cpp listener --ros-args --remap __node:=pi4docker_listener
```

同じコンテナ内の talker と listener で通信できます。
ラズパイ5ホストや Windows ホストからのメッセージをラズパイ4コンテナでは受信できました。
ラズパイ4ホストや WSL コンテナからのメッセージをラズパイ4コンテナで受信できません。



### Raspberry Pi 4, Ubuntu 20.04, ROS2 Foxy

| 構成 | 備考 |
|---|---|
| Raspberry Pi 4 Model B |
| Ubuntu 20.04.4 Server |
| ROS2 Foxy |

```shell-session:ターミナルで Ubuntu のバージョンを確認
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.4 LTS (Focal Fossa)"
```

Ubuntu 20.04 に適合する ROS2 LTS は Foxy なので Foxy のインストール方法を見る。

https://docs.ros.org/en/foxy/How-To-Guides/Installing-on-Raspberry-Pi.html

ラズパイであっても Ubuntu であれば Ubuntu のインストール方法で良いとある。

https://docs.ros.org/en/foxy/Installation/Ubuntu-Install-Debians.html

```shell-session:ターミナル
$ locale
LANG=C.UTF-8
```
UTF-8なのでそのままでOK。

```shell-session:ターミナル
$ sudo apt install software-properties-common
$ sudo apt add-apt-repository universe
'universe' distribution component is already enabled for all sources.
$ sudo apt update && sudo apt install curl -y
$ sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
$ cat /etc/apt/sources.list.d/ros2.list
deb [arch=arm64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu focal main

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install python3-argcomplete
$ sudo apt install ros-foxy-ros-base
$ sudo apt install ros-foxy-desktop
Errors were encountered while processing:
 /var/cache/apt/archives/libgl-dev_1.3.2-1~ubuntu0.20.04.2_arm64.deb
 /var/cache/apt/archives/libegl-dev_1.3.2-1~ubuntu0.20.04.2_arm64.deb
 /var/cache/apt/archives/libgles-dev_1.3.2-1~ubuntu0.20.04.2_arm64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
```
ros-foxy-ros-base はエラーなくインストールできたが、ros-foxy-desktop はエラー。
Ubuntu 20.04.4 Server だからデスクトップ周りのライブラリがないのか。

```shell-session:ターミナル
$ source /opt/ros/foxy/setup.bash
$ ros2 run demo_nodes_cpp talker --ros-args --remap __node:=pi4talker
```

```shell-session:別のターミナル
$ source /opt/ros/foxy/setup.bash
$ ros2 run demo_nodes_cpp listener --ros-args --remap __node:=pi4listener
```
ラズパイ4からのメッセージがラズパイ4で受信できる。

ラズパイ4からのメッセージが Windows で受信できないし、Windows からのメッセージがラズパイ4で受信できない。
ファイアウォールのせいか。

```shell-session:また別のターミナル
$ sudo ufw disable
Firewall stopped and disabled on system startup
```

ファイアウォールを無効にしたら、ラズパイ4、ラズパイ5、Windows ホスト間でそれぞれのメッセージをそれぞれが受信できるようになりました。





## 各環境の疎通確認の状況

ROS2 公式のデモ talker/listener を異なるホスト・環境で動かして通信できたかどうかを以下の表にまとめます。
同じホストかつ同じ環境の talker/listener は普通に通信できるので省略します。
また、左右を入れ替えた逆方向の通信も普通にできるので省略します。

| talker | listener | 通信 |
|---|---|---|
| Mac, ROS2 Humble | Windows, ROS2 Jazzy | ok |
| Mac, ROS2 Humble | Windows, WSL, Docker CE, ROS2 Humble | NG |
| Windows, ROS2 Jazzy | Windows, WSL, Docker CE, ROS2 Humble | ok |
| Windows, ROS2 Jazzy | RPi4, Ubuntu 20.04, ROS2 Foxy | ok |
| Windows, ROS2 Jazzy | RPi4, Ubuntu 20.04, Docker CE, ROS2 Humble | ok |
| Windows, ROS2 Jazzy | RPi5, Ubuntu 24.04, ROS2 Jazzy | ok |
| Windows, ROS2 Jazzy | RPi5, Ubuntu 24.04, Docker CE, ROS2 Jazzy | NG |
| Windows, WSL, Docker CE, ROS2 Humble | RPi4, Ubuntu 20.04, Docker CE, ROS2 Humble | NG |
| RPi4, Ubuntu 20.04, ROS2 Foxy | RPi4, Ubuntu 20.04, Docker CE, ROS2 Humble | NG |
| RPi4, Ubuntu 20.04, ROS2 Foxy | RPi5, Ubuntu 24.04, ROS2 Jazzy | ok |
| RPi4, Ubuntu 20.04, Docker CE, ROS2 Humble | RPi5, Ubuntu 24.04, ROS2 Jazzy | ok |
| RPi5, Ubuntu 24.04, ROS2 Jazzy | RPi5, Ubuntu 24.04, Docker CE, ROS2 Jazzy | NG |


次の表は Open AD Kit の containers/visualizer を異なるホスト・環境で動かして通信できたかどうかの結果です。

| containers | visualizer | 通信 |
|---|---|---|
| Windows, Docker Desktop | Windows, Docker Desktop, VcXsrv | NG |
| Mac, Docker Desktop | Mac, Docker Desktop, XQuartz | NG |
| RPi4, Ubuntu 20.04, Docker CE | Windows, WSL, Ubuntu 20.04, Docker CE | NG |
| RPi4, Ubuntu 20.04, Docker CE | Windows, WSL, Ubuntu 24.04, Docker CE | NG |