はじめに
本記事はROS 2アドベントカレンダー12日目の記事です.
この手のイベントに参加するのは初めてなので至らないや不適切な点がございましたらご容赦ください.
2024年1月26日追記
本記事の方法よりもミラーモードを活用したほうが良さそうです.
一応本記事も残しておきますが...
本記事の概要
下の画像のように,Raspberry Pi上のノード(Node B)で配信したトピックをWSL2内のノード(Node A)で購読しようとしたときに必要となる設定について,色々調べたことをまとめました.
イメージ的にはRaspberry Pi上では重くてできない処理をリソースのあるマシンで代替したり,複数台のRaspberry Pi内のノードの状態を中央集権的に監視するようなユースケースを考えています.
Windowsなんて使うな?まあそれはそうなんですけど...
前提
今回動作確認を行ったマシンの環境は以下の通りです.
マシンA | version |
---|---|
機種 | Surface Laptop Studio 2 |
OS | Windows11 Pro 22H2 |
WSL2 | Ubuntu 22.04.3 LTS |
ROS 2 | humble |
マシンB | version |
---|---|
機種 | Raspberry Pi 4 Model B |
OS | Ubuntu MATE 22.04.3 LTS |
ROS 2 | humble |
後述しますが,2023年12月7日時点でWindows11 Proでのみ動作を確認しています.
Homeだと恐らくできないと思うので,他のやり方があれば情報を頂けますと幸いです.
Windowsとraspberry piがWiFiか何かで同一ルータの下にぶら下がっているものとします.
両マシンにROS 2を導入するところまで出来ているとします.(Win側はWSL2内のUbuntuに導入)
例として
$ ros2 run demo_nodes_cpp talker
[INFO] [1701932607.846492099] [talker]: Publishing: 'Hello World: 1'
[INFO] [1701932608.846204901] [talker]: Publishing: 'Hello World: 2'
[INFO] [1701932609.846247598] [talker]: Publishing: 'Hello World: 3'
...
が実行できる状態にあるとします.
WSL2側の設定
ROS 2は同一ネットワーク内のあるノードを自動的に見つけて,メッセージのやり取りを行ってくるはずです.
しかし,WSL2はデフォルトでは直接ルータからIPアドレスを割り当てられるわけではないので,WSL2内のROS 2からはraspberry piのROS 2上で立てたノードを見つけることができませんでした.(その逆も然り)
そこで,
こちらの記事を参考に,仮想スイッチマネージャーの設定を行いました.
手順
1. Hyper-Vの有効化
Windowsの
「スタート」>「設定」>「アプリ」>「オプション機能」>「Windowsのその他の機能」
からHyper-Vを有効化します.
再起動を要求されるので指示に従います.
Windows 11 homeだとHyper-Vの項目がなく,この方法が使えないようです.
他にやり方があれば情報をいただけますと幸いです.
2. 仮想スイッチの作成
Hyper-Vマネージャーから「仮想スイッチマネージャー」を選択し,新しい仮想ネットワークスイッチを作成します.
種類は「外部」で,名前は任意です.(ここでは「myswitch」とします)
3. .wslconfig
の作成
Windows側のホームディレクトリ(C:\Users\<USERNAME>
)に.wslconfig
を作成して以下を書き込みます.
[wsl2]
networkingMode=bridged
vmSwitch=myswitch
dhcp=true
localhostForwarding=True
4. IPv6の無効化
3まででも一応目的は達成できるのですが,このままだとwsl2から外部への通信速度が激烈に遅く,トピックの購読などに支障が出ます.
(「wsl2 slow network」等で調べると色々出てきます)
色々な解決方法が模索されているようですが,筆者はIPv6を無効化することで解決できたので,その方法を記しておきます. 筆者も日によって症状が出たり出なかったりで正直よく分かりません...とりあえず,下記の方法でIPv6を無効化することで良くなった経験があるので,その方法を示しておきます.
(詳しい方,何かコメント等頂けますと幸いです.)
「スタート」>「ncpa.cpl」で検索し,
ネットワーク接続の「vEthernet」をクリック,「プロパティ」からIPv6のチェックを外します.
ここまで終わったら,一応PowerShell等でwsl --shutdown
でWSL2を再起動させておきましょう.
WSL2内のUbuntuで
$ ip a
...
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 5e:bb:f6:9e:ee:fa brd ff:ff:ff:ff:ff:ff
inet 192.168.**.***/24 brd 192.168.**.255 scope global eth0
valid_lft forever preferred_lft forever
...
とIPアドレス(192.168.**.***)が割り当てられていれば成功です.
動作テスト
raspberry pi上で
$ ros2 run demo_nodes_cpp talker
...
[INFO] [1701936642.555888717] [talker]: Publishing: 'Hello World: 30'
[INFO] [1701936643.555560694] [talker]: Publishing: 'Hello World: 31'
[INFO] [1701936644.555553278] [talker]: Publishing: 'Hello World: 32'
[INFO] [1701936645.555564862] [talker]: Publishing: 'Hello World: 33'
[INFO] [1701936646.555625094] [talker]: Publishing: 'Hello World: 34'
[INFO] [1701936647.555615198] [talker]: Publishing: 'Hello World: 35'
...
WSL2上で
$ ros2 run demo_nodes_cpp listener
[INFO] [1701936642.422464196] [listener]: I heard: [Hello World: 30]
[INFO] [1701936643.422907222] [listener]: I heard: [Hello World: 31]
[INFO] [1701936644.424529921] [listener]: I heard: [Hello World: 32]
...
とメッセージが確認できればOKです.
注意
- 両マシンの
$ROS_DOMAIN_ID
が違うと,当然ですが互いにノードが見えなくなってしまうので注意です. - WSL2が直接物理ネットワークにアクセスできているのでセキュリティがどうなるのかとか実はよくわかっていないです.一応気を付けてください.
おわりに
ここまで読んでいただいておいてアレなのですが,筆者はROS 2使い始めてまだ数日の赤ちゃんです.(ROS 1はそこそこ使っていたのですが)
上記の情報も,詳しい人から見たら「何やってんだコイツ」な内容かもしれないのですが,ご意見や情報の修正等頂けますと幸いです.
2024年1月26日追記
ミラーモードなるものが追加されていたのでそちらを使ったほうがよさそうですね...