Which Fast DDS transport each ROS 2 topic is communicated over, and why
Developer toolsC++ · JavaScriptGitHub @atinfinityOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Shows which Fast DDS transport (UDPv4 / SHM / data-sharing) each ROS 2 Jazzy topic uses, and why
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Shows which Fast DDS transport each ROS 2 topic is communicated over — UDPv4,
UDPv6, TCP, shared memory (SHM) or zero-copy data-sharing — and why.
All distros below use rmw_fastrtps_cpp (rmw_fastrtps_dynamic_cpp works the same):
docker compose build
docker compose run --rm dev bash
colcon build --symlink-install && source build/$ROS_DISTRO/install/setup.bash
ros2 run demo_nodes_cpp talker &
ros2 run demo_nodRead the full README ↗English | 日本語
Documentation site: https://atinfinity.github.io/fastdds_transport_viz/
Shows which Fast DDS transport each ROS 2 topic is communicated over — UDPv4, UDPv6, TCP, shared memory (SHM) or zero-copy data-sharing — and why.
All distros below use rmw_fastrtps_cpp (rmw_fastrtps_dynamic_cpp works the same):
| ROS 2 distro | Fast DDS | Notes |
|---|---|---|
| Humble | 2.6 | Prediction only — the binary has no statistics module |
| Jazzy | 2.14 | Prediction + --stats measurement |
| Lyrical | 3.6 | Prediction + --stats measurement |
| Rolling | 3.x (head) | Tracks Fast DDS main; best-effort in CI, not a required check |
$ ros2 transport list -v --stats --topic '^/(chatter|bounded)$'
TOPIC TYPE PUBS SUBS TRANSPORT LATENCY HZ LOSS REASON
/bounded std_msgs/msg/Int32 1 1 DATA_SHARING x1 108 µs 0 same-host-guid,datasharing-qos-enabled-both,datasharing-domain-ids-match,datasharing-confirmed-no-data-submessages
/bounded_pub@ba8b86aa803d(688) -> /bounded_sub@ba8b86aa803d(690) DATA_SHARING 108 µs (max 155 µs) 10.0 0 measured=SHM (unmeasured, delivered) same-host-guid,datasharing-qos-enabled-both,datasharing-domain-ids-match,datasharing-confirmed-no-data-submessages
/chatter std_msgs/msg/String 1 2 UDPv4 x1, SHM x1 217 µs 0 same-host-guid,datasharing-disabled-writer,reader-no-shm-locator,common-udpv4-locator,measured-udpv4-traffic,both-shm-locators,measured-shm-traffic
/talker@ba8b86aa803d(691) -> /listener_udp@ba8b86aa803d(689) UDPv4 185 µs (max 239 µs) 1.0 0 measured=UDPv4 9pkt 1.19 kB same-host-guid,datasharing-disabled-writer,reader-no-shm-locator,common-udpv4-locator,measured-udpv4-traffic
/talker@ba8b86aa803d(691) -> /listener@ba8b86aa803d(692) SHM 217 µs (max 254 µs) 1.0 0 measured=SHM 10pkt 1.31 kB same-host-guid,datasharing-disabled-writer,both-shm-locators,measured-shm-traffic
statistics: 448 samples from 5 participant(s)
shared memory: /dev/shm 37.4 MB used of 16.7 GB (16.6 GB free) | Fast DDS 3.90 MB in 6 segment(s), 11 port(s), 1 data-sharing history, 1 data-sharing notification(s)
The same capture on a terminal (--color auto, default when stdout is a terminal):
The same run opened in the web viewer (table view):
--stats, the measurement comes from the Fast DDS statistics module and shows
the transport that actually carried packets.--explain describes them.UDPv4, UDPv6, TCPv4/TCPv6, SHM, DATA_SHARING) with
machine-readable reason codes; the observed nodes need no change. Pairs whose QoS do
not match (reliability, durability, deadline, liveliness, ownership, partition) are
shown as NONE with the policy that breaks them.--stats. The Fast DDS statistics module supplies the packets and
bytes that actually flowed per locator, the write-to-notification
latency (LATENCY), the delivered samples per second of each pair (HZ), lost and
resent packets (LOSS), host names and process ids, and
the proof of zero-copy data-sharing; a measurement that contradicts the
prediction is flagged.--watch (live terminal view that marks
what changed), --json with a published schema, the ros2 transport command, and a
web viewer (graph and table, live updates through transport_viz_web with a timeline of
the frames received so far, and recordings made with transport_viz_web --record
replayed on the same timeline). transport_viz_web also serves the latest document as
Prometheus metrics on /metrics.--topic / --node regex filters, --explain for the codes in use,
--advise for what to change to get past them, ros2 transport codes for all of them./dev/shm, the Fast DDS segments,
ports and data-sharing histories in it, stale leftovers, and whether the observed nodes
share it at all.LARGE_DATA (TCP), UDPv6, LOCALHOST discovery range,
large SHM samples, zero-copy data-sharing, and two physical hosts (x86_64 ↔ Jetson Orin
NX over Wi-Fi, prediction and measurement in both directions).docker compose build
docker compose run --rm dev bash
colcon build --symlink-install && source build/$ROS_DISTRO/install/setup.bash
ros2 run demo_nodes_cpp talker &
ros2 run demo_nodes_cpp listener &
ros2 transport list -v --explain
Run the tool in the same environment (env vars, XML profile, network/IPC namespace) as the nodes you observe.
On a Linux host, releases from 2.1.0 on also run without a build, from the image on GHCR
(:humble, :jazzy, :lyrical; see Getting started):
docker run --rm --net host --ipc host ghcr.io/atinfinity/fastdds_transport_viz:jazzy ros2 transport list -v.
ros2 transport list [--domain N] [--timeout S] [--quiet S] [--topic REGEX] [--node REGEX]
[--all] [-v] [--explain] [--locators] [--advise] [--stats] [--json | --csv]
[--color auto|always|never] [--watch [--interval S]]
ros2 transport diff BEFORE.json AFTER.json [--key node|guid] [--changes-only] [--json]
[--topic REGEX] [--node REGEX] [--all] [-v] [--explain] [--locators]
[--advise] [--color auto|always|never]
ros2 transport codes
ros2 transport is a thin ros2cli extension (package ros2transport) that runs the
transport_viz binary of fastdds_transport_viz; the binary can also be run directly as
ros2 run fastdds_transport_viz transport_viz, with the same options plus --list-codes
(and transport_viz diff for ros2 transport diff).
| Option | Effect |
|---|---|
-v | expand writer → reader pairs under each topic |
--explain | append a legend for the reason codes used |
--locators | add a line under each pair with the locator the tool selected and the locators that actually carried packets (implies -v; ignored with --json, which always carries them) |
--advise | add a fix <code>: … line under each pair for its reason codes that have a remedy, and the remedy under each code of the legend (implies -v and --explain; ignored with --json, which always carries them as reason_code_remedies) |
--stats | also show measured transports, latency and loss; observed nodes need FASTDDS_STATISTICS, see docs/statistics.md |
--json | machine-readable output (schema_version: 1, see schema/); open it in the web viewer |
--csv | one CSV row per writer → reader pair (RFC 4180 quoting, LF line ends, a header line first; an empty cell where the JSON value is null, lists joined with ;), for a spreadsheet or pandas; exclusive with --json, not accepted by diff. With --watch the header is printed once and each frame adds its rows, observed_at telling the frames apart |
--topic REGEX | only topics whose name matches |
--node REGEX | only pairs involving a node whose full name matches (its unpaired endpoints stay visible) |
--all | include services/actions and non-ROS DDS topics; each service or action is one SERVICE / ACTION row per client-server pair rather than its raw rq/ / rr/ topics |
--watch |
ros2 transport diff BEFORE.json AFTER.json compares two saved --json documents (change
a profile or an environment variable, run again, see what moved) without observing
anything: the after snapshot is printed with the pairs that were added (+), changed (~)
or removed (-) marked as in --watch, or with --json as the after document plus a
changes object. Pairs are matched by node names (--key node, the default, so a restart
of the nodes is not a change) or by GUIDs (--key guid, what --watch does);
--changes-only keeps only the topics that moved. The exit status is 0 without changes, 1
with, 2 on an error, so it works in scripts. The web viewer compares two documents the same
way and highlights the result. Details in
docs/how-it-works.md.
--stats, watch mode, web viewer, first checks--stats) — statistics topics, enabling them, the 10-instance pitfallSHM by default and how to enable data-sharing--json output in the browser, live mode (transport_viz_web) and its history, recording and replay (--record), Prometheus /metrics, JSON schemarmw_fastrtps_cpp and rmw_fastrtps_dynamic_cpp are supported
(the launch test suite passes on both, see CI); nodes on CycloneDDS or Connext are not
covered, and Fast DDS participants that are not ROS nodes appear only with --all
(Discovery Servers, which have no endpoints, only in the participants section of
--json, the -v footer and the web viewer).
The tool refuses to start on another RMW (exit 1, naming it)./dev/shm, and Docker Desktop cannot observe nodes on the
host.ROS_AUTOMATIC_DISCOVERY_RANGE=OFF hides everything.NONE with type-name-mismatch, except on Fast DDS 3.x (Lyrical and
later) when both announce an XTypes TypeInformation that agrees: Fast DDS then matches
them regardless of the names, and the pair carries type-names-differ-same-type
(#213). Two versions
of the same message definition are told apart by the ROS 2 type hash (REP-2011), which
only the rmw of Jazzy and later announces: on Humble such a pair looks healthy, and the
subscription still receives nothing. Fast DDS's own, older type description cannot stand
in for it — measured on 2026-09-21, no Humble endpoint announces a TypeIdentifier, a
TypeObject or a TypeInformation either, because rmw_fastrtps registers no type in
the TypeObjectFactory those are filled from (Fast DDS 2.14, and so Jazzy, announces
them just as little; see docs/verification-log.md). On Humble, rebuild and reinstall every node
against the same version of the message package, and, if a machine with Jazzy or later is
available, run the same graph there, where the tool does report the mismatch.likely (marked ?) until --stats confirms them. Measuring requires
FASTDDS_STATISTICS on the observed nodes before they start, and the shipped profile
when a node talks to more than 10 locators.Both packages claim REP 2004 Quality Level 3,
with one exception: Linux only, so Windows 10 (a tier 1 platform of REP 2000) is not
supported. See the quality declarations of
fastdds_transport_viz and
ros2transport for the version policy and
public API, change control, testing, dependencies and platforms, and
SECURITY.md to report a vulnerability.
Apache-2.0
re-render every --interval seconds, highlighting added/changed/removed pairs; keys q p v e a l f (with --json: JSON Lines with a changes object) |
--color | ANSI colors for transports and warnings (auto = only on a terminal) |
LATENCY is Fast DDS's own HISTORY_LATENCY statistic
(write-to-notification between the two histories), sampled during a short observation; it
does not replace a load test or an end-to-end measurement, and across hosts it includes
the clock offset. HZ counts the samples that reached each reader
(#143); there is no
writer-side publish rate: PUBLICATION_THROUGHPUT looked like one but is not
(#137).fastdds_transport_viz_names, a participant without SHM that reads the node names); all
are filtered from the output.network_mode: host without ipc: host) still select SHM or data-sharing between each
other and lose every message. The pair is NONE with shm-ipc-namespace-split when the
tool can tell: the two announce the same SHM port number (shm-port-collision, the usual
case with one node per container), or the tool shares the IPC namespace of one of them
(their SHM ports or data-sharing segments are only half there). Otherwise the pair stays
SHM or DATA_SHARING and only shm-not-visible in the shared-memory line hints at it
(#101, #110).rmw_fastrtps_cpp sends the samples
of types with an unbounded uint8[] field over a companion topic <topic>/_buf_cpu. The
tool adds the companion's counters to the parent pair (buffer-companion-folded) and shows
the companion topic only with --all; a companion it cannot link to its parent stays
visible with buffer-companion-unmatched, and its parent pair then shows no traffic of its
own (#119).