Skip to content

feat(LibCarla, Carla): add Zenoh ROS2 middleware - #9735

Merged
LuisPovedaCano merged 6 commits into
carla-simulator:ue4-devfrom
habby1012:feat/zenoh-ros2-middleware
Jun 10, 2026
Merged

feat(LibCarla, Carla): add Zenoh ROS2 middleware#9735
LuisPovedaCano merged 6 commits into
carla-simulator:ue4-devfrom
habby1012:feat/zenoh-ros2-middleware

Conversation

@habby1012

@habby1012 habby1012 commented May 19, 2026

Copy link
Copy Markdown

Description

Adds Zenoh as a third ROS 2 middleware backend on top of the existing abstraction. Users select it at runtime via --rmw=zenoh, alongside --rmw=fastdds and --rmw=cyclonedds.

New Zenoh middlewareLibCarla/source/carla/ros2/middleware/zenoh/:

  • ZenohSharedSession — opens a process-wide Zenoh session on first use and declares the carla_bridge node so rmw_zenoh peers see it. Defaults to connecting at tcp/localhost:7447, and it can be overridden via ZENOH_SESSION_CONFIG_URI or ZENOH_CONFIG_OVERRIDE.
  • ZenohWireFormat — small helpers that build the keyexpr, liveliness token string, and per-message attachment in the format rmw_zenoh expects.
  • ZenohPublisherMiddleware / ZenohSubscriberMiddleware — implement the existing IPublisherMiddleware / ISubscriberMiddleware interfaces. CDR serialization is shared with the FastDDS / CycloneDDS paths.

Wire it into the factory:

  • Middleware.h, MiddlewareFactory.h — add a Zenoh enum value and a factory branch that constructs ZenohPublisherMiddleware / ZenohSubscriberMiddleware when CARLA_ROS2_MIDDLEWARE_ZENOH is defined.
  • LibCarla/cmake/CMakeLists.txt, cmake/ros2/CMakeLists.txt, cmake/zenoh/CMakeLists.txt (new) — compile zenoh sources into carla_ros2 and install zenoh headers + libzenohc.a to the LibCarla dependencies dir.

Build & runtime selection:

  • Util/BuildTools/Setup.sh — download prebuilt zenoh-c 1.8.0 and strip --strip-debug the static library.
  • Carla.Build.cs — define CARLA_ROS2_MIDDLEWARE_ZENOH and link libzenohc.a into the UE4 plugin.
  • CarlaSettings.h — accept zenoh as a value for --rmw=.

Teststest_ros2_middleware.cpp: mirror the existing fastdds / cyclonedds cases for zenoh (to/from string, availability check, factory get/set, factory create-when-unavailable).

Where has this been tested?

  • Platform(s): Linux (Ubuntu 24.04)
  • Python version(s): 3.12
  • Unreal Engine version(s): UE4 4.26

Tests run:

  • make LibCarla ARGS="--ros2": passed.
  • make check.LibCarla ARGS="--ros2": 406 / 406 pass across all four configs (server release 137, client release 66, server debug 137, client debug 66).
  • make launch ARGS="--ros2 --rmw=fastdds" then python -m nose2 -v smoke.test_ros2: 5 / 5 pass in 39.1 s.
  • make launch ARGS="--ros2 --rmw=cyclonedds" then python -m nose2 -v smoke.test_ros2: 5 / 5 pass in 38.4 s.
  • make launch ARGS="--ros2 --rmw=zenoh" then python -m nose2 -v smoke.test_ros2: 5 / 5 pass in 38.6 s.

Possible Drawbacks

  • Adds a new build dependency (zenoh-c 1.8.0, ~5 MB after strip). Fetched as prebuilt archive on first make setup --ros2.
  • No change to --rmw=fastdds / --rmw=cyclonedds paths; existing behavior preserved.

This change is Reviewable

@habby1012
habby1012 requested a review from a team as a code owner May 19, 2026 11:07
@LuisPovedaCano LuisPovedaCano self-assigned this May 19, 2026

@JArmandoAnaya JArmandoAnaya 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.

I added one very small suggestion.

LuisPovedaCano
LuisPovedaCano previously approved these changes May 27, 2026

@LuisPovedaCano LuisPovedaCano 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.

The PR adds --rmw=zenohz support to CARLA but the companion PythonAPI/examples/ros2/Dockerfile only handles rmw_fastrtps_cpp and rmw_cyclonedds_cpp.
It should be extended to install ros-${ROS_DISTRO}-rmw-zenoh-cpp when RMW_IMPLEMENTATION=rmw_zenoh_cpp is passed

I've tested this end-to-end on the feat/zenoh-ros2-middleware branch on Ubuntu 24.04.
The implementation is clean.
Great addition.

@JArmandoAnaya

Copy link
Copy Markdown
Contributor

@LuisPovedaCano It would be great to add this update to the project's Docker script so we can test Zenoh features in the future.

Install ros-${ROS_DISTRO}-rmw-zenoh-cpp in the Dockerfile when selected
and accept --rmw=zenoh in run_rviz.sh, mirroring the --rmw=zenoh support
added to the CARLA server. Addresses post-approval review feedback.
@habby1012

