Skip to content

feat(LibCarla/ros2): [1/3] add publisher durability QoS and latched OpenDRIVE map topic#9786

Open
JArmandoAnaya wants to merge 7 commits into
carla-simulator:ue4-devfrom
JArmandoAnaya:feature/ros2-qos-durability-and-map
Open

feat(LibCarla/ros2): [1/3] add publisher durability QoS and latched OpenDRIVE map topic#9786
JArmandoAnaya wants to merge 7 commits into
carla-simulator:ue4-devfrom
JArmandoAnaya:feature/ros2-qos-durability-and-map

Conversation

@JArmandoAnaya

@JArmandoAnaya JArmandoAnaya commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Is recommended merge this PR after #9778

Description

The native ROS 2 interface streams sensor data well, but everything it publishes is volatile: a node that joins after the simulation has started has no way to learn anything about the world it is observing. The most basic piece of that picture is the map itself.

This PR teaches the publisher layer about durability. A publisher can now request transient local delivery, and each middleware (FastDDS, CycloneDDS and Zenoh) translates that into its own QoS, so the last sample is retained and delivered to late-joining subscribers. The default behavior of every existing topic is unchanged.

The first topic built on top of it is /carla/map, which carries the full OpenDRIVE description of the current map and is refreshed on every map load. Any ROS 2 node can read it at any time, with no connection to the simulator:

ros2 topic echo --qos-durability transient_local --once /carla/map

To show what that enables, the PR also adds a small example. A single command runs a demo stack in Docker against a server started with --ros2: it spawns the hero vehicle on autopilot, converts the latched map into lane markers and broadcasts the map to hero transform, so RViz displays the camera, the lidar point cloud and the town lane network together in one world-fixed view.

./run_map_and_lidar_demo.sh
./run_rviz.sh

The demo stack cleans up after itself: stopping the container destroys the vehicle and its sensors, and a new run removes anything left behind by a previous unclean exit.

Related to #9784 (first part of the series; ego vehicle topics and traffic lights follow in separate PRs, the last of which updates the CHANGELOG).

Preview

carla-ros2-path

Where has this been tested?

  • Platform(s): Linux (Ubuntu)
  • Python version(s): 3.10, 3.12
  • Unreal Engine version(s): 4.26

Validation: make check.LibCarla ARGS="--ros2" passes (140 server + 66 client tests, debug and release), make CarlaUE4Editor builds, full package build with --ros2 passes the ROS 2 smoke tests, and a late-joining ros2 topic echo receives the latched map on all three --rmw= middlewares. The demo was run end-to-end against the packaged server and verified in RViz on ROS 2 Humble.

Possible Drawbacks

The latched map sample is kept in the middleware history, which holds the OpenDRIVE string (around 2 MB for the stock towns) in memory for the lifetime of the episode. On Zenoh, if the advanced publisher cache cannot be created, the publisher falls back to volatile delivery and logs a warning, so late joiners would not receive the map.


This change is Reviewable

@JArmandoAnaya JArmandoAnaya requested a review from a team as a code owner June 11, 2026 23:16
Copilot AI review requested due to automatic review settings June 11, 2026 23:16
@update-docs

update-docs Bot commented Jun 11, 2026

Copy link
Copy Markdown

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds ROS 2 “latched” map publication (OpenDRIVE) via configurable publisher QoS, and introduces a Docker-based ROS 2 demo that visualizes the map lane network and live sensors in RViz.

Changes:

  • Publish the current map’s OpenDRIVE on rt/carla/map with transient-local durability (re-published on episode start / map load).
  • Add publisher QoS plumbing across ROS 2 middlewares (FastDDS, CycloneDDS, Zenoh) plus tests for the new default QoS behavior.
  • Add a one-command “map and lidar” ROS 2 demo stack (Docker, RViz preset, marker conversion + TF helper) and documentation.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.cpp Triggers ROS 2 map publish with OpenDRIVE string on episode start.
