えいあーるれいの技術日記

ROS2やM5 Stack、Ubuntuについて書いています

Jazzy以降、「ROS_LOCALHOST_ONLY」使えないらしいよ(ROS 2)

ROS 2は、DDSベースのマルチキャスト通信を採用しているため、同じネットワーク内であれば、ROS 2トピックが通るようになります。

これは、ROS 2の正しい挙動ですが、複数人で使うときは管理しにくくなり、一気に使い勝手が悪くなります。


これを解消するために

  • ROS_DOMAIN_ID でPCごとに別々のIDを設定する
  • ROS_LOCALHOST_ONLY を設定する

の2つの方法が利用できましたが、ironの頃から ROS_LOCALHOST_ONLY が非推奨になってjazzyでは使えなくなったため、この代替案が必要となります。

今回は、この代替を示します。


設定方法

ROS_LOCALHOST_ONLY の代替として ROS_AUTOMATIC_DISCOVERY_RANGE が使用できます。

# デフォルト:全コンピュータが検出可能
export ROS_AUTOMATIC_DISCOVERY_RANGE=SUBNET

# LOCALHOST_ONLYの代替:自PCのみ検出可能
export ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOST

# :new: (自分含めて)どのコンピュータからも探索不能
export ROS_AUTOMATIC_DISCOVERY_RANGE=OFF

デフォルトは SUBNET なので、設定しなければこれまで通りマルチキャスト通信になります。

docs.ros.org

⚠️:片方が ROS_STATIC_PEERS (後述)でローカルホスト側のIPアドレスが設定されていると、LOCALHOST設定したPC(ROS_STATIC_PEERS 設定の有無にかかわらず)とSUBNET設定したPCの疎通が開始されます

各設定における挙動についてはは「適用範囲について」を参照してください。


ROS_STATIC_PEERSについて

特定のPCとだけ通信したいという場合は、 LOCALHOST 設定の上で ROS_STATIC_PEERS で接続先のIPアドレス(or 相手のPC上で自分のIPアドレス)を設定すると通信できます。

LOCALHOST の設定と矛盾していそうな気がしますが、これは活用できると便利かもしれません。

設定方法

通信したいPCのアドレスを ROS_STATIC_PEERS に記述します。

この設定は1台でも適用されれば、その他のPCで設定しなくても疎通するようになります。

# 疎通したいPCのうちいずれか1台以上で疎通先を記述
export ROS_STATIC_PEERS="192.168.0.2"

## 複数台の場合:セミコロンで分割
export ROS_STATIC_PEERS="192.168.0.2;192.168.0.3"

RaspberryPi OS (bookworm 64bit, ROS-Jazzy) 上でdemo_nodes_cpp.talker を実行して設定の適用範囲を確認しました。


適用範囲

細かく疎通範囲を設定するために、2つの環境変数をうまく組み合わせる必要がありますが、文字だけではかなり分かりにくくなっています。

そこで、図を用意しました。

DISCOVERY_RANGE=OFFの場合

この設定上のノードは、同じLaunch上に記述したとしても、いずれのノードともUDP通信できません。

DISCOVERY_RANGE=OFFの場合

DISCOVERY_RANGE=LOCALHOSTの場合

次の条件下で接続できます。

  • ROS_DOMAIN_IDが一致
  • いずれかの条件を満たす構成(重複OK)
    • 同じPC内の DISCOVERY_RANGE について、LOCALHOST or SUBNET 設定のノード
    • STATIC_PEERS が接続先を示している or 接続先がPC1のIPアドレスを示している場合において、DISCOVERY_RANGE について LOCALHOST or SUBNET 設定のノード

DISCOVERY_RANGE=LOCALHOSTの場合

LOCALHOSTの場合(STATIC_PEERSをPC1側から設定)

DISCOVERY_RANGE=SUBNETの場合

次の条件下で接続できます。

  • ROS_DOMAIN_IDが一致
  • いずれかの条件を満たす構成(重複OK)
    • 同じネットワーク内の DISCOVERY_RANGE について、LOCALHOST or SUBNET 設定のノード
    • STATIC_PEERS が接続先を示している or 接続先がPC1のIPアドレスを示している場合において、DISCOVERY_RANGE について LOCALHOST or SUBNET 設定のノード

DISCOVERY_RANGE=SUBNETの場合

背景

この変更は、 ROS_LOCALHOST_ONLY では満たせないケースを補完するものです。

(例:PC1とPC2は相互通信させたいが、PC3とは分離したい)

以下のディスカッションでオプションやその有効範囲が議論されていました。

discourse.ros.org

「トピック・ノードの公開範囲を限定」するだけならsros2というツールを使えば、暗号化と一緒に他のノードから発見されなくなります。

しかしながら、講習の場面においてその環境の設定のためにsros2を教えてさらに複雑にするメリットが無いということもあり、このようなオプションの変更がされたようです。


また、ROSの探索機能から除外される OFF単体テストで用いられることを想定していそうです。(どのような場合に役立つのか、よくわかっていないですが…)

Proposed changes to how ROS performs discovery of nodes - #25 by grey - Next Generation ROS - ROS Discourse

変更の適用はIron以降となっています。


まとめ

非推奨となった ROS_LOCALHOST_ONLY の代わりとなるオプションとその動作について説明しました。

特定のPCと相互通信するオプションについては、sros2を使うことなく探索範囲から除外できるので、使い勝手の良いオプションだと思われます。