跳至主要内容

ROS 2 Domain ID

ROS_DOMAIN_ID 用來選擇 ROS 2 Process 所使用的 DDS Domain。需要彼此通訊的 Node 與工具通常必須位於相同 Domain,而互不相關的系統則可以使用不同的 Domain ID,避免彼此意外 Discovery。

概述​

ROS 2 Communication 建立在 DDS Discovery 之上,而 Domain ID 是 DDS 用來判斷哪些 Participant 屬於同一個 Discovery Domain 的第一層設定之一。

在一般 ROS 2 Discovery 情況下,需要彼此通訊的 Participant 通常必須使用相同的 Domain ID,包括:

  • ROS 2 Node
  • CLI Terminal
  • RViz2
  • rosbag Recording 或 Playback Process
  • 執行在 Container 內的 ROS 2 Application

相同的 Domain ID 是一般 Discovery 的必要條件,但並不足以單獨保證通訊成功。Network Connectivity、Firewall Rule、DDS / RMW Configuration、Discovery Setting、Message Type 與 QoS Compatibility 仍然都會影響結果。

提示

Domain ID 不是 Security Boundary

Domain ID 不會驗證 Participant 身分、不會加密 Traffic,也無法阻止其他系統選擇相同的 ID。

如果需要 Access Control、Authentication 或 Encryption,應使用適當的 Network Control 與 ROS 2 / DDS Security Mechanism。

當 ROS_DOMAIN_ID 沒有設定,且 Launcher 或 Application 也沒有另外覆寫時,ROS 2 一般預設使用 0。

不要假設所有 Robotic Suite Package 都使用 0。例如:

在修改 Domain ID 之前,請先確認目前安裝版本的 Launch Configuration。

為什麼重要​

同一個 Network 中可能同時存在多台 Robot、Development Machine、Container 或 Test Environment。

如果互不相關的系統使用相同 Domain ID,它們可能會 Discovery 到原本不應該加入同一個 ROS 2 System 的 Node。

反過來,如果原本應該彼此通訊的 Process 使用不同 Domain ID,通常就無法 Discovery 到對方。

因此,一致的 Domain ID 可以協助定義預期的 ROS 2 Discovery Group,尤其適用於:

  • 同一個 Network 上有多台 Robot
  • Host 與 Container Deployment
  • 共用的 Development Lab
  • RViz2 或 CLI Tool 執行在 Robot Container 之外
  • rosbag Recording 與 Playback
  • Multi-machine ROS 2 System

核心概念​

相同 Domain ID​

需要彼此通訊的 Participant 通常必須使用相同的 ROS_DOMAIN_ID。

例如:

Host ROS 2 node ROS_DOMAIN_ID=42
Container ROS 2 node ROS_DOMAIN_ID=42
RViz2 ROS_DOMAIN_ID=42
ros2 CLI ROS_DOMAIN_ID=42

只要其他 Network 與 Middleware 條件也符合,這些 Participant 就可以加入同一個 DDS Discovery Domain。

不同 Domain ID​

使用不同 Domain ID 的 Participant,通常會位於不同的 DDS Discovery Domain。

例如:

Robot A ROS_DOMAIN_ID=42
Robot B ROS_DOMAIN_ID=43

當多個獨立系統共用相同 Physical Network 時,這種方式可以避免彼此 Discovery。

選擇 Domain ID​

為每一個預期彼此通訊的系統指定一個 Domain ID;對於共用同一 Network、但彼此獨立的系統,則使用不同且尚未分配的 ID。

對預設 DDS UDP Port Mapping 而言,ROS 2 官方 Domain ID 文件 將 0 到 101 描述為在常見 Platform Configuration 下較保守、通常適合使用的範圍。

這不代表 101 以上的 ID 是無效的。

DDS 會根據 Domain ID 與 Participant 數量推導 UDP Port,因此實際安全範圍會受到作業系統 Ephemeral Port Range,以及單一 Host 上 DDS Participant 數量影響。

不要假設整個 0 到 232 範圍在所有 Deployment 中都一定安全。若要為大型或 Production System 選擇 Domain ID,請確認官方文件中的 Platform 與 Participant Constraint。

以下範例使用 42 僅作為示範。請替換成實際分配給你的系統的 Domain ID。

注意

Production System 不要在沒有遵循該 Deployment 所規定的 Stop、Configuration 與 Restart Procedure 前,直接修改正在執行中的 Robot 或 Production Workload Domain ID。

實作步驟​

1. 檢查目前 Environment​

以下範例使用 Linux 上的 Bash。

先依照 CLI Basics 說明,source 正確的 ROS 2 Distribution 與必要的 Workspace Overlay。

以標準 ROS 2 Humble Installation 為例:

source /opt/ros/humble/setup.bash

printenv ROS_DISTRO
printf 'ROS_DOMAIN_ID=%s\n' "${ROS_DOMAIN_ID-unset}"

請依實際安裝的 ROS 2 Distribution 使用正確的 Setup Path。

如果 ROS_DOMAIN_ID 顯示為 unset,而 Launcher 或 Application 也沒有另外 Override,ROS 2 一般會使用預設值 0。

2. 設定目前 Shell 的 Domain ID​

完成 ROS 2 Environment 與 Workspace Overlay Source 後:

export ROS_DOMAIN_ID=42

printenv ROS_DOMAIN_ID

最後一個指令應該會輸出:

42

每一個會進行以下操作的 Shell 都應該分別確認:

  • 啟動 ROS 2 Node
  • 執行 RViz2
  • Record 或 Play Rosbag
  • 使用 CLI Command 檢查 ROS 2 Graph

export 只會影響目前 Shell,以及之後從該 Shell 啟動的 Process。

它不會修改:

  • 已經執行中的 Node
  • 另一個 Terminal
  • 已存在的 Container Process
  • 由 Service Manager 啟動的 Service

修改 Domain ID 後,請安全停止並從正確 Environment 重新啟動受影響的 ROS 2 Process。

3. 必要時設定為 Persistent​

對 Interactive Bash Terminal,先檢查目前 Startup Configuration:

grep -n 'ROS_DOMAIN_ID' ~/.bashrc

如果已經存在 Assignment,應直接修改原本的設定,而不是再增加一筆。

如果沒有任何預期的 Assignment,可以加入:

export ROS_DOMAIN_ID=42

請將它放在不會被後續 Startup Script 覆寫的位置。

不要重複在 .bashrc 中加入多筆 ROS_DOMAIN_ID 設定。

開啟新的 Terminal 後再次確認:

printenv ROS_DOMAIN_ID

Login Shell、其他 Shell Type、Service Manager、SDK Launcher 與 Container 可能會使用不同的 Configuration Source。

應修改真正用來啟動目標 Process 的 Environment,而不是無差別地修改整台機器上的所有 Environment。

4. 分別設定 Host 與 Container Environment​

修改 Host Shell 不會自動修改 Container 內的 Environment。

同樣地,在某個 docker exec Shell 中執行 export ROS_DOMAIN_ID=...,也不會修改 Container 的 Startup Configuration 或其他已經執行中的 Process。

General FAQ 中記錄了 Robotic Suite 的 Compose Layout,以及既有的 stop.sh / launch.sh Lifecycle Workflow。

對使用這套 Layout 的 Release,先確認目標 Container:

docker ps --format '{{.Names}}'

設定 Container Name,並進入對應 Configuration Directory:

container_name=your_existing_container

cd "/usr/local/Advantech/ros/container/docker/docker-compose/${container_name}"

編輯現有的 docker-compose.yml。

請保留檔案原本使用的 environment Syntax。

如果 Service 使用 List Syntax:

environment:
- ROS_DOMAIN_ID=42

如果使用 Mapping Syntax:

environment:
ROS_DOMAIN_ID: 42

不要移除或覆蓋其他無關的 Environment Setting。

這個設定屬於 Container Configuration,不會自動從 Host 繼承。

如果 Compose File 使用 Variable Interpolation,請確認實際是哪一個 Shell 或 Environment File 提供該變數。

安全停止相關 Workload 後,FAQ 中記錄的 Lifecycle Workflow 為:

cd /usr/local/Advantech/ros/container/docker

./stop.sh "$container_name" && ./launch.sh "$container_name"

修改後的 Compose Environment 必須在 Container Create 或 Recreate 時才能真正套用。

單純執行:

docker restart <container_name>

只會保留既有 Container Configuration,不會套用修改後的 Compose Environment Definition。

請確認目前安裝版本中的 Robotic Suite Lifecycle Script 是否會 Recreate Container,或確實會套用更新後的設定。

如果該 Release 使用不同的 Recreation Procedure,請依該版本文件操作。

接著獨立確認 Container Environment:

docker exec "$container_name" printenv ROS_DOMAIN_ID

如果 Host-side ROS 2 Process 與 Container 內 Process 需要彼此通訊,兩者應使用相同的 Assigned Domain ID。

同時也要檢查 Container 內實際用來啟動 ROS 2 的 Shell 或 Launcher,因為 Startup Script 仍可能覆寫 Container-level Environment。

相同的 Domain ID 無法修正不相容的 Container Network Mode,也無法解決被阻擋的 DDS Discovery Traffic。

5. 驗證預期的 ROS 2 Graph​

從正確 source 的 Shell 中,明確指定 Domain ID 進行檢查:

ROS_DOMAIN_ID=42 ros2 node list
ROS_DOMAIN_ID=42 ros2 topic list -t

你應該會看到屬於目標 Running System 的 Node 與 Topic。

不要預期會出現固定清單,實際 Graph 取決於目前有哪些 Process 正在執行。

單純看到 Empty Graph,並不能證明 Domain ID 一定設定錯誤。Network 或 DDS Discovery 問題也可能產生相同現象。

6. 選擇性執行純文字 Connectivity Test​