PythonAPI/test/smoke/test_ros2.py Adds smoke coverage for world reload + map re-publish stability.
PythonAPI/examples/ros2/rviz/ros2_native.rviz Adds map marker display and switches fixed frame to map.
PythonAPI/examples/ros2/run_map_and_lidar_demo.sh New entry script to build/run the Docker demo stack.
PythonAPI/examples/ros2/ros2_native.py Ensures SIGTERM in containers triggers cleanup via KeyboardInterrupt.
PythonAPI/examples/ros2/map_and_lidar_demo/map_to_markers.py New node converting /carla/map OpenDRIVE into RViz MarkerArray.
PythonAPI/examples/ros2/map_and_lidar_demo/launcher.sh New container entrypoint orchestrating helper processes and shutdown.
PythonAPI/examples/ros2/map_and_lidar_demo/ego_tf_broadcaster.py New helper broadcasting map->hero TF using simulation time.
PythonAPI/examples/ros2/map_and_lidar_demo/cleanup.py New helper to remove leftover demo actors and restore async mode.
PythonAPI/examples/ros2/map_and_lidar_demo/build.sh New script to build the demo Docker image (wheel + helpers).
PythonAPI/examples/ros2/map_and_lidar_demo/Dockerfile New Docker image extending RViz image with CARLA wheel + helpers.
PythonAPI/examples/ros2/README.md Documents the demo, files, and usage flow.
LibCarla/source/test/server/test_ros2_middleware.cpp Extends tests to validate default QoS + QoS propagation.
LibCarla/source/carla/ros2/publishers/PublisherImpl.h Adds optional PublisherQos parameter to publisher initialization.
LibCarla/source/carla/ros2/publishers/CarlaMapPublisher.h New publisher for latched OpenDRIVE map topic.
LibCarla/source/carla/ros2/publishers/CarlaMapPublisher.cpp Implements CarlaMapPublisher::Write.
LibCarla/source/carla/ros2/middleware/zenoh/ZenohWireFormat.h Adds QoS serialization for rmw_zenoh liveliness keyexprs.
LibCarla/source/carla/ros2/middleware/zenoh/ZenohPublisherMiddleware.h Adds transient-local support via advanced publisher cache + fallback.
LibCarla/source/carla/ros2/middleware/fastdds/FastDDSPublisherMiddleware.h Applies transient-local durability/history settings based on QoS.
LibCarla/source/carla/ros2/middleware/cyclonedds/CycloneDDSPublisherMiddleware.h Applies transient-local durability/history settings based on QoS.
LibCarla/source/carla/ros2/middleware/PublisherQos.h Introduces PublisherQos and DurabilityKind.
LibCarla/source/carla/ros2/middleware/IPublisherMiddleware.h Updates publisher middleware interface to accept PublisherQos.
LibCarla/source/carla/ros2/ROS2.h Adds map publisher member + ProcessDataFromMap API.
LibCarla/source/carla/ros2/ROS2.cpp Implements OpenDRIVE map publishing and resets publisher on shutdown.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread PythonAPI/examples/ros2/README.md
Comment thread PythonAPI/examples/ros2/map_and_lidar_demo/map_to_markers.py Outdated
Comment thread PythonAPI/examples/ros2/map_and_lidar_demo/map_to_markers.py Outdated
@JArmandoAnaya JArmandoAnaya changed the title feat(LibCarla/ros2): add publisher durability QoS and latched OpenDRIVE map topic feat(LibCarla/ros2): [1/3] add publisher durability QoS and latched OpenDRIVE map topic Jun 12, 2026
@JArmandoAnaya

Copy link
Copy Markdown
Contributor Author

Hello @youtalk. I added more PRs related to ROS2 and a plan in #9784. This time, the goal is to add missing topics and functions that already exist in the carla-ros-bridge project, which would add value if we move them into the internal carla ROS2 implementation. I want to know your opinion about them. I know @LuisPovedaCano will review these PRs later when he has time, but I'd value your opinion as a ROS2 expert.
Best.

@youtalk

youtalk commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

@JArmandoAnaya Thank you for your great works! I'll review them.

@Blyron

Blyron commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Hi @JArmandoAnaya, thanks for your hard work!
Now we are gonna be slower with reviews.... Sorry for not being able to give more details

@JArmandoAnaya

Copy link
Copy Markdown
Contributor Author

Hello @Blyron, don't worry, I understand. I hope that all is good on your side. I was working faster over the last few weeks because I'd just finished other projects and had time to work on Carla in my free time. I'm taking on more projects now, so I'll also be slower to send more PRs. I will be happy to keep helping with this porting. Thank you for your time.

