Skip to main content

VSLAM Navigation

Introduction​

Visual SLAM (Simultaneous Localization and Mapping) enables robots to build maps while tracking their position using only cameras. Isaac ROS Visual SLAM provides GPU-accelerated VSLAM that runs at 60 Hz on Jetson and desktop GPUs.

Learning Objectives:

  • Understand VSLAM principles
  • Set up Isaac ROS Visual SLAM
  • Calibrate stereo cameras
  • Run real-time localization and mapping
  • Integrate VSLAM with navigation stack

Theory​

What is VSLAM?​

Visual SLAM solves two problems simultaneously:

  1. Localization: Where is the robot?
  2. Mapping: What does the environment look like?

Input: Stereo camera images or depth camera Output:

  • Robot pose (position + orientation)
  • 3D point cloud map
  • Tracked features

Isaac VSLAM Architecture​

┌─────────────────────────────────────────────┐
│ Stereo Cameras → Rectification → Feature │
│ (Left/Right) (CUDA) Tracking │
│ (CUDA) │
└─────────────────────────────────────────────┘
↓
┌──────────────────────┐
│ Visual Odometry │
│ (Track features) │
└──────────────────────┘
↓
┌──────────────────────┐
│ Loop Closure │
│ (Recognize places) │
└──────────────────────┘
↓
┌──────────────────────┐
│ Pose Graph │
│ Optimization │
└──────────────────────┘

VSLAM vs LiDAR SLAM​

FeatureVSLAMLiDAR SLAM
SensorStereo/Depth cameraLiDAR scanner
CostLow (cameras ~$100)High (LiDAR ~$1000+)
Range2-10m10-100m
LightingNeeds lightWorks in dark
TextureNeeds featuresWorks on plain walls
ComputeGPU-acceleratedCPU
Use CaseIndoor, texturedOutdoor, large spaces

Installation​

Prerequisites​

# Ubuntu 22.04 with ROS 2 Humble
# NVIDIA GPU with CUDA support

# Verify CUDA
nvcc --version

Install Isaac ROS Visual SLAM​

# Create workspace
mkdir -p ~/isaac_vslam_ws/src
cd ~/isaac_vslam_ws/src

# Clone repositories
git clone https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_common.git
git clone https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_visual_slam.git
git clone https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_image_pipeline.git

# Install dependencies
cd ~/isaac_vslam_ws
rosdep install --from-paths src --ignore-src -r -y

# Build
colcon build --symlink-install

# Source workspace
source install/setup.bash

Camera Setup​

Stereo Camera Calibration​

Supported Cameras:

  • Intel RealSense D435i, D455
  • ZED 2, ZED 2i
  • OAK-D
  • Custom stereo rigs

Calibrate Camera:

# Install camera calibration package
sudo apt install ros-humble-camera-calibration

# Launch calibration (8x6 checkerboard, 0.025m squares)
ros2 run camera_calibration cameracalibrator \
--size 8x6 \
--square 0.025 \
--no-service-check \
--ros-args \
-r image:=/camera/left/image_raw \
-r camera:=/camera/left

# Repeat for right camera
ros2 run camera_calibration cameracalibrator \
--size 8x6 \
--square 0.025 \
--no-service-check \
--ros-args \
-r image:=/camera/right/image_raw \
-r camera:=/camera/right

Save calibration files to:

  • ~/.ros/camera_info/left.yaml
  • ~/.ros/camera_info/right.yaml

RealSense Camera Setup​

# Install RealSense ROS wrapper
sudo apt install ros-humble-realsense2-camera

# Launch RealSense with stereo
ros2 launch realsense2_camera rs_launch.py \
enable_infra1:=true \
enable_infra2:=true \
enable_depth:=true

Running Isaac VSLAM​

Launch VSLAM​

Create vslam.launch.py:

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
return LaunchDescription([
# RealSense camera
Node(
package='realsense2_camera',
executable='realsense2_camera_node',
parameters=[{
'enable_infra1': True,
'enable_infra2': True,
'enable_depth': True,
'depth_module.profile': '640x480x30',
'infra_fps': 30.0
}]
),

# Image rectification
Node(
package='isaac_ros_image_proc',
executable='image_format_converter_node',
parameters=[{
'encoding_desired': 'rgb8'
}],
remappings=[
('image_raw', '/camera/infra1/image_rect_raw'),
('image', '/camera/left/image_rect')
]
),

Node(
package='isaac_ros_image_proc',
executable='image_format_converter_node',
parameters=[{
'encoding_desired': 'rgb8'
}],
remappings=[
('image_raw', '/camera/infra2/image_rect_raw'),
('image', '/camera/right/image_rect')
]
),

# Isaac VSLAM
Node(
package='isaac_ros_visual_slam',
executable='isaac_ros_visual_slam',
parameters=[{
'denoise_input_images': False,
'rectified_images': True,
'enable_debug_mode': False,
'debug_dump_path': '/tmp/vslam',
'enable_slam_visualization': True,
'enable_landmarks_view': True,
'enable_observations_view': True,
'map_frame': 'map',
'odom_frame': 'odom',
'base_frame': 'base_link',
'camera_optical_frames': [
'camera_infra1_optical_frame',
'camera_infra2_optical_frame'
]
}],
remappings=[
('stereo_camera/left/image', '/camera/left/image_rect'),
('stereo_camera/left/camera_info', '/camera/infra1/camera_info'),
('stereo_camera/right/image', '/camera/right/image_rect'),
('stereo_camera/right/camera_info', '/camera/infra2/camera_info')
]
)
])

