Skip to main content

ROS 2 Domain ID

ROS_DOMAIN_ID selects the DDS domain used by a ROS 2 process. Nodes and tools that should communicate normally need to participate in the same domain, while unrelated systems can use different Domain IDs to avoid discovering each other unintentionally.

Overview​

ROS 2 communication is built on DDS discovery. The Domain ID is one of the first settings DDS uses to decide which participants belong to the same discovery domain.

For ordinary ROS 2 discovery, participants that should communicate generally need the same Domain ID. This includes:

  • ROS 2 nodes
  • CLI terminals
  • RViz2
  • rosbag recording or playback processes
  • ROS 2 applications running inside containers

A matching Domain ID is necessary for ordinary discovery, but it is not sufficient by itself. Network connectivity, firewall rules, DDS / RMW configuration, discovery settings, message types, and QoS compatibility still matter.

:::info Domain ID is not a security boundary A Domain ID does not authenticate participants, encrypt traffic, or prevent another system from choosing the same ID.

Use appropriate network controls and ROS 2 / DDS security mechanisms when access control, authentication, or encryption is required. :::

The usual ROS 2 default is 0 when ROS_DOMAIN_ID is unset and no launcher or application overrides it.

Do not assume every Robotic Suite package uses 0. For example:

Always check the launch configuration for the installed release before changing the Domain ID.

Why It Matters​

A shared network may contain several robots, development machines, containers, or test environments at the same time.

If unrelated systems use the same Domain ID, they may discover nodes that were never intended to participate in the same ROS 2 system.

If processes that should communicate use different Domain IDs, they normally will not discover each other at all.

A consistent Domain ID therefore helps define the intended ROS 2 discovery group, especially when working with:

  • multiple robots on the same network
  • host and container deployments
  • shared development labs
  • RViz2 or CLI tools running outside the robot container
  • rosbag recording and playback
  • multi-machine ROS 2 systems

Core Concepts​

Same Domain ID​

Participants that should communicate normally need to use the same ROS_DOMAIN_ID.

For example:

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

These participants can belong to the same DDS discovery domain, assuming the remaining network and middleware requirements are also satisfied.

Different Domain IDs​

Participants using different Domain IDs normally belong to different DDS discovery domains.

For example:

Robot A ROS_DOMAIN_ID=42
Robot B ROS_DOMAIN_ID=43

This is useful when independent systems share the same physical network.

Choosing a Domain ID​

Assign one Domain ID to each intended communicating system, and use a different unallocated ID for unrelated systems sharing the same network.

For the default DDS UDP port mapping, the official ROS 2 Domain ID guide describes 0 through 101 as a conservative range commonly suitable across standard platform configurations.

This does not mean that IDs above 101 are invalid. DDS derives UDP ports from the Domain ID and participant count, so safe ranges depend on operating-system ephemeral-port ranges and the number of DDS participants on a host.

Do not assume the entire 0 through 232 range is universally safe for every deployment. Check the platform and participant constraints in the official guide when selecting IDs for a large or production system.

The examples below use 42 only as an illustration. Replace it with the Domain ID assigned to your system.

:::warning Production systems Do not change the Domain ID of a running robot or production workload without following the approved stop, configuration, and restart procedure for that deployment. :::

Hands-on Steps​

1. Check the Current Environment​

These examples use Bash on Linux.

First source the correct ROS 2 distribution and any required workspace overlay, as described in CLI Basics.

For a standard ROS 2 Humble installation:

source /opt/ros/humble/setup.bash

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

Use the setup path for the ROS 2 distribution actually installed on your system.

If ROS_DOMAIN_ID is unset, the usual ROS 2 default is 0 unless another launcher or application overrides it.

2. Set the Domain ID for the Current Shell​

After sourcing the required ROS 2 environment and workspace overlay:

export ROS_DOMAIN_ID=42

printenv ROS_DOMAIN_ID

The last command should print:

42

Repeat this check in every shell that will:

  • launch a ROS 2 node
  • run RViz2
  • record or play a rosbag
  • inspect the ROS 2 graph with CLI commands

An export affects only the current shell and processes started from it afterward.

It does not modify:

  • an already running node
  • another terminal
  • an existing container process
  • a service launched by a service manager

After changing the Domain ID, safely stop and relaunch the affected ROS 2 processes from the intended environment.

3. Make the Setting Persistent When Appropriate​

For interactive Bash terminals, first inspect the existing startup configuration:

grep -n 'ROS_DOMAIN_ID' ~/.bashrc

If an existing assignment is present, edit it rather than adding another one.

If no intentional assignment exists, you may add:

export ROS_DOMAIN_ID=42

Place it after any startup script that would otherwise overwrite the value.

Do not repeatedly append multiple ROS_DOMAIN_ID assignments to .bashrc.

Open a new terminal and verify:

printenv ROS_DOMAIN_ID

Login shells, other shell types, service managers, SDK launchers, and containers may use different configuration sources. Change the environment used by the process you actually intend to launch rather than modifying every environment on the machine.

