Skip to navigation

Use ZED with Isaac™ ROS 5

Open in ClaudeOpen in ChatGPT

This guide explains how to add ZED camera support to an NVIDIA® Isaac™ ROS 5 environment through the ZED ROS 2 Wrapper, and how to verify that the ZED data reach the Isaac™ ROS nodes.

Before starting, install Isaac™ ROS 5 and run the installation test by following the Setting up Isaac™ ROS 5 guide. Then follow the section that matches your installation path:

Requirements

  • ZED SDK 5.6 or newer (recommended), built for L4T 39.2 on Jetson™ or for CUDA 13 and Ubuntu 24.04 on x86_64. Both installation paths below install it. The ZED SDK 5.5 also works with Isaac™ ROS 5; see What requires the ZED SDK 5.6.
  • ZED ROS 2 Wrapper v5.4.1 or newer: the first version that supports ROS 2 Lyrical. Use v5.6.0 or newer to publish the ZED data with the CUDA zero-copy transport.
  • The rmw_fastrtps_cpp (Fast DDS, the default) or the rmw_zenoh_cpp v0.10.5 or newer (Zenoh) ROS 2 middleware, required by Isaac™ ROS 5: see Middleware requirement. To use Zenoh, follow the Use Zenoh with Isaac™ ROS 5 guide. Do not switch the ZED nodes to Cyclone DDS as described in the ROS 2 DDS and Network Tuning guide: the network tuning for large messages described there still applies to Fast DDS.
  • The ZED X Driver for L4T 39.2 installed on the host, only if you use GMSL2 cameras (ZED X, ZED X Mini, ZED X Nano, ZED X One) on a Jetson™ device. The driver is required with both installation paths.

NVIDIA® does not test ZED cameras on DGX Spark. This guide covers Jetson™ and x86_64 platforms.

When you build the ZED ROS 2 Wrapper with ROS 2 Lyrical, colcon prints the warning #warning BUFFER_HEADER_DEPRECATION and three similar warnings for the tf2_ros headers. This is expected: ROS 2 Lyrical deprecates the tf2_ros/*.h headers, which the wrapper still includes to keep compatibility with the previous ROS 2 distributions.

Versions of the ZED ROS 2 Wrapper older than v5.6.0 can also print the warning 'isaac_ros_nitros' not found, ISAAC ROS NITROS transport will not be available. This is expected: NITROS was removed in Isaac™ ROS 5, and the ZED node publishes standard ROS 2 messages. Read more in the Isaac™ ROS integration overview. We recommend the ZED ROS 2 Wrapper v5.6.0 or newer with Isaac™ ROS 5.

What requires the ZED SDK 5.6

The Isaac™ ROS 5 integration, including the CUDA zero-copy transport and the object detection example, works with the ZED SDK 5.5 and 5.6. The CUDA zero-copy transport depends on the version of the ZED ROS 2 Wrapper (v5.6.0 or newer), not on the version of the ZED SDK.

The ZED SDK 5.6 adds the real-time priority of the GMSL2 capture and sensor threads, for the ZED X, ZED X Mini, ZED X Nano, and ZED X One cameras on Jetson™. The installer creates the zed group, adds your user to it, and lets its members run these threads at real-time priority without root privileges (/etc/security/limits.d/60-zed-rtprio.conf). This setting:

  • takes effect at your next login: log out and log in again, or restart the device, after installing the ZED SDK;
  • does not apply to Docker containers: with the Docker installation, add the --ulimit rtprio=5 option to the container, as described in Add ZED support with Docker.

With the ZED SDK 5.5, or without this setting, the threads run at normal priority.

Add ZED support with Docker

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

Add the ZED SDK to the Isaac™ ROS Docker image

