Skip to content
Edge AI

NVIDIA Isaac ROS: GPU-accelerated packages for robotics deployment

Isaac ROS is NVIDIA's toolkit for building robots: pre-built, GPU-accelerated packages for visual SLAM, spatial mapping, object detection and motion planning.

· Ozgur Ogul Koca


Isaac ROS in brief

What Isaac ROS is

Isaac ROS is NVIDIA's toolkit for building robots. It is a set of pre-built, GPU-accelerated software packages for common robotics tasks: visual SLAM, spatial mapping, object detection and motion planning.

Isaac ROS compared with building from scratch

Task DIY Approach With Isaac ROS
Visual SLAM Months of development Works out of the box
Object Detection Train your own models Pre-optimized models included
3D Mapping Complex implementation One-line configuration
Navigation Extensive testing needed Production-proven code

The package set

Package What It Does Real-World Use
cuVSLAM Camera-based localization Robot knows where it is
nvblox 3D environment mapping Robot sees obstacles
DNN Inference AI object detection Robot recognizes things
cuMotion Arm motion planning Robot picks up objects

NITROS

NITROS (NVIDIA Isaac Transport for ROS) makes data transfer between components 7x faster by keeping data on the GPU instead of copying it back and forth to CPU.

Traditional:
Camera
[Copy to CPU]
Process
[Copy to GPU]
AI
[Copy to CPU]
Output
With NITROS:
Camera
GPU
AI
Output
(no copying!)

Performance comparison

Feature Without Isaac ROS With Isaac ROS
Data Transfer Slow (CPU copies) Fast (zero-copy)
Visual SLAM 15 FPS 60 FPS
3D Mapping 0.6 FPS 30 FPS
Development Time 6-12 months 2-4 weeks

What this post covers

  1. Setting up Isaac ROS on Jetson devices
  2. Using cuVSLAM for visual navigation
  3. Building 3D maps with nvblox
  4. Integrating with ROS 2 and Nav2
  5. Connecting to Isaac Sim for testing

Isaac ROS shortens robotics development. You get production-ready, GPU-optimized components that already work together, instead of writing each one from scratch.


Where Isaac ROS fits

NVIDIA Isaac ROS is a set of CUDA-accelerated ROS 2 packages that run on NVIDIA GPUs and Jetson platforms. This post walks through the architecture: perception, navigation, manipulation, simulation, and the deployment patterns that carry an autonomous robot into production.

The packages sit between research-grade algorithms and production implementations, under the real-time constraints a robot imposes. Autonomous mobile robots (AMRs), robotic manipulators and multi-robot systems all build on the same infrastructure.


Isaac ROS architecture and core packages

NITROS: zero-copy GPU acceleration

NITROS (NVIDIA Isaac Transport for ROS) implements ROS 2 Humble's type adaptation and type negotiation features. It transfers data between nodes without a copy. That removes the CPU-GPU memory transfer bottleneck.

# Example: Creating a NITROS-enabled node
from isaac_ros_nitros import NitrosNode
from sensor_msgs.msg import Image

class MyNitrosPerceptionNode(NitrosNode):
    def __init__(self):
        super().__init__('my_nitros_node')

        # NITROS automatically negotiates GPU-accelerated data transfer
        self.subscription = self.create_subscription(
            Image,
            '/camera/image_raw',
            self.image_callback,
            10,
            # NITROS type adaptation happens transparently
        )

    def image_callback(self, msg):
        # Data arrives as GPU tensor - no CPU copy needed
        # Process directly on GPU
        pass

What NITROS changes:

  • 3x improvement on Jetson Xavier, 7x improvement on Jetson Orin
  • Interoperates with standard ROS 2 nodes
  • Automatic fallback to CPU messages for non-NITROS nodes

The Isaac ROS packages

Isaac ROS ships specialized packages organized by functional domain:

Category Packages Purpose
Perception isaac_ros_apriltag, isaac_ros_object_detection, isaac_ros_pose_estimation Object detection, fiducial tracking, 6-DoF pose
Scene Reconstruction isaac_ros_nvblox 3D reconstruction, costmap generation
Navigation isaac_ros_visual_slam, isaac_ros_navigation_goal Visual odometry, path planning
Manipulation isaac_ros_cumotion Motion planning, trajectory optimization
DNN Inference isaac_ros_dnn_inference TensorRT/Triton acceleration
Common isaac_ros_common, isaac_ros_nitros Docker environments, type adaptation

Hardware-accelerated perception

AprilTag detection

Isaac ROS AprilTag provides GPU-accelerated fiducial marker detection with support for CPU, GPU, and PVA (Programmable Vision Accelerator) backends on Jetson devices.

# Launch file: apriltag_detection.launch.py
from launch import LaunchDescription
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode

def generate_launch_description():
    apriltag_node = ComposableNode(
        package='isaac_ros_apriltag',
        plugin='nvidia::isaac_ros::apriltag::AprilTagNode',
        name='apriltag',
        namespace='',
        parameters=[{
            'size': 0.162,  # Tag size in meters
            'max_tags': 64,
            'tile_size': 4,
            'backend': 'GPU'  # Options: CPU, GPU, PVA
        }],
        remappings=[
            ('image', '/camera/image_rect'),
            ('camera_info', '/camera/camera_info')
        ]
    )

    container = ComposableNodeContainer(
        name='apriltag_container',
        namespace='',
        package='rclcpp_components',
        executable='component_container_mt',
        composable_node_descriptions=[apriltag_node],
        output='screen'
    )

    return LaunchDescription([container])

Stereo depth estimation

Isaac ROS provides DNN-based stereo depth estimation through the ESS (Efficient Stereo Search) model:

# Stereo depth pipeline configuration
stereo_depth_node = ComposableNode(
    package='isaac_ros_ess',
    plugin='nvidia::isaac_ros::dnn_stereo_depth::ESSDisparityNode',
    name='ess_disparity',
    parameters=[{
        'engine_file_path': '/path/to/ess.engine',
        'threshold': 0.9,
        'image_type': 'RGB_U8',
    }],
    remappings=[
        ('left/image_rect', '/stereo/left/image_rect'),
        ('right/image_rect', '/stereo/right/image_rect'),
        ('left/camera_info', '/stereo/left/camera_info'),
        ('right/camera_info', '/stereo/right/camera_info')
    ]
)

Object detection with RT-DETR and YOLOv8

Isaac ROS Object Detection supports multiple detection architectures:

# config/object_detection.yaml
object_detection:
  ros__parameters:
    model_file_path: "/models/rtdetr.onnx"
    engine_file_path: "/models/rtdetr.engine"
    input_tensor_names: ["images"]
    output_tensor_names: ["labels", "boxes", "scores"]
    input_binding_names: ["images"]
    output_binding_names: ["labels", "boxes", "scores"]
    confidence_threshold: 0.5
    nms_threshold: 0.45
    class_names: ["person", "forklift", "pallet", "box"]

Navigation stack with Isaac ROS

Visual SLAM with cuVSLAM

Isaac ROS Visual SLAM provides GPU-accelerated visual-inertial odometry using the cuVSLAM library (formerly Elbrus):

# visual_slam.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    visual_slam_node = Node(
        package='isaac_ros_visual_slam',
        executable='visual_slam_node',
        name='visual_slam',
        parameters=[{
            'denoise_input_images': False,
            'rectified_images': True,
            'enable_slam_visualization': True,
            'enable_observations_view': True,
            'enable_landmarks_view': True,
            'enable_imu_fusion': True,
            'gyro_noise_density': 0.000244,
            'gyro_random_walk': 0.000019393,
            'accel_noise_density': 0.001862,
            'accel_random_walk': 0.003,
            'calibration_frequency': 200.0,
            'imu_frame': 'imu_link',
            'map_frame': 'map',
            'odom_frame': 'odom',
            'base_frame': 'base_link'
        }],
        remappings=[
            ('stereo_camera/left/image', '/zed/left/image_rect_color'),
            ('stereo_camera/left/camera_info', '/zed/left/camera_info'),
            ('stereo_camera/right/image', '/zed/right/image_rect_color'),
            ('stereo_camera/right/camera_info', '/zed/right/camera_info'),
            ('visual_slam/imu', '/zed/imu/data')
        ],
        output='screen'
    )

    return LaunchDescription([visual_slam_node])

cuVSLAM performance:

  • 60+ FPS for VGA resolution
  • ~1% drift in localization on KITTI benchmark
  • 0.003 degrees/meter orientation error

Nvblox 3D reconstruction

Nvblox generates real-time 3D reconstructions using TSDF (Truncated Signed Distance Function) representation:

# nvblox_nav2.launch.py
nvblox_node = Node(
    package='nvblox_ros',
    executable='nvblox_node',
    name='nvblox',
    parameters=[{
        # Mapping parameters
        'voxel_size': 0.05,
        'esdf_update_rate_hz': 10.0,
        'mesh_update_rate_hz': 5.0,
        'max_tsdf_update_hz': 30.0,

        # Sensor configuration
        'use_depth': True,
        'use_lidar': True,
        'lidar_width': 1800,
        'lidar_height': 16,
        'lidar_vertical_fov_rad': 0.52,

        # Dynamic scene handling
        'people_segmentation': True,
        'dynamic_mapper': True,
        'clear_dynamic_objects': True,

        # Frame configuration
        'global_frame': 'odom',
        'map_clearing_radius_m': 5.0
    }],
    remappings=[
        ('depth/image', '/camera/depth/image_rect_raw'),
        ('depth/camera_info', '/camera/depth/camera_info'),
        ('color/image', '/camera/color/image_raw'),
        ('color/camera_info', '/camera/color/camera_info'),
        ('pointcloud', '/velodyne/points')
    ]
)

Nav2 integration with Isaac ROS GEMs

# Complete navigation stack launch
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from ament_index_python.packages import get_package_share_directory
import os

def generate_launch_description():
    nav2_bringup_dir = get_package_share_directory('nav2_bringup')
    nvblox_examples_dir = get_package_share_directory('nvblox_examples_bringup')

    # Nav2 stack with nvblox costmap plugin
    nav2_launch = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(nav2_bringup_dir, 'launch', 'bringup_launch.py')
        ),
        launch_arguments={
            'use_sim_time': 'true',
            'params_file': os.path.join(
                nvblox_examples_dir,
                'config',
                'nav2_params_nvblox.yaml'
            )
        }.items()
    )

    # Nvblox for 3D reconstruction and costmap
    nvblox_launch = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(nvblox_examples_dir, 'launch', 'nvblox.launch.py')
        ),
        launch_arguments={
            'lidar': 'True',
            'num_cameras': '3'
        }.items()
    )

    return LaunchDescription([nav2_launch, nvblox_launch])

Manipulation and grasping with cuMotion

cuMotion MoveIt 2 integration

Isaac ROS cuMotion provides CUDA-accelerated motion planning with up to 80x speedup over CPU-based planners:

# cumotion_moveit.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
from moveit_configs_utils import MoveItConfigsBuilder