4. Configure Host and Container Environments Separately​

Changing the host shell does not automatically change the environment inside a container.

Likewise, exporting ROS_DOMAIN_ID inside one docker exec shell does not change the container's startup configuration or other already running processes.

The General FAQ documents the Robotic Suite Compose layout and its existing stop.sh / launch.sh lifecycle workflow.

For releases that use this layout, first identify the intended container:

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

Set its name and enter the corresponding configuration directory:

container_name=your_existing_container

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

Edit the existing docker-compose.yml.

Preserve the environment syntax already used by the file.

If the service uses list syntax:

environment:
- ROS_DOMAIN_ID=42

If it uses mapping syntax:

environment:
ROS_DOMAIN_ID: 42

Do not replace unrelated environment settings.

This value belongs to the container configuration; it is not automatically inherited from the host.

If the Compose file uses variable interpolation instead, verify which shell or environment file supplies that variable.

After safely stopping the affected workload, the lifecycle workflow documented in the FAQ is:

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

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

An edited Compose environment must be applied when the container is created or recreated.

A plain:

docker restart <container_name>

retains the existing container configuration and does not apply a changed Compose environment definition.

Verify that the installed Robotic Suite lifecycle scripts recreate or otherwise apply the edited configuration. If the installed release uses a different recreation procedure, follow that release's documentation.

Check the container environment independently:

docker exec "$container_name" printenv ROS_DOMAIN_ID

For participants that need to communicate, this should match the assigned Domain ID used by the host-side ROS 2 processes.

Also check the actual shell or launcher used to start ROS 2 inside the container, because startup scripts can override the container-level value.

A matching Domain ID does not fix an incompatible container network mode or blocked DDS discovery traffic.

5. Verify the Intended ROS 2 Graph​

From a correctly sourced shell, inspect the assigned domain explicitly:

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

You should see the nodes and topics that belong to the intended running system.

Do not expect a fixed list: the graph depends on what is currently running.

An empty graph by itself does not prove that the Domain ID is wrong. Network or DDS discovery problems can produce the same symptom.

6. Perform an Optional Text-only Connectivity Test​

For an isolated test, use an agreed, unused Domain ID and an environment with demo_nodes_cpp installed.

Do not launch robot drivers or send actuator commands.

In the first sourced terminal:

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

In the second sourced terminal:

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

The listener should print the talker's text messages.

Stop both examples with:

Ctrl+C

To test across a host/container boundary or between two hosts, run one example on each side only after confirming the network configuration and the launch environment on both sides.

Expected Result​

After the Domain ID is configured correctly:

  • processes that should communicate use the same assigned ROS_DOMAIN_ID
  • ros2 node list and ros2 topic list -t show the intended ROS 2 graph
  • the optional talker/listener test succeeds when both sides use the same Domain ID
  • an unrelated ROS 2 system using a different Domain ID does not normally appear in the same discovery graph

Remember that matching Domain IDs confirm only one part of the communication setup. DDS discovery still depends on compatible networking, middleware, and discovery configuration.

Useful Commands​

# 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

Common Problems​

  • The shell prints the new ID, but running nodes still use the old one — changing an environment variable does not modify an already running process. Safely restart the affected process and check for launcher, service-manager, or container overrides.

  • The Domain IDs match, but discovery still fails — check network reachability, multicast or configured discovery-server access, firewall rules, container networking, ROS_LOCALHOST_ONLY, and compatible RMW / DDS settings. See DDS Discovery.

  • The topic is visible, but no messages arrive — Domain ID and discovery are already working at least partially. Check the exact topic name, message type, active publisher, and QoS compatibility. See QoS Mismatch.

  • An unexpected robot appears in the graph — inspect the actual launch environments of both systems and assign different Domain IDs if the systems are intended to remain independent. A ROS 2 namespace does not create a separate DDS domain.

  • The host sees ROS 2 nodes, but the container does not — check the Domain ID inside the container separately and confirm that the container network mode supports the required DDS discovery traffic.

  • CLI graph information appears stale — the ROS 2 CLI daemon is domain-specific. Restart the daemon for the domain you are inspecting:

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

    The next graph query starts the daemon again.

    These commands target the daemon for Domain ID 42; they do not restart application nodes and do not stop a daemon belonging to another Domain ID.

    See the official ROS 2 CLI daemon reference.

Key Takeaways​

  • ROS 2 processes that should discover and communicate with each other normally need the same ROS_DOMAIN_ID.
  • Different Domain IDs are useful for separating independent ROS 2 systems that share the same physical network.
  • A matching Domain ID is necessary for ordinary discovery, but network, DDS / RMW, firewall, message-type, and QoS settings can still prevent communication.
  • Host shells, containers, services, and separate terminals must be checked independently because they do not automatically share the same environment.
  • ROS_DOMAIN_ID is a discovery-group setting, not an authentication or security mechanism.
  • Choose Domain IDs with DDS port allocation and platform constraints in mind rather than assuming every value in the theoretical range is universally safe.