Copy link
Copy Markdown
Author

Thanks for the reviews! Added Zenoh support to the ROS2 example as suggested by @JArmandoAnaya and @LuisPovedaCano:

  • DockerFile: installs ros-${ROS_DISTRO}-rmw-zenoh-cpp when --rmw=zenoh is selected.
  • run_rviz.sh: accepts --rmw=zenoh.

@habby1012

Copy link
Copy Markdown
Author

Thanks again @JArmandoAnaya @LuisPovedaCano !
Added the Zenoh support for the ROS2 example (Dockerfile + run_rviz.sh --rmw=zenoh). Feel free to check whenever you have time 🙂

@JArmandoAnaya

Copy link
Copy Markdown
Contributor

Hello @habby1012, Thank you for the commit. I'll test this locally as soon as possible. I will let you know my review.

@habby1012

Copy link
Copy Markdown
Author

@JArmandoAnaya, Sure, thanks!

@LuisPovedaCano

LuisPovedaCano commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

I wasn't able to run the example. The topics are published but not subscribed.

docker run --rm --net=host \
  --env="RMW_IMPLEMENTATION=rmw_zenoh_cpp" \
  carla-rviz-humble-zenoh \
  ros2 topic info /clock
Type: rosgraph_msgs/msg/Clock
Publisher count: 1
Subscription count: 0

Enabling the logs with debug it appeared this:
zenoh_ext::advanced_subscriber: Create AdvancedSubscriber{key_expr: 0/clock/rosgraph_msgs::msg::dds_::Clock_/TypeHashNotSupported}

so changing in ZenohWireFormat.h

inline std::string zenoh_make_topic_keyexpr(
    const std::string& domain,
    const std::string& topic_no_rt,
    const char*        type_name,
    const char*        type_hash)
{
  return domain + "/" + topic_no_rt + "/" + type_name + "/" + type_hash;
}

to:

inline std::string zenoh_make_topic_keyexpr(
    const std::string& domain,
    const std::string& topic_no_rt,
    const char*        type_name,
    const char* /* type_hash */)
{
  return domain + "/" + topic_no_rt + "/" + type_name + "/TypeHashNotSupported";
}

Has worked for me, now I can subscribe to the topics.
I tested running the RViz, I can see the cameras and all the topics.

Were you able to get it to work with RViz displaying the images without having to make this change?

The steps I followed to run the example are:

  1. In one terminal run: docker run --rm --net=host carla-rviz-humble-zenoh ros2 run rmw_zenoh_cpp rmw_zenohd
  2. Launch CARLA in another terminal with make launch ARGS="--ros2 --editor-flags='--ros2' --rmw=zenoh"
  3. After start the simulation, in a third terminal go to PythonAPI/examples/ros2 and run python ros2_native.py --file stack.json
  4. In a 4th terminal, go also to PythonAPI/examples/ros2 and run ./run_rviz.sh --distro=humble --rmw=zenoh

For DDS implementations, the step 1 was not required.
Should CARLA run the rmw_zenohd?
It is mandatory to run it? I tested without it and it does not work, but maybe it can be configured somehow.
All this should be documented

@habby1012

Copy link
Copy Markdown
Author

Hi @LuisPovedaCano, sorry this one tripped you up on humble, and thanks a lot for digging into it. Even finding a workaround really helped me pin it down.

Humble doesn't subscribe because CARLA publishes each topic with its real RIHS01 type hash. On jazzy and rolling, rmw_zenoh builds the subscriber key expression with that same hash, so they line up. Humble's rmw_zenoh doesn't do type hashes, so it always uses TypeHashNotSupported, which never matches CARLA's RIHS01_.... That's the Subscription count: 0 you saw. (and why it worked for me, I was on jazzy).

Forcing TypeHashNotSupported fixes humble but would break jazzy/rolling, so instead I just wildcarded the hash part of the key expression (.../* instead of .../<hash>), which matches both. RViz shows everything on humble and jazzy now.

I also added one step to the example README, which is starting rmw_zenohd.

Thanks again, really appreciate the careful review! Pushed both changes whenever you get a chance to look.

@LuisPovedaCano LuisPovedaCano 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.

Last commit fixes zenoh for both humble and jazzy.
I've been able to run simulations with both distros successfully.

@cgeller

cgeller commented Jun 14, 2026

Copy link
Copy Markdown

@habby1012 Really nice work, thanks a lot! Do you also plan to add Zenoh in the CARLA UE5 Version? I guess this would also he helpful for many other users.

@JArmandoAnaya

Copy link
Copy Markdown
Contributor

Hello @cgeller 👋, yes, it is the idea. We are in the middle of a porting process to pull all existing ROS2 improvements from the UE4 branch into UE5. But since this process also requires closing a current gap between the two sides about some previous ROS2 features missing in UE5 before merging the ROS2 middleware decoupling that exists now in UE4. I hope we can finish that in the next few weeks.

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