@JArmandoAnaya JArmandoAnaya force-pushed the feature/ros2-qos-durability-and-map branch from 9bec6be to 6168f0a Compare June 17, 2026 07:29

@youtalk youtalk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, minimal way to add latched topics: the PublisherQos defaults reproduce the old behavior, and all three RMWs implement transient_local correctly — the Zenoh fallback even rewrites the advertised liveliness QoS so a transient_local subscriber won't falsely match. A few asks below to keep the QoS surface and the map topic robust for arbitrary ROS 2 consumers. One cross-cutting request for the series: please add Jazzy to the interop validation (the PR reports Humble only) — RIHS type hashes and CycloneDDS exist precisely so modern distros can discover and decode these topics, and Jazzy gates matching on the type hash.

Comment thread LibCarla/source/carla/ros2/middleware/PublisherQos.h
Comment thread LibCarla/source/carla/ros2/publishers/CarlaMapPublisher.h
@JArmandoAnaya

Copy link
Copy Markdown
Contributor Author

@youtalk Thank you for your review. I will take a look today. Please excuse the delay; I was out the last week.

@youtalk

youtalk commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@JArmandoAnaya Totally no problem. I really appreciate your usual fast-paced development.

…map topic

Publishers in the native ROS 2 layer can now request transient local
durability, and each middleware (FastDDS, CycloneDDS, Zenoh) maps it to
its own QoS so late-joining subscribers still receive the last sample.
The first user is a new /carla/map topic that publishes the OpenDRIVE
description of the current map on every map load, letting any ROS 2
node read the map at any time without connecting to the simulator.
…e markers in RViz

A single command now runs a demo stack in Docker against a CARLA server
started with --ros2. It spawns the hero vehicle on autopilot, converts
the latched /carla/map OpenDRIVE into lane markers and broadcasts the
map to hero transform, so RViz shows the camera, the lidar point cloud
and the town lane network together in one world-fixed view. The stack
cleans up after itself: stopping the container destroys the vehicle and
its sensors, and a new run removes anything a previous unclean exit
left behind.
Review feedback: history_depth was only honored for transient local
publishers, while volatile ones silently kept a hardcoded depth of 1.
The writer history is now set from the requested depth in every case,
and the invalid depth 0 is clamped to 1 through a single helper used by
all three middlewares. The defaults still produce the exact QoS every
publisher had before.
Review feedback: python is not guaranteed to exist on modern systems,
so the helpers now declare python3 directly. The waypoint cap in
map_to_markers.py becomes a named constant and logs a warning when a
lane is truncated by it.
…ensor streams

Extend PublisherQos with a ReliabilityKind and a SensorData() profile.
The default stays reliable, keeping the exact writer QoS every existing
publisher had, while camera image/camera_info and point cloud topics
(lidar, semantic lidar, radar, DVS) switch to best-effort delivery so a
slow or vanished subscriber can never stall the publishing thread, the
ROS 2 sensor-data idiom for high-rate streams.

All three middlewares honor the new field: FastDDS and CycloneDDS set
the writer reliability, Zenoh advertises it in the liveliness QoS
segment (rmw enum value 2) that rmw_zenoh matches endpoints on. The
bundled RViz preset switches its image and point cloud displays to
best-effort so they keep matching.
std_msgs/String carries no Header and that is deliberate: it keeps
rt/carla/map wire-compatible with the carla-ros-bridge /carla/map topic.
Document the identity contract a late joiner can rely on instead of a
stamp: the writer cache holds exactly one sample and the map is
re-published on every episode start / map load, so the latched payload
always describes the currently loaded map.
… config

The zenoh-ext advanced-publisher cache backing transient_local latching
only works on a session with timestamping enabled. The bundled session
config already turns it on, but when that file cannot be loaded the
zenoh default config does not, silently degrading latched topics such
as rt/carla/map to volatile. Patch the fallback config so latching
stays on by default.
@JArmandoAnaya JArmandoAnaya force-pushed the feature/ros2-qos-durability-and-map branch from 6168f0a to 356d1f6 Compare July 7, 2026 05:23
@JArmandoAnaya

Copy link
Copy Markdown
Contributor Author

The last comments and recommendations from @youtalk were applied. The PR is ready for code review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants