Skip to content

feat(ros2-bridge): port to ros2-client 0.10.1 and RustDDS 0.14 - #2854

Merged
trunk-io[bot] merged 2 commits into
mainfrom
worktree-ros2-client-0.10-port
Aug 11, 2026
Merged

feat(ros2-bridge): port to ros2-client 0.10.1 and RustDDS 0.14#2854
trunk-io[bot] merged 2 commits into
mainfrom
worktree-ros2-client-0.10-port

Conversation

@bobdingAI

@bobdingAI bobdingAI commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Ports dora-ros2-bridge from ros2-client 0.8.0 / rustdds =0.11.4 to
ros2-client 0.10.1 / rustdds 0.14, removing the = pin on RustDDS. One
upgrade, not two: ros2-client 0.10.1 declares rustdds = "0.14".

No source changes were required. Every ros2-client symbol the bridge uses (~60
items) survives 0.8 → 0.10.1 — the public-surface diff is additions only
(distributions, pub use rustdds, Node::stop_spinner). The APIs that were
removed, QosPolicyBuilder::property() and the rustdds::CdrEncodingSize
re-export, were never referenced here.

ros2-client and cdr-encoding move into [workspace.dependencies] so the
bridge and its arrow helper cannot drift apart on the ROS distro.
cdr-encoding goes 0.10.2 → 0.11 to match what RustDDS depends on, leaving a
single copy in the lockfile.

Kept as two commits: the first is the original port (ros2-client 0.10.0 /
rustdds 0.13.1, with a Windows CI exclusion); the second moves it to
rustdds 0.14 and deletes that exclusion. Read the second commit alone to see
what changed.

No Windows workaround needed

