Repository navigation
fix(rtps): interoperate with CycloneDDS peers (ROS 2 rmw_cyclonedds_cpp) - #862
Merged
alexchunlin merged 3 commits intoOct 30, 2026
Merged
Conversation
The interop matrix only ran the ROS 2 pairs on rmw_fastrtps_cpp. Add
rmw_cyclonedds_cpp to the harness image and run the pub/sub pairs (reliable and
best-effort, both directions) again on CycloneDDS. Services are left out:
rmw_cyclonedds_cpp correlates requests with a {guid, seq} header in the
payload, not the related_sample_identity inline QoS espp uses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Four defects stopped samples between espp and a CycloneDDS participant (ROS 2 rmw_cyclonedds_cpp). FastDDS tolerates all four. - HEARTBEAT and GAP addressed to readerId ENTITYID_UNKNOWN were dropped. CycloneDDS addresses its SEDP and user-data heartbeats that way, so espp never NACKed and never received SEDP data. Resolve the reader through the matched writer, as the DATA path already does. - ACKNACKs had no INFO_DST and echoed the incoming readerId. CycloneDDS resolves the writer by (destination prefix, writerId), so it ignored them. Add INFO_DST and use the reader's own entity id. - The pre-emptive ACKNACK used sequence base 0. RTPS 8.3.5.5 requires >= 1; CycloneDDS patches base 0 only for eProsima and RTI vendor ids and logs "malformed packet received from vendor 13.37" for espp. - SEDP samples without PID_UNICAST_LOCATOR (CycloneDDS omits it) kept the TopicData constructor's placeholder address. Reset the locators before parsing and fall back to the participant's default unicast locator. Co-authored-by: ewang360 <61071212+ewang360@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
✅Static analysis result - no issues found! ✅ |
cppcheck useStlAlgorithm on SEDPAgent.cpp:114. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
alexchunlin
marked this pull request as ready for review
October 29, 2026 22:52
finger563
approved these changes
Oct 29, 2026
alexchunlin
added a commit
to rammp-org/RAMMP-mib-fw
that referenced
this pull request
Oct 30, 2026
esp-cpp/espp#862 is in 1.3.11. With 1.3.10 and older the Jetson (ROS 2 on rmw_cyclonedds_cpp) and the MIB exchange no samples. docs/ros2.md follows, and lists PUSH_ASSIST with the states reported as ENABLED. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Four defects in
components/rtpsstop every sample between espp and a CycloneDDS participant, including ROS 2 onrmw_cyclonedds_cpp. FastDDS tolerates all four, so the existing interop matrix never caught them.ENTITYID_UNKNOWNwere dropped (MessageReceiver.cpp). CycloneDDS addresses its SEDP and user-data heartbeats to the participant, not to one reader (RTPS 2.5 8.3.7.5). espp looked up a reader by id 0, found none, and never NACKed, so it never received the SEDP data. The reader is now resolved through the matched writer, as the DATA path already does.INFO_DSTand echoed the incomingreaderId(StatefulReader.cpp). CycloneDDS resolves the writer by (destination prefix,writerId), so it ignored them. The ACKNACKs now carryINFO_DSTand the reader's own entity id.StatefulReader.cpp). RTPS 8.3.5.5 requires a base of at least 1. CycloneDDS'svalidate_AckNackrepairs base 0 only for eProsima and RTI vendor ids, so for espp (vendor 13.37) it logsmalformed packet received from vendor 13.37and drops the message. The base is now 1.PID_UNICAST_LOCATORkept a placeholder address (TopicData.cpp,SEDPAgent.cpp). CycloneDDS leaves the per-endpoint locator out, which RTPS 2.5 8.5.3.2 allows: the participant's default locator applies.TopicData's constructor pre-fills a placeholder address, andreadFromBuffer()never reset it, so samples went to that address. The locators are now reset before parsing, and an endpoint without one falls back to its participant's default unicast locator.The interop harness (
components/rtps/interop) now installsrmw_cyclonedds_cppand runs the ROS 2 pub/sub pairs a second time on CycloneDDS: reliable and best-effort, in both directions.Motivation and Context
ROS 2 on CycloneDDS can't exchange any sample with espp.
ros2 topic listshows the espp topics, butros2 topic echostays silent, and nothing published from ROS 2 arrives. We hit this between an ESP32-P4 board and a Jetson running ROS 2 Humble onrmw_cyclonedds_cpp.This reproduces in the harness's container, where multicast always works, and the same container passes every FastDDS pair while failing in Cyclone
@ewang360 found and root-caused these four defects on the robot. This PR carries her patch unchanged, adds the harness cases, and adds the measurements below.
Not in this PR: services over
rmw_cyclonedds_cpp. rmw_cyclonedds_cpp correlates requests with a{guid, seq}header at the start of the payload (cdds_request_header_t). It doesn't use therelated_sample_identityinline QoS that espp's services and rmw_fastrtps_cpp use. With this PR, both service pairs still fail on CycloneDDS:ros2 service callnever gets a reply, and the espp client gets0back. That needs its own change, so the harness leaves the service pairs out of the CycloneDDS run.How has this been tested?
Interop harness (
components/rtps/interop/run.sh, Docker on an Apple Silicon Mac,ros:jazzy-ros-base, CycloneDDS 0.10.5):malformed packetlinesmainThe golden wire-format test still passes.
Hardware:
main.rmw_cyclonedds_cpp1.3.4 with CycloneDDS 0.10.5.Each row is one flash of the board. The full patch and stock were each run 3 times, with the same result each time.
ros2 topic echo)malformed packeton the JetsonENTITYID_UNKNOWNfixINFO_DSTand the reader idSo the first, second and fourth fixes are each needed for delivery. Base 1 is what removes the
malformed packetwarnings, and it's what the spec requires.Screenshots (if appropriate, e.g. schematic, board, console logs, lab pictures):
On the Jetson, against stock 1.3.10:
Types of changes
Checklist:
Software
.github/workflows/build.ymlfile to add my new test to the automated cloud build github action. (Not needed: the new cases are in the interop harness, whichrtps_interop.ymlalready runs on everycomponents/rtps/**change.)🤖 Generated with Claude Code