如果要做獨立測試,請使用雙方事先約定、目前沒有其他系統使用的 Domain ID,並確認 Environment 中已安裝 demo_nodes_cpp。

不要啟動 Robot Driver,也不要送出 Actuator Command。

在第一個已經 source 的 Terminal 中:

ROS_DOMAIN_ID=42 ros2 run demo_nodes_cpp talker \
--ros-args -r chatter:=/domain_id_check

在第二個已經 source 的 Terminal 中:

ROS_DOMAIN_ID=42 ros2 run demo_nodes_cpp listener \
--ros-args -r chatter:=/domain_id_check

Listener 應該會持續顯示 Talker 發出的文字 Message。

使用:

Ctrl+C

停止兩個範例。

若要跨 Host / Container,或兩台 Host 進行測試,請先確認雙方 Network Configuration 與 Launch Environment,再分別在兩側各執行一個範例。

預期成果​

正確設定 Domain ID 後:

  • 需要彼此通訊的 Process 使用相同的 ROS_DOMAIN_ID
  • ros2 node list 與 ros2 topic list -t 可以看到預期的 ROS 2 Graph
  • 選擇性的 Talker / Listener Test 在雙方使用相同 Domain ID 時可以正常通訊
  • 使用不同 Domain ID 的獨立 ROS 2 System,通常不會出現在相同 Discovery Graph 中

請記得,相同 Domain ID 只代表通訊設定中的其中一個條件。

DDS Discovery 仍然依賴彼此相容的 Network、Middleware 與 Discovery Configuration。

常用指令​

# Check the current shell
printenv ROS_DOMAIN_ID
printf 'ROS_DOMAIN_ID=%s\n' "${ROS_DOMAIN_ID-unset}"

# Set the current shell
export ROS_DOMAIN_ID=42

# Inspect one domain explicitly
ROS_DOMAIN_ID=42 ros2 node list
ROS_DOMAIN_ID=42 ros2 topic list -t

# Check a container
docker exec "$container_name" printenv ROS_DOMAIN_ID

# Restart the ROS 2 CLI daemon for the domain being inspected
ROS_DOMAIN_ID=42 ros2 daemon stop
ROS_DOMAIN_ID=42 ros2 node list

常見問題​

  • Shell 已經顯示新的 ID,但執行中的 Node 仍然使用舊值 — 修改 Environment Variable 不會改變已經執行中的 Process。請安全重新啟動相關 Process,並檢查 Launcher、Service Manager 或 Container Environment 是否有額外 Override。

  • Domain ID 相同,但 Discovery 仍然失敗 — 檢查 Network Reachability、Multicast 或已設定的 Discovery Server Access、Firewall Rule、Container Networking、ROS_LOCALHOST_ONLY,以及彼此相容的 RMW / DDS Setting。可參考 DDS Discovery。

  • Topic 看得到,但沒有收到 Message — 這代表 Domain ID 與 Discovery 至少已經部分正常。接著檢查完整 Topic Name、Message Type、Active Publisher 與 QoS Compatibility。可參考 QoS Mismatch。

  • Graph 中出現不預期的 Robot — 檢查雙方實際的 Launch Environment。如果兩個系統應該彼此獨立,請分配不同的 Domain ID。ROS 2 Namespace 本身不會建立獨立 DDS Domain。

  • Host 看得到 ROS 2 Node,但 Container 看不到 — 分別檢查 Container 內的 Domain ID,並確認 Container Network Mode 支援需要的 DDS Discovery Traffic。

  • CLI Graph Information 看起來過期 — ROS 2 CLI daemon 與 Domain ID 有關。可以重新啟動目前正在檢查的 Domain Daemon:

    ROS_DOMAIN_ID=42 ros2 daemon stop
    ROS_DOMAIN_ID=42 ros2 node list

    下一次 Graph Query 會重新啟動 Daemon。

    這些指令只會操作 Domain ID 42 對應的 Daemon;不會重新啟動 Application Node,也不會停止屬於其他 Domain ID 的 Daemon。

    可參考 ROS 2 官方 CLI daemon 文件。

重點整理​

  • 需要彼此 Discovery 與通訊的 ROS 2 Process,通常必須使用相同的 ROS_DOMAIN_ID。
  • 當多個獨立 ROS 2 System 共用相同 Physical Network 時,可以使用不同 Domain ID 進行隔離。
  • 相同 Domain ID 是一般 Discovery 的必要條件,但 Network、DDS / RMW、Firewall、Message Type 與 QoS Setting 仍可能造成通訊失敗。
  • Host Shell、Container、Service 與不同 Terminal 必須分別確認,因為它們不會自動共用相同 Environment。
  • ROS_DOMAIN_ID 是 Discovery Group Setting,不是 Authentication 或 Security Mechanism。
  • 選擇 Domain ID 時應考慮 DDS Port Allocation 與 Platform Constraint,不要假設理論範圍中的每個值在所有環境中都一定安全。