refactor(ros2): decouple DDS middleware and add CycloneDDS backend#9589
refactor(ros2): decouple DDS middleware and add CycloneDDS backend#9589JesusAnaya wants to merge 1 commit intocarla-simulator:ue4-devfrom
Conversation
Refactors the ROS2 native integration in LibCarla to decouple the transport layer from FastDDS, introducing a strategy-pattern abstraction that supports multiple DDS backends simultaneously. CycloneDDS is added as a second supported backend alongside FastDDS. The backend is selected at build time via --included-dds=fastdds,cyclonedds and resolved at runtime through DDSBackendFactory. The abstraction is designed to be open to additional backends (e.g. OpenDDS) without modifying the publisher/subscriber logic. This refactoring was driven by the need of multiple CARLA community teams to work with CycloneDDS instead of FastDDS in their ROS2 workflows. See: carla-simulator#9294 Key changes: - New DDS abstraction layer: DDSBackend enum, DDSBackendFactory, IDDSPublisherBackend and IDDSSubscriberBackend interfaces - FastDDS extracted into FastDDSPublisherBackend / FastDDSSubscriberBackend - CycloneDDS backend added: IDL-generated C type bindings, native serialization via dds_topic_descriptor_t, CycloneDDSConversions.h - PublisherImpl<T> and SubscriberImpl<S> delegate to backends via factory - 30 ROS2 type headers guarded with CARLA_ROS2_DDS_FASTDDS; POD msg structs and per-backend type maps added for independent serialization - Build system updated: Setup.sh, BuildLibCarla.sh, Vars.mk, CMake files - UE4 integration: CarlaSettings parses --dds-backend arg, CarlaEngine passes it to ROS2::Enable(), Carla.Build.cs reads included_dds_backends.txt - 61 unit tests in test_dds_backend.cpp covering factory, interfaces, backend resolution, enum/string conversion, and available-backends query - Fixed ROS2.cpp: restore ESensors enum values in GetOrCreateSensor() calls (sensor_type is a stream ID, not an enum value) - Windows build scripts left unchanged; Windows supports FastDDS only
|
Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would update our CHANGELOG.md based on your changes. |
|
Hi, thanks for sharing this PR — the DDS abstraction looks like a clean way to support CycloneDDS while keeping the current architecture. I'm curious about one design choice: did you consider moving the abstraction to the ROS2 layer (e.g., using rclcpp + rmw) instead of directly at the DDS layer? I've been experimenting with that approach on our side (based on the ue5-dev branch), and it seems feasible to integrate with CARLA as well. It could potentially allow switching middleware through RMW implementations. I'm wondering what trade-offs led you to stay at the DDS layer — for example, dependency concerns or integration complexity. Would love to hear your thoughts — thanks! |
|
Hi @JesusAnaya First of all, thank you so much for your interest in contributing to CARLA! We really appreciate the time and effort you’ve put into this. However, we’ve noticed this PR is quite large (40+ files/changes), which makes it very difficult for us to perform a thorough and high-quality review. To ensure we don't miss anything and to speed up the merging process, could you please break this down into smaller, more focused PRs? Small, incremental changes are much easier for the maintainers to digest and get merged quickly. Best, |
|
@habby1012 Hi, thank you very much for your comment. The proposal you mentioned sounds interesting. I'm personally working on this refactoring because I'm interested in making Carla compatible with other DDS middleware for personal projects, without having to propose such a large architecture change. I don't know if the Carla Core team plans to make changes of this kind in the future, but I think that for now, given the way the server is designed, keeping DDS as an internal library might be the easiest way to integrate ROS. I imagine that maintaining the current integrity and supporting ROS in the simplest way possible for project maintenance is one of the priorities, but it's something that can be discussed, I suppose, although it would have to be discussed with more people within the core team to see if there are plans to achieve this or something similar to what you mentioned in the long term. |
Thank you so much for your comment. What you're saying makes perfect sense. It's just that when I was making the changes, I realized that to achieve my goal, I had to make all those modifications. Let me take a step back and go back to a previous version where I made the fewest changes and see how we can start from there. I'll try to make the fewest possible changes for this first iteration, and then I'll submit iterations of my proposed changes in subsequent pull requests, as you mentioned. |
Description
I'd like to start by saying that I genuinely hope the team sees value in this proposal. This refactoring was born out of a real need I have myself, and one I've seen shared by others in the community, particularly teams working with Autoware and similar ROS2-based projects that rely on CycloneDDS rather than FastDDS. Right now, CARLA's ROS2 integration is tightly coupled to FastDDS, which blocks those workflows entirely.
This PR introduces a clean abstraction layer that solves that problem today with CycloneDDS support, and opens the door for additional DDS backends in the future, without touching publisher/subscriber logic. I think this is a net positive for the project's ecosystem, and I'd love to hear the team's thoughts.
Refactors the ROS2 native integration in LibCarla to decouple the transport layer from FastDDS, introducing a strategy-pattern abstraction that supports multiple DDS backends simultaneously. CycloneDDS is added as a second supported backend alongside FastDDS.
The backend is selected at build time via
--included-dds=fastdds,cycloneddsand resolved at runtime throughDDSBackendFactory. The abstraction is designed to be open to additional backends (e.g. OpenDDS) without modifying the publisher/subscriber logic.This refactoring was driven by the need of multiple CARLA community teams to work with CycloneDDS instead of FastDDS in their ROS2 workflows.
Key changes:
DDSBackendenum,DDSBackendFactory,IDDSPublisherBackendandIDDSSubscriberBackendinterfacesFastDDSPublisherBackend/FastDDSSubscriberBackenddds_topic_descriptor_t,CycloneDDSConversions.hPublisherImpl<T>andSubscriberImpl<S>delegate to backends via factoryCARLA_ROS2_DDS_FASTDDS; POD msg structs and per-backend type maps added for independent serializationSetup.sh,BuildLibCarla.sh,Vars.mk, CMake filesCarlaSettingsparses--dds-backendarg,CarlaEnginepasses it toROS2::Enable(),Carla.Build.csreadsincluded_dds_backends.txttest_dds_backend.cppcovering factory, interfaces, backend resolution, enum/string conversion, and available-backends queryFixes #9294
How to Build & Test
The following steps build CARLA with both FastDDS and CycloneDDS backends enabled.
--included-dds=fastdds,cycloneddscompiles both into separate static libraries (libcarla_fastdds.aandlibcarla_cyclonedds.a). At runtime, the active backend is selected via--dds-backend=<fastdds|cyclonedds>.Each step pipes output to a numbered log file for easier debugging if something goes wrong.
Status & Call for Testing
This PR is currently a draft. Linux testing has been completed, but Windows support still needs to be validated. I plan to test the Windows build myself this week to confirm that FastDDS remains stable under the new abstraction.
In the meantime, I'd love for others to try this out. If you run into any issues, have suggestions, or want to propose changes, please feel free to:
The goal is to iterate together until we have a version that's solid enough to merge. I'm very open to feedback on both the architecture and the implementation details.
Where has this been tested?
Possible Drawbacks
This change is