feat(LibCarla/ros2): [1/7] add DDS middleware abstraction layer for multi-vendor support - #9608
Conversation
…ackend support Introduce a strategy-pattern abstraction that decouples PublisherImpl and SubscriberImpl from the FastDDS API, enabling future integration of additional DDS middleware implementations (e.g. CycloneDDS). New abstraction layer (LibCarla/source/carla/ros2/dds/): - DDSMiddleware enum and string conversion utilities - IDDSPublisherMiddleware / IDDSSubscriberMiddleware pure virtual interfaces - DDSMiddlewareFactory with thread-safe middleware selection and creation - FastDDSPublisherMiddleware<T> / FastDDSSubscriberMiddleware<S> template implementations behind the new interfaces - FastDDSTypeMap<T> identity-mapping type traits (to be replaced with real conversions when POD message types are introduced) Modified files: - PublisherImpl.h: replaced direct FastDDS inheritance and members with delegation to IDDSPublisherMiddleware via the factory (public API unchanged) - SubscriberImpl.h: same pattern for subscriber side - cmake/fast_dds/CMakeLists.txt: added CARLA_ROS2_DDS_FASTDDS compile definition, new header globs, and fixed missing include directories in the debug build target No behavior change — FastDDS remains the only compiled middleware. Concrete publishers and subscribers are unaffected.
|
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. |
d89cf2d to
0ab35ee
Compare
|
The smoke tests in the Ubuntu CI/CD are failing, but I'm not sure if this is an internal problem with the GitHub Actions, since I ran the same tests locally and all of them passed without problems. https://github.com/carla-simulator/carla/actions/runs/23674779274/job/69127370062?pr=9608 |
|
Hi to the review team, The DDS middleware decoupling series tracked in #9294 is now complete. All 7 PRs in the chain are pushed, compile cleanly, pass unit and smoke tests, and build a full package. I would like to request a formal review. GoalDecouple CARLA's native ROS2 integration from FastDDS so that a second DDS middleware (CycloneDDS) can be selected at runtime, without duplicating any publisher or subscriber code. End users will be able to pick their middleware with StrategyThe approach is a strategy pattern with unified CDR serialization. Publishers and subscribers never see a DDS vendor type. Instead:
The key simplification is that neither backend needs per-vendor generated type files. One CDR serializer, one POD struct per message, two thin transport adapters. How to navigate the seriesThe PRs are linear, each branch contains every prior commit. Review them in order. Each PR description now carries the same "PR series" table with commit IDs and file counts so you can see at a glance which commits are new to each PR.
Suggested reading order: review 1/7 and 2/7 together (they set up the abstraction and type layer), then 3/7 (mechanical migration, zero behavior change), then 4/7 (small, just registers CycloneDDS). PRs 5/7 and 6/7 contain the core of the new serialization and CycloneDDS transport, they are the most interesting. 7/7 is a pure cleanup of dead code. Status and testing
Thanks for the review. |
|
As a ROS 2 developer, I am very excited about the DDS multi-vendor support here and look forward to using it soon. However, I have a question regarding the CARLA community's focus. Why is the community currently concentrating its maintenance efforts on the |
|
Hi @youtalk, I'm glad you see value in this effort to add multipurpose DDS support, just as I do. Regarding your comments, I can't speak for everyone who actively contributes to Carla. But I do believe that the |
|
@JesusAnaya Thank you for your quick response!
This feedback was a very important notice for me. |
|
From me the code looks fine. I will add someone to have a look and test, could we add tests in the near future PRs? |
|
Hello @Blyron, I added new unit tests and smoke tests in the subsequent PRs to this one. But I can see how to add a unit test to this one too if you require it. This pull request series (7 in total) is thought to be merged all, and they are complementing the changes in each step. |
|
I have seen those. For this step we are ok. But in next steps we will need more exhaustive tests for incoming PRs related with ROS2 |
|
@Blyron, great! Thanks. I'll check any comments in the code review in case the team requests any changes. |
LuisPovedaCano
left a comment
There was a problem hiding this comment.
Code looks good.
I have tested it.
Merging. I will look for your next PR.
Introduce the vendor-neutral middleware strategy layer of the ROS 2 middleware decoupling series and its FastDDS implementation, compiled into libcarla-ros2-native.so. Ported from ue4-dev: - middleware/Middleware.h: the Middleware enum plus the string and ROS 2 type-name helpers; the CycloneDDS value and its availability branches are present but stay compiled out until the CycloneDDS middleware lands (upstream ue4-dev #9608). - middleware/IPublisherMiddleware.h, ISubscriberMiddleware.h: the type-erased publisher/subscriber strategy interfaces. Subscribers write received samples straight into caller-owned storage to avoid a copy (upstream ue4-dev #9608). - middleware/MiddlewareFactory.h: creates the active middleware for a traits type; each vendor arm is double-gated on its CARLA_ROS2_MIDDLEWARE_* macro and CARLA_ROS2_MIDDLEWARE_TESTING so the suite exercises the availability logic without linking DDS (upstream ue4-dev #9608). - middleware/ActiveMiddleware.{h,cpp}: a DDS-free bridge (SetActiveMiddleware) so ROS2.cpp, the only ROS 2 translation unit in carla-server, can select the middleware without any DDS header crossing the shared-library boundary. Nothing calls it until the cutover; the definition ships now so the shared lib has a translation unit that compiles MiddlewareFactory.h and the FastDDS headers with the real vendor macros. - middleware/fastdds/GenericCdrPubSubType.h: one FastDDS TopicDataType that serializes every carla::ros2::msg::* struct through the unified CdrSerialization.h path, replacing the generated per-type PubSubType classes; getSerializedSizeProvider reports the actual instance size so variable-length payloads (camera frames, point clouds) are not bounded by the static max size (upstream ue4-dev #9643). - middleware/fastdds/FastDDS{Publisher,Subscriber}Middleware.h: the FastDDS strategy implementations. Each endpoint advertises the REP-2016 "typehash=RIHS01_<hex>;" USER_DATA so Jazzy RMWs match on the REP-2011 type hash (upstream ue4-dev #9681). - middleware/fastdds/FastDDSSharedParticipant.{h,cpp}: a refcounted process-wide DomainParticipant shared across all FastDDS endpoints, avoiding the discovery storm that destroying N participants back to back caused on shutdown (upstream ue4-dev #9681). UE5 adaptation: ue5-dev pins FastDDS 2.11.2 with bundled Fast-CDR 1.x, so GenericCdrPubSubType.h keeps the Fast-CDR 1.x spellings (eprosima::fastcdr::Cdr::DDS_CDR, getSerializedDataLength()) matching CdrSerialization.h from the previous PR of the series. The wire format is classic CDR little-endian and is unchanged. The existing publishers keep using the generated FastDDS types; the cutover to this abstraction and the PublisherImpl/SubscriberImpl rewrite land in the next PR of the series. No behavior change. (adapted from ue4-dev 82c28e2) (adapted from ue4-dev f53144c) (adapted from ue4-dev 02a83ef) (adapted from ue4-dev c64e8f4) (cherry picked from commit f6d9a5b)
Introduce a strategy-pattern abstraction that decouples PublisherImpl and SubscriberImpl from the FastDDS API, enabling future integration of additional DDS middleware implementations (e.g. CycloneDDS).
New abstraction layer (LibCarla/source/carla/ros2/dds/):
Modified files:
No behavior change - FastDDS remains the only compiled middleware. Concrete publishers and subscribers are unaffected.
Description
This PR introduces a DDS middleware abstraction layer that decouples
PublisherImplandSubscriberImplfrom the FastDDS API, laying the groundwork for supporting multiple DDS middleware implementations in CARLA's native ROS2 integration.This is the first in a series of PRs that incrementally implements the decoupled DDS middleware architecture originally prototyped in draft PR #9589. The end goal is to support multiple DDS backends, starting with CycloneDDS, so users can choose the most appropriate middleware for their deployment.
These changes do not affect current behavior. FastDDS remains the only compiled middleware, and all concrete publishers and subscribers remain unchanged.
What's new
Abstraction layer (
LibCarla/source/carla/ros2/dds/):DDSMiddleware- enum and string conversion utilities for middleware selectionIDDSPublisherMiddleware/IDDSSubscriberMiddleware- type-erased pure virtual interfacesDDSMiddlewareFactory- static factory with thread-safe middleware selection and creation viaSetMiddleware(),CreatePublisher<T>(), andCreateSubscriber<S>()FastDDSPublisherMiddleware<T>/FastDDSSubscriberMiddleware<S>- FastDDS implementations behind the new interfacesFastDDSTypeMap<T>- identity-mapping type traits that will be replaced with real conversions when POD message types are introduced in a future PRModified files:
PublisherImpl.h- removed direct FastDDS inheritance and raw DDS entity members; now delegates tostd::unique_ptr<IDDSPublisherMiddleware>via the factory while keeping the public API unchangedSubscriberImpl.h- same delegation pattern for the subscriber sidecmake/fast_dds/CMakeLists.txt- addedCARLA_ROS2_DDS_FASTDDScompile definition for both release and debug targets, added new header globs fordds/anddds/fastdds/, and fixed pre-existing missing include directories in the debug build targetDesign decisions
RMW= ROS Middleware)msg_typeis currently already the FastDDS type; this will evolve into real conversion logic once POD message types are introducedPR series
This PR is part of the DDS middleware decoupling series (#9294). Each PR in the chain inherits the commits of all prior PRs. The Commits column lists only the commits introduced by that PR, and the Files column counts only the files changed by those new commits.
feature/dds-middleware-abstraction-layer0ab35ee6feature/ros2-pod-types-and-fastdds-conversionse665d2affeature/ros2-publishers-pod-types-migration98b6f7aafeature/ros2-cyclonedds-enum-factory2a4a8db3GenericCdrPubSubTypefeature/ros2-cdr-serialization5a9dd3b4,0a9ca585feature/ros2-cyclonedds-cdr-middlewared3f2a45b,2d80046bfeature/ros2-remove-fastdds-generated-typeseea4e0a4Related
Fixes #9294
Where has this been tested?
Possible Drawbacks
Compilation steps
Test plan
make LibCarla ARGS="--ros2"compiles successfully (release build)make check.LibCarlapasses (no regressions)PublisherImpl.handSubscriberImpl.h)This change is