def generate_launch_description():
    moveit_config = MoveItConfigsBuilder("franka_panda").to_dict()

    # cuMotion planner node
    cumotion_planner = Node(
        package='isaac_ros_cumotion',
        executable='cumotion_planner_node',
        name='cumotion_planner',
        parameters=[
            moveit_config,
            {
                'robot_file': '/config/franka.xrdf',
                'urdf_path': '/urdf/franka.urdf',
                'time_dilation_factor': 0.5,
                'collision_cache_mesh': 32,
                'collision_cache_cuboid': 32,
                'interpolation_dt': 0.02,
                'voxel_dims': [2.0, 2.0, 2.0],
                'voxel_size': 0.05,
            }
        ],
        output='screen'
    )

    # Robot segmentation for collision avoidance
    robot_segmentation = Node(
        package='isaac_ros_cumotion',
        executable='cumotion_robot_segmentation_node',
        name='robot_segmentation',
        parameters=[{
            'robot_file': '/config/franka.xrdf',
            'urdf_path': '/urdf/franka.urdf',
            'distance_threshold': 0.1,
        }],
        remappings=[
            ('depth_image', '/camera/depth/image_rect_raw'),
            ('camera_info', '/camera/depth/camera_info')
        ]
    )

    return LaunchDescription([cumotion_planner, robot_segmentation])

Grasp definition and execution

# grasps/box_grasps.isaac_grasp
object:
  name: "cardboard_box"
  dimensions: [0.3, 0.2, 0.15]

grasps:
  - name: "top_grasp"
    approach_direction: [0, 0, -1]
    grasp_pose:
      position: [0.0, 0.0, 0.1]
      orientation: [0, 0, 0, 1]  # wxyz quaternion
    gripper_opening: 0.08
    pre_grasp_distance: 0.1
    post_grasp_distance: 0.05

  - name: "side_grasp"
    approach_direction: [1, 0, 0]
    grasp_pose:
      position: [0.2, 0.0, 0.075]
      orientation: [0.707, 0, 0.707, 0]
    gripper_opening: 0.06
    pre_grasp_distance: 0.08
    post_grasp_distance: 0.05

DNN inference nodes: DOPE and CenterPose

DOPE (Deep Object Pose Estimation)

DOPE provides instance-level 6-DoF pose estimation trained on synthetic data:

# dope_inference.launch.py
dope_node = ComposableNode(
    package='isaac_ros_dope',
    plugin='nvidia::isaac_ros::dope::DopeDecoderNode',
    name='dope_decoder',
    parameters=[{
        'object_name': 'soup_can',
        'model_file_path': '/models/dope_soup.onnx',
        'engine_file_path': '/models/dope_soup.engine',
        'input_tensor_names': ['input'],
        'input_binding_names': ['input'],
        'output_tensor_names': ['output'],
        'output_binding_names': ['output'],
        'camera_matrix': [
            616.078, 0.0, 325.579,
            0.0, 616.562, 240.189,
            0.0, 0.0, 1.0
        ],
        'cuboid_dimensions': [0.068, 0.068, 0.102]  # Object dimensions
    }]
)

# DOPE runs at 39.8 FPS on Jetson AGX Orin, 89.2 FPS on RTX 4060 Ti

CenterPose for category-level detection

CenterPose detects objects at the category level without requiring instance-specific training:

centerpose_node = ComposableNode(
    package='isaac_ros_centerpose',
    plugin='nvidia::isaac_ros::centerpose::CenterPoseDecoderNode',
    name='centerpose_decoder',
    parameters=[{
        'object_name': 'chair',  # Category, not specific instance
        'model_file_path': '/models/centerpose_chair.onnx',
        'output_field_size': [128, 128],
        'cuboid_scaling_factor': 1.0,
        'score_threshold': 0.3,
    }]
)

FoundationPose for novel objects

# FoundationPose for zero-shot pose estimation
foundationpose_node = ComposableNode(
    package='isaac_ros_foundationpose',
    plugin='nvidia::isaac_ros::foundationpose::FoundationPoseNode',
    name='foundationpose',
    parameters=[{
        'mesh_file_path': '/meshes/custom_object.obj',
        'texture_path': '/meshes/custom_object_texture.png',
        'refine_model_file_path': '/models/foundationpose_refine.onnx',
        'score_model_file_path': '/models/foundationpose_score.onnx',
        'refine_iterations': 3,
        'min_detection_threshold': 0.5,
    }]
)

Isaac Sim for synthetic data generation

Domain randomization with Replicator

Isaac Sim's Replicator extension generates synthetic training data in bulk:

# replicator_sdg.py - Synthetic Data Generation Script
import omni.replicator.core as rep

with rep.new_layer():
    # Camera setup with randomization
    camera = rep.create.camera(
        position=rep.distribution.uniform((1, 1, 1), (3, 3, 3)),
        look_at=(0, 0, 0)
    )

    # Environment randomization
    with rep.trigger.on_frame(num_frames=10000):
        # Lighting randomization
        rep.randomizer.light(
            light_type="dome",
            intensity=rep.distribution.uniform(500, 2000),
            color=rep.distribution.uniform((0.8, 0.8, 0.8), (1.0, 1.0, 1.0))
        )

        # Object pose randomization
        with rep.get.prims(semantics=[("class", "target_object")]):
            rep.modify.pose(
                position=rep.distribution.uniform((-0.5, -0.5, 0), (0.5, 0.5, 0.3)),
                rotation=rep.distribution.uniform((0, 0, 0), (360, 360, 360))
            )

        # Material randomization
        rep.randomizer.materials(
            materials=rep.get.material(semantics=[("class", "randomizable")]),
            input_prims=rep.get.prims(semantics=[("class", "target_object")])
        )

    # Output configuration
    render_product = rep.create.render_product(camera, (1280, 720))

    # Annotations
    rep.WriterRegistry.get("BasicWriter")(
        output_dir="/output/synthetic_data",
        rgb=True,
        bounding_box_2d_tight=True,
        semantic_segmentation=True,
        instance_segmentation=True,
        distance_to_camera=True
    ).attach([render_product])

ROS 2 bridge configuration

# isaac_sim_ros2_config.yaml
ros2_bridge:
  node_namespace: "isaac_sim"

  publishers:
    - topic: /rgb/image_raw
      type: sensor_msgs/Image
      frame_id: camera_link
      publish_rate: 30

    - topic: /depth/image_raw
      type: sensor_msgs/Image
      frame_id: camera_link
      publish_rate: 30

    - topic: /camera_info
      type: sensor_msgs/CameraInfo
      frame_id: camera_link

    - topic: /joint_states
      type: sensor_msgs/JointState
      publish_rate: 100

  subscribers:
    - topic: /cmd_vel
      type: geometry_msgs/Twist

    - topic: /joint_command
      type: trajectory_msgs/JointTrajectory

Multi-robot coordination

Mission dispatch with VDA5050

Isaac ROS provides fleet management through VDA5050 standard compliance:

# mission_client.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    # Mission client connects robot to fleet management
    mission_client = Node(
        package='isaac_ros_mission_client',
        executable='mission_client',
        name='mission_client',
        parameters=[{
            'mqtt_host': 'fleet-manager.local',
            'mqtt_port': 1883,
            'mqtt_transport': 'tcp',
            'robot_name': 'amr_001',
            'manufacturer': 'NVIDIA',
            'serial_number': 'AMR-2024-001',
            'nav2_action_server': 'navigate_to_pose',
            'status_update_rate': 1.0,
        }],
        output='screen'
    )

    return LaunchDescription([mission_client])

Namespace configuration for multiple robots

# multi_robot_nav.launch.py
from launch import LaunchDescription
from launch.actions import GroupAction
from launch_ros.actions import PushRosNamespace

def generate_launch_description():
    robots = ['carter1', 'carter2', 'carter3']
    launch_actions = []

    for robot in robots:
        robot_group = GroupAction([
            PushRosNamespace(robot),
            IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    os.path.join(nav2_bringup_dir, 'launch', 'bringup_launch.py')
                ),
                launch_arguments={
                    'namespace': robot,
                    'use_namespace': 'true',
                    'map': f'/maps/{robot}_map.yaml',
                    'params_file': f'/config/{robot}_nav2_params.yaml'
                }.items()
            )
        ])
        launch_actions.append(robot_group)

    return LaunchDescription(launch_actions)

Isaac ROS DevOps and CI/CD

Docker development environment

