claudeDroneteam-docs
documentation · reference
Docs reference

Structured knowledge from collected_doc_media/claudedrone_docs/. Browse the tree on the left; the source of truth is markdown in the repo.

ROS 2 DDS discovery — common problems

When nodes can't see each other: DOMAIN_ID, firewall, NIC.

stabledoc-seoupdated 2026-05-11T00:00:00.000ZClaudeDrone

ROS 2’s DDS layer handles peer discovery automatically — nodes find each other without a central master. That works beautifully when it works, and is mysteriously broken when it doesn’t. This page covers the four most common reasons two ROS 2 nodes can see each other’s published topics but fail to subscribe successfully, or fail to see each other at all.

Cause 1 — ROS_DOMAIN_ID mismatch

ROS_DOMAIN_ID is the network namespace for DDS. Nodes with different domain IDs cannot see each other, by design. The default is 0; you can set it to any integer 0-101.

Diagnostic: echo $ROS_DOMAIN_ID on every machine / shell where you’re running nodes. They must all match.

Fix: export the same ROS_DOMAIN_ID in every shell. In ~/.bashrc or a project-local .env file.

Cause 2 — Firewall blocking multicast / UDP

DDS uses multicast UDP for initial discovery and unicast UDP for ongoing communication. A firewall that blocks UDP on the relevant ports breaks discovery.

Diagnostic: sudo ufw status or sudo iptables -L. Look for rules blocking 7400-7500 (DDS default port range).

Fix: open the ports, or disable the firewall on the dev network. For a dev machine on a trusted LAN, sudo ufw disable is usually fine.

Cause 3 — Multiple network interfaces

If your machine has multiple NICs (wired + WiFi + a Docker bridge + tailscale + …), DDS may pick the wrong one for discovery — broadcasting on docker0 instead of eth0, for example.

Diagnostic: ros2 topic list shows topics from local node but not from a remote node on the same LAN; tcpdump -i any port 7400 shows traffic on the wrong interface.

Fix: restrict DDS to one interface. With CycloneDDS:

export CYCLONEDDS_URI='<CycloneDDS><Domain><General><NetworkInterfaceAddress>eth0</NetworkInterfaceAddress></General></Domain></CycloneDDS>'

For development on a single machine, the simpler fix is export ROS_LOCALHOST_ONLY=1 — DDS will skip discovery on external interfaces entirely.

Cause 4 — Stale shared-memory segments

DDS uses shared memory for fast intra-machine communication. After a crashed node, stale /dev/shm/fastrtps_* segments can confuse discovery.

Diagnostic: ls /dev/shm/ | grep fastrtps shows old segments.

Fix:

sudo rm /dev/shm/fastrtps_*
# kill any zombie ROS processes first:
pkill -9 -f 'rclpy|rclcpp|ros2'

This is also a useful step when discovery has been working and suddenly stops — usually means a previous crash left state behind.

A diagnostic recipe

When in doubt, run this sequence on two machines you expect to see each other:

# On machine A
ros2 daemon stop && ros2 daemon start
ros2 topic list
ros2 multicast send

# On machine B
ros2 multicast receive

If multicast receive doesn’t see the send, you have a network / firewall / interface problem. If it does, you have a ROS_DOMAIN_ID or shared-memory problem.

Where to go next

© 2026 claudeDrone Team · auto-pipeline · Nuxt 3 SSR