Compare hosts & containers¶
Many ROS 2 problems only appear between two machines: a robot and a laptop, or two containers. AutoDiag compares their environments side by side.
flowchart LR
subgraph robot["Robot or container"]
R1["dds-autodiag collect --redact"] --> R2[("robot.json")]
end
subgraph you["Your machine"]
L1["dds-autodiag compare robot.json laptop.json"] --> L2["Side-by-side table<br/>+ findings + report"]
end
R2 -- "copy file" --> L1
R3["Live collector<br/>token-protected"] -. "private IP or SSH tunnel" .-> L2
Option A: snapshot files (recommended)¶
On the robot or inside the container, with ROS 2 sourced:
On your machine, redact a snapshot with the same salt and compare the two files:
dds-autodiag collect --redact --salt team42 -o laptop.json
dds-autodiag compare robot.json laptop.json --report report.md
Without --salt, collect --redact picks a random salt and prints it to stderr, so you can reuse it on the other
side.
Redaction keeps comparisons working
--redact replaces hostnames, IP addresses and home paths with short hashes. With the same --salt on both
sides, the same value always hashes to the same token and the comparison still works.
Redacted file vs. the live host
dds-autodiag compare robot.json (or loading robot.json in the dashboard under Hosts) compares the
file with this host's unredacted snapshot. Domain, RMW, distro and discovery rows still work, but the hashed
hostname never equals the real one, so rules that check for the same host always see "different hosts". For
containers on one host, collect without --redact, or redact both sides and compare the two files.
Option B: live collector¶
On the peer, start AutoDiag with a collector token, listening on the network (a non-loopback bind also needs the dashboard token, and the IP you connect to must be an allowed host):
AUTODIAG_AGENT_TOKEN=<long-random-secret> AUTODIAG_UI_TOKEN=<another-secret> \
AUTODIAG_ALLOWED_HOSTS=<private-ip> dds-autodiag serve --host 0.0.0.0 --port 8081
In your dashboard, open Hosts → Connect to a live collector and enter http://<private-ip>:8081 and the
collector token. The dashboard you have open is always this host; the URL you enter is the peer. Opening the
collector’s own UI flips the pair — you then type this laptop as http://<laptop-LAN-IP>:8080 (the laptop serve
must listen on 0.0.0.0 and have AUTODIAG_AGENT_TOKEN set). From a bridge-network container, 127.0.0.1 is the
container, not the PC.
For security, the collector is only fetched from private or loopback IPs, without proxies or redirects, and with a size limit.
Over the internet, use an SSH tunnel instead. The peer can then stay on 127.0.0.1
(AUTODIAG_AGENT_TOKEN=<long-random-secret> dds-autodiag serve --port 8081), and you enter http://127.0.0.1:8081:
Docker containers¶
The Local Docker environments card lists running containers (name, network, IP, published or AUTODIAG_PORT)
and the command to collect a snapshot from each. It runs docker on this AutoDiag process, so a collector
inside a container without the Docker CLI cannot list the host or siblings. Your laptop never appears as a Docker
row. Use Connect + token, or a snapshot file:
AutoDiag must be installed inside the container for this. For shared memory between containers,
SHM_IPC_NAMESPACE_DIFFERENCE is a two-snapshot rule: collect
in both containers, then compare the two files with the transport you expect:
docker exec container-a bash -lc "dds-autodiag collect" > a.json
docker exec container-b bash -lc "dds-autodiag collect" > b.json
dds-autodiag compare a.json b.json --transport dds_shm
The rule needs both snapshots detected as containers and the same host identity. Docker gives each container its own
hostname, unless they share the UTS namespace (--uts=host) or you set the same --hostname.
The repo ships an isolated multi-RMW fleet (Cyclone, Fast DDS, Zenoh, domain and QoS faults) in
examples/lab-fleet/ (./run-lab.sh). Domain 87 so it never joins a host graph on domain 0. Collector token:
lab-collector-token. Your laptop serve at http://127.0.0.1:8080 stays this host; connect a lab URL under
Hosts as the peer.
What gets compared¶
| Row | Typical finding |
|---|---|
| Domain ID | DOMAIN_MISMATCH |
| RMW | RMW_MISMATCH (Zenoh vs DDS is an error) |
| ROS distro | DISTRO_MISMATCH |
| Discovery range | DISCOVERY_RANGE_RESTRICTED, LOCALHOST_ONLY |
| Network interfaces | MULTICAST_CAPABILITY_ABSENT |
| IPC namespace | SHM_IPC_NAMESPACE_DIFFERENCE |