Skip to navigation

Use Zenoh with Isaac™ ROS 5

Open in ClaudeOpen in ChatGPT

This guide explains how to replace the default Fast DDS middleware with Zenoh in an Isaac™ ROS 5 environment, with the Docker or the Bare Metal installation path, and how to verify that it works.

Isaac™ ROS 5 works with the default rmw_fastrtps_cpp middleware (Fast DDS) without any additional step. Use Zenoh when its features fit your application better: Zenoh uses TCP and a router for the discovery, so it does not depend on UDP multicast, and it works reliably on Wi-Fi networks and between networks. Read more in the ROS 2 Zenoh guide.

Requirements

  • Isaac™ ROS 5 installed and tested by following the Setting up Isaac™ ROS 5 guide.
  • The rmw_zenoh_cpp package v0.10.5 or newer: the first version that supports the rosidl::Buffer buffer backends used by Isaac™ ROS 5 and by the CUDA zero-copy transport of the ZED ROS 2 Wrapper. The Isaac™ ROS Buildfarm provides it.
  • The same middleware for all the ROS 2 nodes that communicate with each other, on all the machines.

Follow the section that matches your installation path:

Install Zenoh with Docker

Skip this section if you installed Isaac™ ROS 5 with the Bare Metal installation.

The packages installed with apt-get in the Isaac™ ROS container are lost when the container is removed. To keep Zenoh in your environment, add a custom image layer that installs it and selects it as the ROS 2 middleware, on top of the base Isaac™ ROS image.

  1. Create the folders for the custom image layer and its configuration in your workspace:

    mkdir -p ${ISAAC_ROS_WS}/docker ${ISAAC_ROS_WS}/scripts ${ISAAC_ROS_WS}/.isaac-ros-cli
  2. Create the ${ISAAC_ROS_WS}/docker/Dockerfile.zenoh file with the following content. The same file works on Jetson™ and x86_64 devices:

    ARG BASE_IMAGE=ubuntu:24.04
    FROM ${BASE_IMAGE}
    SHELL ["/bin/bash", "-c"]
    ARG DEBIAN_FRONTEND=noninteractive
    # Install the Zenoh ROS 2 middleware
    RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    apt-get update \
    && apt-get install -y --no-install-recommends ros-${ROS_DISTRO}-rmw-zenoh-cpp \
    && rm -rf /var/lib/apt/lists/*
    # Use Zenoh as the ROS 2 middleware in all the shells of the container
    ENV RMW_IMPLEMENTATION=rmw_zenoh_cpp
    # Wait up to 1 second, instead of 1 ms, before dropping a message under congestion,
    # so that large messages such as the ZED images and point clouds are not silently dropped
    ENV ZENOH_CONFIG_OVERRIDE="transport/link/tx/queue/congestion_control/drop/wait_before_drop=1000000"

    The ZENOH_CONFIG_OVERRIDE setting is explained in Zenoh settings for the ZED data.

  3. Tell the Isaac™ ROS CLI where to find the new Dockerfile. Create the ${ISAAC_ROS_WS}/scripts/.isaac_ros_common-config file:

    echo 'CONFIG_DOCKER_SEARCH_DIRS=(${ISAAC_ROS_WS}/docker /etc/isaac-ros-cli/docker)' > ${ISAAC_ROS_WS}/scripts/.isaac_ros_common-config

    Both folders are required: the Isaac™ ROS CLI uses the first configuration file it finds, and the /etc/isaac-ros-cli/docker folder contains the base Dockerfile.isaac_ros.

  4. Register the zenoh image key in the workspace configuration file ${ISAAC_ROS_WS}/.isaac-ros-cli/config.yaml:

    docker:
    image:
    additional_image_keys:
    - zenoh

    If the file already lists other image keys, for example the 00-zed_sdk key of the Use ZED with Isaac™ ROS guide, add zenoh to the list and keep the other keys.

  5. Exit all the shells of the running Isaac™ ROS container, if any, so that the container stops. Then build the new image and start the container:

    isaac-ros activate --build-local

    The first local build also rebuilds the base Isaac™ ROS image: it can take several minutes, depending on your device and your internet connection. The message Error response from daemon: failed to resolve reference ... not found is expected at the end of the build and every time you start the container: the Isaac™ ROS CLI looks for the image in the NVIDIA® registry before using the local one.

    After the image has been built once, use isaac-ros activate to start the container without rebuilding the image.

  6. Inside the container, check that Zenoh is installed and selected:

    apt-cache policy ros-lyrical-rmw-zenoh-cpp | grep Installed
    echo $RMW_IMPLEMENTATION
    echo $ZENOH_CONFIG_OVERRIDE

    The installed version must be 0.10.5 or newer, the second command must print rmw_zenoh_cpp, and the third one the Zenoh setting for large messages.

The container shares the network of the host, so the nodes running in the container and the nodes running on the host use the same Zenoh router.

Continue with Test Zenoh with Isaac™ ROS.

Install Zenoh with Bare Metal

Skip this section if you installed Isaac™ ROS 5 with the Docker installation.

  1. Install Zenoh from the Isaac™ ROS Buildfarm:

    sudo apt-get update
    sudo apt-get install -y ros-lyrical-rmw-zenoh-cpp
  2. Check the installed version. It must be 0.10.5 or newer:

    apt-cache policy ros-lyrical-rmw-zenoh-cpp | grep Installed
  3. Select Zenoh as the ROS 2 middleware in every new shell, and set the Zenoh setting for large messages explained in Zenoh settings for the ZED data:

    echo "export RMW_IMPLEMENTATION=rmw_zenoh_cpp" >> ~/.bashrc
    echo "export ZENOH_CONFIG_OVERRIDE='transport/link/tx/queue/congestion_control/drop/wait_before_drop=1000000'" >> ~/.bashrc
    source ~/.bashrc

    Open a new terminal, or run source ~/.bashrc, in all the terminals that are already open.

Continue with Test Zenoh with Isaac™ ROS.

Test Zenoh with Isaac™ ROS

This test runs the installation test of Isaac™ ROS 5 with Zenoh: an Isaac™ ROS node converts test images on the GPU, and the images are exchanged through the Zenoh middleware.

Run all the commands in the Isaac™ ROS environment. With the Docker installation, run isaac-ros activate in each new terminal to open a shell in the running container.

  1. In a first terminal, start the Zenoh router. Unlike Fast DDS, Zenoh does not discover the nodes with UDP multicast: the nodes discover each other through the router, which must be running before you start them.

    ros2 run rmw_zenoh_cpp rmw_zenohd

    Keep the router running while you use ROS 2. One router per host is enough. To connect several hosts, see Running across multiple machines.

  2. In a second terminal, check that ROS 2 uses Zenoh:

    ros2 doctor --report | grep "middleware name"

    The output must contain rmw_zenoh_cpp.

  3. Follow the steps of Test the installation in other terminals, with the router still running: install the test packages, publish the test image, start the component container, and load the image format converter. The /image_rgb8 topic must be published at about 30 Hz, with the rgb8 encoding.

If the nodes start without errors but ros2 topic list does not show their topics, check that the router is running and that RMW_IMPLEMENTATION is set to rmw_zenoh_cpp in all the terminals.

Use the ZED ROS 2 Wrapper with Zenoh

The ZED ROS 2 Wrapper uses the middleware selected by the RMW_IMPLEMENTATION environment variable: no change to its configuration is required.

  1. Add ZED support to your Isaac™ ROS environment by following the Use ZED with Isaac™ ROS guide, and run its ZED test with the Zenoh router running.

  2. With the ZED ROS 2 Wrapper v5.6.0 or newer, check the transport in the log of the ZED node. The CUDA zero-copy transport works with Zenoh v0.10.5 or newer, as with Fast DDS:

    * Buffer transport: CUDA zero-copy [automatic CPU fallback for subscribers that cannot use it]

    With an older version of rmw_zenoh_cpp, the line explains that the node publishes standard CPU data, and which version is required.

We validated Zenoh on a Jetson™ AGX Thor with a ZED 2i, with both installation paths: the CUDA zero-copy examples received all the images and point clouds as CUDA buffers. To choose between Fast DDS and Zenoh, compare their latencies in the image and point cloud tutorials: Fast DDS has the lowest latency with large CPU messages, while Zenoh has the lowest latency with the CUDA zero-copy transport.

ros2 topic hz can occasionally report a lower rate for the ZED image topics than the camera frame rate, while the Isaac™ ROS nodes loaded in the ZED container receive all the images. Check that the Zenoh setting for large messages is applied in all the terminals, and check the rate of the topics published by your Isaac™ ROS nodes, for example /zed/image_rgb8 in the ZED test.

Zenoh settings for the ZED data

The ZED topics carry large messages, such as images and point clouds of several MB. With the default QoS of the ZED nodes, Zenoh drops a message when it cannot send it within 1 ms, without any error: under load, images and point clouds can be silently lost. The installation steps above set the ZENOH_CONFIG_OVERRIDE environment variable to wait up to 1 second (1000000 µs) before dropping a message, which keeps the default QoS of the ZED nodes. Read more in Prevent point clouds and images from being silently dropped.

The variable must be set in the terminals where you start the router and the nodes: the Docker image layer and the ~/.bashrc line of the Bare Metal installation set it in all the shells. Each ZENOH_CONFIG_OVERRIDE value replaces the previous one: to add other settings, such as the shared memory transport, combine them in the same variable, separated by ;, as described in Tuning Zenoh for large messages.

Switch back to Fast DDS

  • Docker: remove zenoh from the additional_image_keys list of the ${ISAAC_ROS_WS}/.isaac-ros-cli/config.yaml file, exit all the shells of the container, and run isaac-ros activate --build-local.
  • Bare Metal: remove the export RMW_IMPLEMENTATION=rmw_zenoh_cpp and export ZENOH_CONFIG_OVERRIDE=... lines from your ~/.bashrc file, and open a new terminal.

The Zenoh router is not required with Fast DDS.