# Dockerfile.isaac_ros_dev
ARG BASE_IMAGE=nvcr.io/nvidia/isaac/ros:aarch64-ros2_humble-nav2_3.1.0

FROM ${BASE_IMAGE}

# Install additional dependencies
RUN apt-get update && apt-get install -y \
    ros-humble-rmw-cyclonedds-cpp \
    python3-colcon-common-extensions \
    && rm -rf /var/lib/apt/lists/*

# Copy workspace
COPY src/ /ros_ws/src/
WORKDIR /ros_ws

# Build workspace
RUN . /opt/ros/humble/setup.sh && \
    colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release

# Set entrypoint
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["bash"]

Production deployment script

#!/bin/bash
# deploy_isaac_ros.sh

set -e

ROBOT_IP=$1
DEPLOY_TAG=$2

# Build production image
docker build \
    --build-arg BASE_IMAGE=nvcr.io/nvidia/isaac/ros:aarch64-ros2_humble-3.1.0 \
    -t my-robot-app:${DEPLOY_TAG} \
    -f Dockerfile.production .

# Export and transfer
docker save my-robot-app:${DEPLOY_TAG} | ssh robot@${ROBOT_IP} 'docker load'

# Deploy with docker-compose
ssh robot@${ROBOT_IP} << 'EOF'
cd /opt/robot_deployment
docker-compose pull
docker-compose up -d --remove-orphans
docker system prune -f
EOF

echo "Deployment complete to ${ROBOT_IP}"

CI/CD pipeline configuration

# .github/workflows/isaac_ros_ci.yaml
name: Isaac ROS CI/CD

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  build-and-test:
    runs-on: self-hosted  # Requires GPU runner
    container:
      image: nvcr.io/nvidia/isaac/ros:x86_64-ros2_humble-3.1.0
      options: --gpus all

    steps:
      - uses: actions/checkout@v4

      - name: Build Workspace
        run: |
          source /opt/ros/humble/setup.bash
          colcon build --symlink-install

      - name: Run Unit Tests
        run: |
          source /opt/ros/humble/setup.bash
          source install/setup.bash
          colcon test --return-code-on-test-failure

      - name: Run Isaac ROS Benchmark
        run: |
          source install/setup.bash
          ros2 launch isaac_ros_benchmark benchmark_perception.launch.py

      - name: Build Production Image
        if: github.ref == 'refs/heads/main'
        run: |
          docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .
          docker push ghcr.io/${{ github.repository }}:${{ github.sha }}

Production deployment patterns

Hardware-in-the-loop testing

# hil_test.launch.py
def generate_launch_description():
    # Configure for HIL testing on actual Jetson hardware
    return LaunchDescription([
        # Sensor drivers
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource(
                os.path.join(realsense_dir, 'launch', 'rs_launch.py')
            ),
            launch_arguments={
                'depth_module.profile': '640x480x30',
                'rgb_camera.profile': '640x480x30',
                'enable_sync': 'true',
                'align_depth.enable': 'true'
            }.items()
        ),

        # Isaac ROS perception pipeline
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource(
                os.path.join(isaac_ros_dir, 'launch', 'perception.launch.py')
            )
        ),

        # Test harness
        Node(
            package='isaac_ros_benchmark',
            executable='benchmark_node',
            parameters=[{
                'test_duration_sec': 300,
                'min_fps_threshold': 25,
                'max_latency_ms': 100,
                'output_file': '/test_results/hil_benchmark.json'
            }]
        )
    ])

Performance monitoring

# monitor_node.py
import rclpy
from rclpy.node import Node
from diagnostic_msgs.msg import DiagnosticArray, DiagnosticStatus
import psutil
import pynvml

class IsaacROSMonitor(Node):
    def __init__(self):
        super().__init__('isaac_ros_monitor')

        pynvml.nvmlInit()
        self.gpu_handle = pynvml.nvmlDeviceGetHandleByIndex(0)

        self.diagnostics_pub = self.create_publisher(
            DiagnosticArray, '/diagnostics', 10
        )

        self.timer = self.create_timer(1.0, self.publish_diagnostics)

    def publish_diagnostics(self):
        msg = DiagnosticArray()
        msg.header.stamp = self.get_clock().now().to_msg()

        # GPU metrics
        gpu_util = pynvml.nvmlDeviceGetUtilizationRates(self.gpu_handle)
        gpu_mem = pynvml.nvmlDeviceGetMemoryInfo(self.gpu_handle)
        gpu_temp = pynvml.nvmlDeviceGetTemperature(
            self.gpu_handle, pynvml.NVML_TEMPERATURE_GPU
        )

        gpu_status = DiagnosticStatus()
        gpu_status.name = 'Isaac ROS GPU'
        gpu_status.level = DiagnosticStatus.OK
        gpu_status.values = [
            KeyValue(key='gpu_utilization', value=f'{gpu_util.gpu}%'),
            KeyValue(key='memory_used_mb', value=f'{gpu_mem.used / 1e6:.0f}'),
            KeyValue(key='temperature_c', value=f'{gpu_temp}')
        ]

        if gpu_temp > 80:
            gpu_status.level = DiagnosticStatus.WARN
            gpu_status.message = 'GPU temperature high'

        msg.status.append(gpu_status)
        self.diagnostics_pub.publish(msg)

ROS 2 Humble and Jazzy integration with Jetson

Workspace setup

# Setup Isaac ROS workspace on Jetson
mkdir -p ~/isaac_ros_ws/src
cd ~/isaac_ros_ws

# Clone Isaac ROS packages
git clone https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_common.git src/isaac_ros_common
git clone https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_visual_slam.git src/isaac_ros_visual_slam
git clone https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nvblox.git src/isaac_ros_nvblox

# Launch development container
cd src/isaac_ros_common
./scripts/run_dev.sh ~/isaac_ros_ws

# Inside container: build workspace
colcon build --symlink-install --packages-up-to isaac_ros_nvblox

Complete navigation stack launch

# full_navigation_stack.launch.py
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node

def generate_launch_description():
    use_sim_time = LaunchConfiguration('use_sim_time', default='false')

    return LaunchDescription([
        DeclareLaunchArgument('use_sim_time', default_value='false'),

        # Visual SLAM for localization
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource([
                get_package_share_directory('isaac_ros_visual_slam'),
                '/launch/isaac_ros_visual_slam.launch.py'
            ]),
            launch_arguments={'use_sim_time': use_sim_time}.items()
        ),

        # Nvblox for 3D reconstruction
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource([
                get_package_share_directory('nvblox_examples_bringup'),
                '/launch/nvblox.launch.py'
            ]),
            launch_arguments={
                'use_sim_time': use_sim_time,
                'people_segmentation': 'true'
            }.items()
        ),

        # Nav2 stack
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource([
                get_package_share_directory('nav2_bringup'),
                '/launch/navigation_launch.py'
            ]),
            launch_arguments={
                'use_sim_time': use_sim_time,
                'params_file': 'nav2_params.yaml'
            }.items()
        ),

        # Object detection for dynamic obstacles
        Node(
            package='isaac_ros_rtdetr',
            executable='rtdetr_node',
            parameters=[{
                'model_file_path': '/models/rtdetr.engine',
                'confidence_threshold': 0.5
            }]
        )
    ])

What Isaac ROS gives a robotics team

  1. NITROS zero-copy: type adaptation for 3-7x performance improvements
  2. Modular architecture: mix and match GEMs based on application requirements
  3. Synthetic data pipeline: train perception models with Isaac Sim's Replicator
  4. Production deployment: Docker images with CI/CD support
  5. Fleet scale: VDA5050 compliance for multi-robot coordination

The packages keep compatibility with the wider ROS 2 ecosystem, so they can be added to a stack that already exists.


References and further reading


Last updated: January 2026

Contact us about edge AI