The =0.11.4 pin was load-bearing: rustdds 0.11.5–0.13.x depended
unconditionally on pnet, whose pnet_datalink declares
#[link(name = "Packet")] under #[cfg(windows)], so Windows linking needed
Packet.lib from the Npcap SDK (RustDDS#375).

That is fixed upstream. RustDDS 92c9b117c
replaced pnet with netdev (which uses windows-sys and needs no SDK); it
shipped in rustdds 0.14.0, #375 is closed, and ros2-client 0.10.1
followed with rustdds ^0.14. So this PR needs no CI exclusions and no Windows
caveat in the docs — cargo tree -e normal --workspace --target x86_64-pc-windows-msvc resolves zero pnet* crates. That matters beyond
tidiness: excluding the bridge from Windows would have cancelled out #3092, the
mio 0.6.23 debug-assertions fix that stopped the bridge test binary aborting
there.

Needs review attention: the ROS distro is now explicit, and this picks humble

0.10 gained distro Cargo features (default = [jazzy], plus
galactic/humble/iron/kilted/lyrical); 0.8 only had a pre-iron-gid
opt-out. These select Gid width in ros2-client's src/gid.rs:

Build GID_LENGTH
0.8 as we shipped it (pre-iron-gid off) 16
0.10 with default = [jazzy] (jazzy ⊃ iron) 16
0.10 with humble (this PR) 24

This aligns the build with the distro our own harness runs
(scripts/ros2dev.sh, scripts/ros2-zenoh-interop.sh). Previously we emitted
iron-era 16-byte Gids while testing against a 24-byte-Gid distro.

It is a deliberate wire-format change. It affects rmw_dds_common graph
discovery only — topic, service, and action payloads are ordinary CDR and
interoperate across distros either way. Anyone doing graph introspection
against an iron-or-newer stack is affected. Happy to split it out or switch to
a feature passthrough (ros-humble / ros-jazzy / …) if you'd rather.

Verification

On Linux, no ROS distro installed:

  • cargo fmt --all -- --check — clean
  • cargo clippy --lib --bins --tests -- -D warnings on the four bridge crates — clean
  • cargo check --examples — clean
  • cargo check --target x86_64-pc-windows-gnu on the bridge and bridge node — clean, so the Windows compile path (including netdev's) builds
  • bridge tests — 18 + 19 passed, 0 failed
  • full workspace cargo test --all (CLAUDE.md exclude list) — see comment below
  • cargo deny check licenses advisories bans sources — all ok
  • Cargo.lock shrinks by 70 lines net: the netdev tree is smaller than pnet's, and mio_08/socketpair leave the graph

Carried over from the earlier revision of this PR (validated at ros2-client
0.10.0 / rustdds 0.13.1 against a real /opt/ros/humble), not re-run on
0.10.1 / 0.14.1: live interop against ros2 run demo_nodes_cpp talker, where
the humble build was listed by ros2 node list with a 24-octet GID and the
counterfactual jazzy build was invisible to graph introspection while still
exchanging 3/3 payloads. The distro feature set is identical between 0.10.0 and
0.10.1, so that result carries.

Not verified: an actual Windows link — no Windows host available, and
cargo check does not link. The known blocker is structurally absent now, and
the nightly test-cross-platform job builds and tests the bridge on Windows,
so a nightly run is the confirmation.

docs/superpowers/specs/2026-07-26-ros2-client-0.10-port-design.md records the
investigation and the alternatives that the upstream release made unnecessary.

@trunk-io

trunk-io Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

😎 Merged successfully - details.

Copy link
Copy Markdown
Collaborator

🤖 Fully automated review by Claude — this review was generated end-to-end by an automated agent with no human vetting. Treat it accordingly.

No issues found. This is a manifest + CI + docs change with no source edits.

Points I verified from the diff:

  • The nightly.yml matrix conversion from platform: [...] to an include:-only list with a per-platform ros2_excludes is valid (one job per include entry; fail-fast: false preserved), and macOS keeps full bridge coverage with an empty excludes string.
  • The Windows exclusion set (dora-ros2-bridge, -arrow, -node, rust-ros2-example-node) is the RustDDS-linking set; msg-gen, dora-cli, dora-daemon stay covered, and the cargo check steps are correctly left unexcluded since Packet.lib is link-time only.
  • Moving ros2-client / cdr-encoding to [workspace.dependencies] removes the drift risk between the bridge and arrow crates, and Cargo.lock resolves a single cdr-encoding 0.11.

The two riding behavior changes — selecting humble (24-byte Gid, affecting rmw_dds_common graph discovery only) and dropping Windows bridge coverage — are deliberate and clearly flagged. My only caveat is the one you already called out: the Windows link failure and the exclusion that avoids it are reasoned, not verified by a green Windows run, so they need a nightly to confirm.


Generated by Claude Code

@phil-opp

Copy link
Copy Markdown
Collaborator

See #2450

@phil-opp

Copy link
Copy Markdown
Collaborator

Let's wait until Atostek/RustDDS@92c9b117c is released, then the Windows exclude should no longer be needed.

@jhelovuo

jhelovuo commented Aug 5, 2026

Copy link
Copy Markdown

RustDDS 0.14.0 was released yesterday.

phil-opp added a commit that referenced this pull request Aug 9, 2026
mio 0.6.23 computes field offsets with the pre-`offset_of!` idiom
`&(*(0 as *const T)).field as *const _ as usize`. Its Windows IOCP
completion handlers run that on every UDP/TCP completion, so with
debug assertions on, rustc's null-pointer check fires a non-unwinding
panic and aborts the process. That killed the `dora-ros2-bridge` test
binary in the Windows nightly as soon as
`context_new_dds_uses_requested_domain` brought up a RustDDS participant.

mio 0.6 cannot be upgraded away: `mio_06 = "^0.6.23"` is a non-optional
direct dependency of every published rustdds (0.14.0 included) and of
ros2-client 0.8-0.10, so the #2854 port does not remove it. Opt just that
dependency out of debug assertions instead; release builds already
behave this way.

Fixes #3091

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
trunk-io Bot pushed a commit that referenced this pull request Aug 9, 2026
…ts (#3092)

mio 0.6.23 computes field offsets with the pre-`offset_of!` idiom
`&(*(0 as *const T)).field as *const _ as usize`. Its Windows IOCP
completion handlers run that on every UDP/TCP completion, so with
debug assertions on, rustc's null-pointer check fires a non-unwinding
panic and aborts the process. That killed the `dora-ros2-bridge` test
binary in the Windows nightly as soon as
`context_new_dds_uses_requested_domain` brought up a RustDDS participant.

mio 0.6 cannot be upgraded away: `mio_06 = "^0.6.23"` is a non-optional
direct dependency of every published rustdds (0.14.0 included) and of
ros2-client 0.8-0.10, so the #2854 port does not remove it. Opt just that
dependency out of debug assertions instead; release builds already
behave this way.

Fixes #3091

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@phil-opp
phil-opp force-pushed the worktree-ros2-client-0.10-port branch from 1705129 to 9d2990e Compare August 11, 2026 17:34
@phil-opp phil-opp changed the title feat(ros2-bridge): port to ros2-client 0.10.0 and RustDDS 0.13.1 feat(ros2-bridge): port to ros2-client 0.10.1 and RustDDS 0.14 Aug 11, 2026
@phil-opp

Copy link
Copy Markdown
Collaborator

The rustdds/ros2-client deps were updates so that the Windows workaround is no longer needed. I pushed an update and updated the description.

bdingfd and others added 2 commits August 11, 2026 17:37
Bumps `dora-ros2-bridge` from ros2-client 0.8.0 / rustdds =0.11.4 to
ros2-client 0.10.0 / rustdds 0.13.1, and lifts the `=` pin on RustDDS.
The two are one upgrade: ros2-client 0.10 declares `rustdds = "0.13"`.

No source changes were required. Every ros2-client symbol the bridge uses
survives 0.8 -> 0.10 (the public-surface diff is additions only), and the
removed APIs — `QosPolicyBuilder::property()` and the
`rustdds::CdrEncodingSize` re-export — were never referenced here.

`ros2-client` and `cdr-encoding` move to `[workspace.dependencies]` so the
bridge and its arrow helper cannot drift apart on the ROS distro.
`cdr-encoding` goes 0.10.2 -> 0.11 to match what RustDDS 0.13 depends on,
leaving a single copy in the lockfile; its only API change tightens
`from_bytes` to `&'de [u8]`, and every call site here yields owned types.

Two consequences worth review attention:

ROS distro is now explicit. 0.10 gained distro features (0.8 only had a
`pre-iron-gid` opt-out), and they select `Gid` width. This builds with
`humble`, giving a 24-byte `Gid` where the previous build had 16 — a
deliberate wire change that aligns the build with the distro our harness
actually runs (`scripts/ros2dev.sh`). It affects `rmw_dds_common` graph
discovery only; topic/service/action payloads are untouched.

Windows is excluded rather than fixed. RustDDS 0.11.5+ depends
unconditionally on `pnet`, whose `pnet_datalink` declares
`#[link(name = "Packet")]` on Windows, so linking needs the Npcap SDK
(Atostek/RustDDS#375, still open — this was the reason for the pin). The
four crates that transitively pull RustDDS are excluded from the Windows
build/test steps in nightly.yml. `Packet.lib` is link-time only, so the
`cargo check` steps and the `cross-check` job's windows-gnu target are
unaffected and stay as they were. The durable fix is upstreaming an
optional-`pnet` feature — RustDDS needs it for one
`pnet::datalink::interfaces()` call.

Verified on Linux against a real ROS 2 Humble install: fmt, clippy
-D warnings, `cargo check --examples`, 110 bridge tests, 1543 workspace
tests, and `cargo deny check licenses advisories bans sources` all pass.
Live interop against `demo_nodes_cpp talker` receives messages and shows
the dora node in `ros2 node list` with a 24-octet GID; the same probe
built with the `jazzy` default is absent from `ros2 node list` while still
receiving payloads, confirming the Gid width governs graph discovery only.

The Windows link failure and the exclusion that avoids it are NOT verified
here — no Windows host was available. That needs a nightly run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rebases the port onto the upstream fix. When the previous commit was
written, ros2-client 0.10.0 required rustdds ^0.13, and every rustdds in
that range depended unconditionally on `pnet`, whose `pnet_datalink` links
`Packet.lib` on Windows (Atostek/RustDDS#375) -- hence the CI exclusion.

RustDDS 92c9b117c replaced `pnet` with `netdev`, which uses `windows-sys`
and needs no npcap SDK. That shipped in rustdds 0.14.0, #375 is closed, and
ros2-client 0.10.1 followed with `rustdds ^0.14`. So:

- ros2-client 0.10.0 -> 0.10.1, rustdds 0.13.1 -> 0.14
- the `ros2_excludes` matrix variable and its four `--exclude` flags go
  away, so nightly builds and tests the bridge on Windows again
- the Windows caveat leaves docs/ros2-bridge.md, keeping only the distro
  note

Restoring that coverage matters beyond tidiness: the exclusion would have
cancelled out #3092, the mio 0.6.23 debug-assertions fix that stopped the
bridge test binary aborting on Windows. mio 0.6.23 is still a non-optional
transitive dependency under rustdds 0.14, so that workaround stays.

Verified: `cargo tree -e normal --workspace --target
x86_64-pc-windows-msvc` resolves zero `pnet*` crates; `cargo check --target
x86_64-pc-windows-gnu` on the bridge and bridge node is clean; fmt, clippy
-D warnings on the bridge crates, and `cargo check --examples` are clean;
`cargo deny check licenses advisories bans sources` all ok; workspace tests
1854 passed / 2 failed, both pre-existing no-multicast rmw_zenoh cases that
fail identically on main. `Cargo.lock` shrinks 70 lines net.

Not verified: an actual Windows link -- no Windows host available, and
`cargo check` does not link. A nightly run is the confirmation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@phil-opp
phil-opp force-pushed the worktree-ros2-client-0.10-port branch from 9d2990e to dfe7dd9 Compare August 11, 2026 17:41
@phil-opp

Copy link
Copy Markdown
Collaborator

@bobdingAI I rebased this onto main and pushed a second commit on top of yours,
so the delta is easy to read in isolation.

The short version: the Windows problem solved itself upstream. RustDDS
92c9b117c replaced pnet
with netdev (uses windows-sys, no npcap SDK), that shipped in rustdds
0.14.0
, #375 is closed, and
ros2-client 0.10.1 followed with rustdds ^0.14. So the second commit moves
0.10.0/0.13.1 → 0.10.1/0.14 and deletes the ros2_excludes matrix variable
entirely — cargo tree -e normal --workspace --target x86_64-pc-windows-msvc
resolves zero pnet* crates, and nightly builds and tests the bridge on Windows
again. That last part matters more than tidiness: the exclusion would have
cancelled out #3092, the mio 0.6.23 debug-assertions fix that stopped the
bridge test binary aborting there.

The open question is the one this PR already flags: the humble distro
feature.
It selects a 24-byte Gid where the current build emits 16, which
changes rmw_dds_common graph-discovery wire compatibility. The live-interop
run recorded in the PR description is what establishes that this is
discovery-only — payloads interoperate either way. I did not re-run it on
0.10.1/0.14.1; the distro feature set is identical between 0.10.0 and 0.10.1,
so that result should carry, but it is carried over rather than re-verified.

We might want to add a Feature passthrough as a follow-up — ros-humble / ros-jazzy / … on dora-ros2-bridge,
so downstreams choose.

🤖 Generated with Claude Code

@trunk-io
trunk-io Bot merged commit 1f06dca into main Aug 11, 2026
16 checks passed
@trunk-io
trunk-io Bot deleted the worktree-ros2-client-0.10-port branch August 11, 2026 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(deps): lift rustdds =0.11.4 pin + bump ros2-client once RustDDS#375 is fixed

4 participants