Launch:

ros2 launch vslam.launch.py

Monitor VSLAM Output​

Published Topics:

# Robot pose
ros2 topic echo /visual_slam/tracking/odometry

# Map points
ros2 topic echo /visual_slam/tracking/slam_path

# Tracking status
ros2 topic echo /visual_slam/status

Visualize in RViz:

rviz2

# Add displays:
# - TF (to see robot movement)
# - Odometry (/visual_slam/tracking/odometry)
# - PointCloud2 (/visual_slam/vis/landmarks_cloud)
# - Path (/visual_slam/tracking/slam_path)

Integrate Isaac VSLAM with Nav2 navigation stack:

# nav2_vslam.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
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')

return LaunchDescription([
# VSLAM for localization
IncludeLaunchDescription(
PythonLaunchDescriptionSource([vslam_launch_file])
),

# Nav2 navigation
IncludeLaunchDescription(
PythonLaunchDescriptionSource([
os.path.join(nav2_bringup_dir, 'launch', 'navigation_launch.py')
]),
launch_arguments={
'use_sim_time': 'false',
'params_file': '/path/to/nav2_params.yaml'
}.items()
)
])

Set Navigation Goal​

# Send goal via command line
ros2 topic pub --once /goal_pose geometry_msgs/msg/PoseStamped \
"{header: {frame_id: 'map'},
pose: {position: {x: 2.0, y: 1.0, z: 0.0},
orientation: {w: 1.0}}}"

Performance Tuning​

Optimize for Speed​

# VSLAM parameters for high-speed operation
parameters:
enable_imu_fusion: true # Use IMU if available
num_cameras: 2
horizontal_stereo_camera: true

# Feature tracking
max_features_per_frame: 1000 # Reduce for speed
min_num_features: 100

# Mapping
enable_localization_n_mapping: true
enable_reading_slam_internals: false

# Performance
use_gpu: true
gpu_id: 0

Quality vs Speed​

SettingSpeedAccuracyUse Case
max_features: 2000SlowHighPrecise mapping
max_features: 1000MediumMediumBalanced
max_features: 500FastLowerFast navigation

Troubleshooting​

Issue 1: Poor Tracking​

Symptoms: Robot pose jumps, tracking lost Causes:

  • Insufficient lighting
  • Lack of visual features (plain walls)
  • Camera framerate too low
  • Motion too fast

Solutions:

# Increase lighting
# Add textured objects to environment
# Slow down robot motion
# Increase camera framerate to 60 FPS

Issue 2: Drift Over Time​

Symptoms: Map slowly shifts Solution: Enable loop closure

parameters:
enable_loop_closure: true
loop_closure_period: 10 # Seconds between checks

Issue 3: High CPU Usage​

Symptoms: High CPU despite GPU acceleration Solution: Ensure CUDA is being used

# Check GPU utilization
nvidia-smi -l 1

# Verify CUDA-enabled build
ros2 pkg prefix isaac_ros_visual_slam

Advanced: IMU Fusion​

Combine VSLAM with IMU for better tracking:

Node(
package='isaac_ros_visual_slam',
executable='isaac_ros_visual_slam',
parameters=[{
'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 frequency
}],
remappings=[
('visual_slam/imu', '/camera/imu')
]
)

Exercises​

  1. Run Isaac VSLAM with RealSense camera and visualize in RViz
  2. Map a room: Walk robot around and observe map building
  3. Test loop closure: Return to starting position and verify drift correction
  4. Compare performance: Measure FPS with CPU SLAM vs Isaac VSLAM
  5. Navigation: Set goal pose and let robot navigate autonomously

Summary​

Isaac ROS Visual SLAM provides GPU-accelerated localization and mapping using stereo or depth cameras, enabling real-time navigation at 60 Hz. Integration with Nav2 allows autonomous robot navigation using only visual sensors.

Further Reading​