The Isaac™ ROS development container is built from a sequence of Dockerfiles, called image layers. To use ZED cameras, add a custom image layer that installs the ZED SDK and the dependencies of the ZED ROS 2 Wrapper 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.00-zed_sdk file with the following content. The same file works on Jetson™ and x86_64 devices:

    docker/Dockerfile.00-zed_sdk
    ARG BASE_IMAGE=ubuntu:24.04
    FROM ${BASE_IMAGE}
    SHELL ["/bin/bash", "-c"]
    ARG DEBIAN_FRONTEND=noninteractive
    # ZED SDK version to install
    ARG ZED_SDK_VERSION=5.6
    # Jetson only: Jetson Linux (L4T) release of the host. JetPack 7.2 is L4T 39.2
    ARG L4T_MAJOR=39
    ARG L4T_MINOR=2
    # Install the ZED SDK, the CUDA compiler and libraries required to build the ZED ROS 2 Wrapper,
    # and the TensorRT runtime required by the AI modules of the ZED SDK (NEURAL depth, Object Detection)
    RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    apt-get update \
    && apt-get install -y --no-install-recommends \
    cuda-nvcc-13-2 cuda-cudart-dev-13-2 cuda-culibos-dev-13-2 cuda-driver-dev-13-2 \
    libnvinfer10 libnvinfer-plugin10 libnvonnxparsers10 \
    git kmod less libgomp1 libpng-dev lsb-release udev wget zstd \
    && cd /tmp \
    && if [[ "$(uname -m)" == "aarch64" ]]; then \
    if [[ ! -f /etc/nv_tegra_release ]]; then \
    echo "# R${L4T_MAJOR} (release), REVISION: ${L4T_MINOR}.0" > /etc/nv_tegra_release; \
    fi \
    && wget -q -O ZED_SDK_Linux.run "https://download.stereolabs.com/zedsdk/${ZED_SDK_VERSION}/l4t${L4T_MAJOR}.${L4T_MINOR}/jetsons" \
    && chmod +x ZED_SDK_Linux.run \
    && ./ZED_SDK_Linux.run silent skip_python skip_drivers \
    && ln -sf /usr/lib/aarch64-linux-gnu/tegra/libv4l2.so.0 /usr/lib/aarch64-linux-gnu/libv4l2.so; \
    else \
    wget -q -O ZED_SDK_Linux.run "https://download.stereolabs.com/zedsdk/${ZED_SDK_VERSION}/cu13/ubuntu24" \
    && chmod +x ZED_SDK_Linux.run \
    && ./ZED_SDK_Linux.run -- silent skip_python skip_cuda; \
    fi \
    && rm -f /tmp/ZED_SDK_Linux.run \
    && rm -rf /usr/local/zed/resources/*
    # Pre-install the dependencies of the ZED ROS 2 Wrapper, so that they persist across container restarts
    RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    apt-get update \
    && source /opt/ros/${ROS_DISTRO}/setup.bash \
    && git clone --depth 1 https://github.com/stereolabs/zed-ros2-wrapper.git /tmp/zed-ros2-wrapper \
    && rosdep update \
    && rosdep install --from-paths /tmp/zed-ros2-wrapper --ignore-src -r -y \
    && apt-get install -y --no-install-recommends \
    ros-${ROS_DISTRO}-zed-description ros-${ROS_DISTRO}-zstd-image-transport \
    ros-${ROS_DISTRO}-cuda-buffer \
    && rm -rf /tmp/zed-ros2-wrapper /var/lib/apt/lists/*
    # Give the container user access to the IMU devices of the GMSL2 cameras (/dev/spsc_*).
    # The Isaac ROS entrypoint sources this script at container startup.
    COPY <<'EOF' /usr/local/bin/scripts/entrypoint_additions/zed-devices.sh
    for zed_dev in /dev/spsc_*; do
    [ -e "${zed_dev}" ] || continue
    ZED_DEV_GID="$(stat -c %g "${zed_dev}")"
    [ "${ZED_DEV_GID}" = "0" ] && continue
    ZED_DEV_GRP="$(getent group "${ZED_DEV_GID}" | cut -d: -f1)"
    if [ -z "${ZED_DEV_GRP}" ]; then
    ZED_DEV_GRP="zedgrp${ZED_DEV_GID}"
    groupadd --gid "${ZED_DEV_GID}" "${ZED_DEV_GRP}" >/dev/null 2>&1
    fi
    adduser "${USERNAME}" "${ZED_DEV_GRP}" >/dev/null 2>&1
    done
    EOF
    • To install a different ZED SDK version, change the ZED_SDK_VERSION value. Make sure the ZED SDK version matches the one required by the ZED ROS 2 Wrapper version you build.
    • The L4T_MAJOR and L4T_MINOR values must match the Jetson™ Linux version of your host. Isaac™ ROS 5 requires JetPack 7.2 (L4T 39.2).
    • The ZED X Driver is not installed in the image (skip_drivers): it must be installed on the host.
    • The base Isaac™ ROS image does not include TensorRT, which the ZED SDK requires for the NEURAL depth modes, used by default by the ZED ROS 2 Wrapper. Without it, the ZED node fails with the error NEURAL TRT NOT FOUND.
    • The ros-${ROS_DISTRO}-cuda-buffer package lets the ZED ROS 2 Wrapper v5.6.0 and newer publish the ZED data with the CUDA zero-copy transport.
    • The base Isaac™ ROS image gives the container user ownership of the /usr/local/zed folder at startup. The zed-devices.sh script also gives it access to the IMU devices of the GMSL2 cameras: without it, the ZED node fails with the errors Cannot open device /dev/spsc_bmi<N>: Permission denied and CAMERA MOTION SENSORS NOT DETECTED.
  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 00-zed_sdk image key in the workspace configuration file ${ISAAC_ROS_WS}/.isaac-ros-cli/config.yaml:

    docker:
    image:
    additional_image_keys:
    - 00-zed_sdk

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

    The Isaac™ ROS CLI builds the custom layers in the alphabetical order of their image keys, not in the order of the additional_image_keys list. The numeric prefix of the 00-zed_sdk key makes it the first custom layer: the layers added later, such as the 01-zed_object_detection layer of the object detection example, are built on top of it, and the ZED SDK layer is not built again. Use numeric prefixes to set the order of your own layers. Keys that start with a letter, such as zenoh, are built after the keys that start with a number.

  5. Share the ZED SDK data folders and, if needed, the GMSL2 driver files with the container. Add the following lines to the ~/.isaac_ros_dev-dockerargs file, which the Isaac™ ROS CLI reads every time it starts the container:

    -v /usr/local/zed/settings:/usr/local/zed/settings
    -v /usr/local/zed/resources:/usr/local/zed/resources
    • /usr/local/zed/settings stores the camera calibration files. Sharing it is required if you plan to use the robot in an area without internet access, after downloading the calibration files by following the Offline Deployment guide.
    • /usr/local/zed/resources stores the AI models of the ZED SDK (NEURAL depth, Object Detection, Body Tracking). Sharing it avoids downloading and optimizing the models every time the container restarts. On robots without internet access, prepare this folder in advance by following the Offline Deployment guide.

    If the folders do not exist on the host, create them before starting the container:

    sudo mkdir -p /usr/local/zed/settings /usr/local/zed/resources

    With GMSL2 cameras (ZED X, ZED X Mini, ZED X Nano, ZED X One) on Jetson™, also add the volumes required by the ZED X Driver and the real-time priority option. The /tmp folder is already shared by the Isaac™ ROS CLI on Jetson™:

    -v /var/nvidia/nvcam/settings/:/var/nvidia/nvcam/settings/
    -v /etc/systemd/system/zed_x_daemon.service:/etc/systemd/system/zed_x_daemon.service
    --ulimit rtprio=5

    The --ulimit rtprio=5 option lets the ZED SDK 5.6 and newer run the GMSL2 capture and sensor threads at real-time priority in the container, as the ZED SDK installer allows on the host. Read more in What requires the ZED SDK 5.6. Check it in the container with ulimit -r, which must print 5.

    See the Docker volumes reference for details.

  6. 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 --build-local flag builds the image with the new 00-zed_sdk layer. The first local build also rebuilds the base Isaac™ ROS image and downloads the CUDA packages: it takes about 20 minutes on a Jetson™ AGX Orin, depending on 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. Use isaac-ros activate --build-local again after modifying Dockerfile.00-zed_sdk.

  7. When the build is complete, the container starts automatically. Check the ZED SDK installation inside the container:

    /usr/local/zed/tools/ZED_Explorer --version

    Check camera opening and depth extraction:

    /usr/local/zed/tools/ZED_Depth_Viewer

For any problems with the Docker image build, refer to the NVIDIA® Isaac™ ROS troubleshooting documentation and to the Isaac™ ROS development environment documentation.

Build the ZED ROS 2 Wrapper in the container

The workspace folder ${ISAAC_ROS_WS} of the host is mounted in the container, so the source code and the build artifacts persist across container restarts.

  1. On the host, clone the ZED ROS 2 Wrapper in the src folder of the workspace:

    cd ${ISAAC_ROS_WS}/src
    git clone https://github.com/stereolabs/zed-ros2-wrapper.git
  2. Start the container, if it is not already running:

    isaac-ros activate
  3. Inside the container, check the dependencies and build the wrapper:

    cd ${ISAAC_ROS_WS}
    sudo apt-get update
    rosdep update
    rosdep install --from-paths src --ignore-src -r -y --skip-keys scout_description
    colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release --packages-up-to zed_wrapper
    source install/local_setup.bash

    The dependencies are already installed in the image by the 00-zed_sdk layer, so rosdep install only adds packages required by a newer version of the wrapper.

    rosdep reports errors such as No definition of [zed_description] for OS version [noble]. This is expected, because the ROS 2 Lyrical rosdep definitions target Ubuntu 26.04: the zed_sdk layer installs the missing packages with apt-get.

  4. Run source ${ISAAC_ROS_WS}/install/local_setup.bash every time you start a new shell in the container.

Continue with Test ZED with Isaac™ ROS.

Alternative: the NVIDIA® zed image key

The Isaac™ ROS CLI also ships a zed image key that installs the ZED SDK and builds the ZED ROS 2 Wrapper directly in the image. You enable it by adding zed to additional_image_keys instead of zed_sdk, as described in the NVIDIA® Isaac™ ROS ZED setup guide.

This option is quick to set up, but the NVIDIA® image layer pins older versions of the ZED SDK and of the ZED ROS 2 Wrapper, and it disables the depth processing and the AI modules of the ZED SDK in the wrapper configuration. We recommend the zed_sdk layer described above to get the latest ZED features and fixes. Do not enable both image keys at the same time.

Add ZED support with Bare Metal

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

Install the ZED SDK

Install the ZED SDK on the host. Do not run the installer with sudo: it asks for your password when needed.

Download and run the ZED SDK installer for JetPack 7.2 (L4T 39.2):

cd ~/Downloads
wget -O ZED_SDK_Linux.run https://download.stereolabs.com/zedsdk/5.6/l4t39.2/jetsons
chmod +x ZED_SDK_Linux.run
./ZED_SDK_Linux.run

If you use GMSL2 cameras (ZED X, ZED X Mini, ZED X Nano, ZED X One), also install the ZED X Driver for L4T 39.2.

With GMSL2 cameras, log out and log in again after the installation, so that the ZED SDK can run the camera threads at real-time priority. Read more in What requires the ZED SDK 5.6.

See the ZED SDK installation guide for more details. Check the installation and the camera:

/usr/local/zed/tools/ZED_Explorer --version
/usr/local/zed/tools/ZED_Depth_Viewer

Build the ZED ROS 2 Wrapper

  1. Activate the Isaac™ ROS environment:

    isaac-ros activate
  2. Clone the ZED ROS 2 Wrapper in the src folder of the workspace, install its dependencies, and build it:

    cd ${ISAAC_ROS_WS}/src
    git clone https://github.com/stereolabs/zed-ros2-wrapper.git
    cd ${ISAAC_ROS_WS}
    sudo apt-get update
    rosdep update
    rosdep install --from-paths src --ignore-src -r -y --skip-keys scout_description
    sudo apt-get install -y ros-lyrical-zed-description ros-lyrical-zstd-image-transport ros-lyrical-cuda-buffer
    colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release --packages-up-to zed_wrapper

    rosdep reports errors such as No definition of [zed_description] for OS version [noble]. This is expected, because the ROS 2 Lyrical rosdep definitions target Ubuntu 26.04: the apt-get install command installs the missing packages from the Isaac™ ROS Buildfarm. The ros-lyrical-cuda-buffer package lets the ZED ROS 2 Wrapper v5.6.0 and newer publish the ZED data with the CUDA zero-copy transport.

  3. Set up the environment variables in every new shell:

    echo "source ${ISAAC_ROS_WS}/install/local_setup.bash" >> ~/.bashrc
    source ~/.bashrc

The ZED integration steps are the same if you selected the Virtual Environment isolation mode of the Isaac™ ROS CLI (sudo isaac-ros init venv): install the ZED SDK on the host, then build the ZED ROS 2 Wrapper in the workspace.

Continue with Test ZED with Isaac™ ROS.

Test ZED with Isaac™ ROS

This test checks that an Isaac™ ROS node receives and processes the ZED images. The Isaac™ ROS ImageFormatConverterNode is loaded in the same component container as the ZED node, and converts the ZED color images on the GPU from the bgra8 to the rgb8 format.

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, then run source ${ISAAC_ROS_WS}/install/local_setup.bash.

  1. Install the Isaac™ ROS image processing package, if it is not already installed:

    sudo apt-get update
    sudo apt-get install -y ros-lyrical-isaac-ros-image-proc

    With the Docker installation, the packages installed with apt-get in the container are lost when the container is removed, for example after rebuilding the image with isaac-ros activate --build-local. Repeat this step if needed.

  2. In a first terminal, start the ZED node. Replace <your_camera_model> with the model of your camera, for example zed2i, zedxm for a ZED X Mini, or zedxonegs for a ZED X One GS:

    ros2 launch zed_wrapper zed_camera.launch.py camera_model:=<your_camera_model>

    To test without a camera, add svo_path:=<full_path_to_svo_file> to replay an SVO recording, with the camera_model of the camera that recorded the file.

    Wait until the node logs === zed started ===. The launch file starts the ZED node in the /zed/zed_container component container. The first time you use a NEURAL depth mode, the ZED SDK downloads and optimizes the AI model, which can take a few minutes.

  3. In a second terminal, check that the ZED topics are published:

    ros2 topic list | grep zed

    You should see the topics of the ZED camera, such as /zed/zed_node/rgb/color/rect/image.

  4. Load the Isaac™ ROS image format converter in the ZED container, and connect it to the rectified color image of the ZED camera:

    ros2 component load /zed/zed_container isaac_ros_image_proc \
    nvidia::isaac_ros::image_proc::ImageFormatConverterNode \
    --node-name zed_image_converter --node-namespace /zed \
    -p encoding_desired:=rgb8 \
    -r image_raw:=/zed/zed_node/rgb/color/rect/image \
    -r image:=/zed/image_rgb8 \
    -e use_intra_process_comms:=true

    Loading the Isaac™ ROS node in the same container as the ZED node enables Intra-Process Communication: the images are exchanged in memory, without serialization. Read more in the Composition and IPC documentation. Intra-process subscribers receive the images in CPU memory: to receive them in GPU memory, use the CUDA zero-copy transport, with Intra-Process Communication disabled and the Isaac™ ROS nodes in a separate component container.

  5. Check that the converted images are published at the same rate as the ZED images. Stop each command with Ctrl+C:

    ros2 topic hz /zed/zed_node/rgb/color/rect/image
    ros2 topic hz /zed/image_rgb8
  6. Check that the images are converted:

    ros2 topic echo --once --field encoding /zed/image_rgb8

    The output must be rgb8.

  7. Optionally, display the converted images with RViz2 (ros-lyrical-rviz2 package) or rqt_image_view (ros-lyrical-rqt-image-view package), subscribing to the /zed/image_rgb8 topic.

To test several cameras at the same time, start one ZED node for each camera with a different camera_name launch argument, for example camera_name:=zedxm and camera_name:=zedxone. If several cameras of the same model are connected, also set the serial_number launch argument. Then replace /zed with /<camera_name> in the commands above: for example, load the converter in the /zedxm/zed_container container and subscribe to the /zedxm/zed_node/rgb/color/rect/image topic.

The ZED camera works with Isaac™ ROS 5. To receive the ZED data directly in GPU memory in your own accelerated nodes, follow the CUDA zero-copy transport guide. You can now use the ZED topics as input for the other Isaac™ ROS packages with the same approach: load them in the ZED container and remap their input topics to the ZED topics.

If you are new to the ZED ROS 2 Wrapper, we recommend starting with the Getting Started with ROS 2 and ZED guide. See the ZED Stereo Node and the ZED Monocular Node documentation for the full list of topics and parameters, and explore the ZED ROS 2 Examples repository for tutorials and advanced examples.