Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.cyberwave.com/llms.txt

Use this file to discover all available pages before exploring further.

Docker Images

The full robot stack is published as four images on Docker Hub, each available in three tags (jazzy, humble, jetson-humble):
ImageDescription
cyberwaveos/go2-ros2-driverGo2 driver, streaming bridges, edge bridge
cyberwaveos/ros2-nav2Nav2 navigation stack (robot-agnostic)
cyberwaveos/ros2-slamSLAM — RTAB-Map, slam_toolbox, Cartographer (robot-agnostic)
cyberwaveos/ros2-elevation-mappingGPU-accelerated elevation mapping (robot-agnostic)
The jetson-humble driver image ships with optimized defaults for constrained hardware.
docker pull cyberwaveos/go2-ros2-driver:jazzy
docker pull cyberwaveos/ros2-nav2:jazzy
docker pull cyberwaveos/ros2-slam:jazzy
docker pull cyberwaveos/ros2-elevation-mapping:jazzy

Quick Start

When connected to the Cyberwave platform, the edge-core service automatically pulls and starts all required containers based on the asset metadata configured for your twin. For local development with Docker Compose, see the driver README.

ROS 2 Topics

The driver publishes standard ROS 2 topics that any ROS 2 node can consume independently:
TopicTypeDescription
/odomnav_msgs/OdometryLiDAR-based odometry
/point_cloud2sensor_msgs/PointCloud23D point cloud from LiDAR
/scansensor_msgs/LaserScan2D laser scan (from point cloud)
/camera/image_rawsensor_msgs/ImageFront camera frames
/joint_statessensor_msgs/JointStateJoint positions and velocities
/imu/datasensor_msgs/ImuIMU measurements
/mapnav_msgs/OccupancyGridOccupancy map (from SLAM)
All robot-specific topics are namespaced as twin_<your-twin-uuid> by default.

Key Environment Variables

VariableDefaultDescription
CYBERWAVE_API_KEYCyberwave API token
CYBERWAVE_TWIN_UUIDDigital twin UUID
CYBERWAVE_MQTT_HOSTmqtt.cyberwave.comMQTT broker
ROBOT_IP(auto-discovered)Go2 IP — validated on startup; see below
ROBOT_IP_FALLBACKS192.168.12.1,192.168.123.161Comma-separated IPs to probe when ROBOT_IP is unset or unreachable
CONFIG_PROFILE(auto)Config profile: jazzy, humble, or jetson
CYBERWAVE_PERIODIC_MAP_UPLOAD_INTERVAL_SEC120Periodic map cloud sync interval (0 to disable)
GO2_USE_CPP_VOXEL_DECODERtrueUse C++ LiDAR decoder (faster)
GO2_OBSTACLE_AVOIDANCEtrueEnable onboard obstacle avoidance (see below)
CYBERWAVE_ENABLE_RECORDING(see below)Global recording toggle for video streams
CYBERWAVE_ENABLE_RECORDING_PREVIEWfalseRecord preview streams (occupancy, costmaps)

Obstacle Avoidance

When GO2_OBSTACLE_AVOIDANCE=true (the default), velocity commands are routed through the Go2’s firmware obstacle avoidance pipeline instead of the standard Sport API. The firmware fuses ultrasonic and LiDAR sensors to detect obstacles and will override velocity commands to prevent collisions. On startup the driver sends SwitchSet and UseRemoteCommandFromApi to the robot so the firmware accepts velocity commands from the ROS 2 stack rather than only the physical remote controller.
Onboard obstacle avoidance operates independently from Nav2’s path planner. The firmware may intervene — slowing down or stopping the robot — even when Nav2 considers the path clear. This can cause Nav2 goals to take longer or be aborted if the firmware repeatedly blocks planned motion. If you need full control over obstacle handling through Nav2’s costmaps and local planner, set GO2_OBSTACLE_AVOIDANCE=false.
To disable:
GO2_OBSTACLE_AVOIDANCE=false

Robot IP discovery

The driver validates that the Go2 is reachable before starting any ROS 2 node, so you get a fast failure instead of a silent WebRTC hang. Resolution order:
  1. ROBOT_IP (from env or Edge Core metadata) — probed via TCP on port 9991.
  2. If unreachable (or unset), each address in ROBOT_IP_FALLBACKS is tried.
  3. First address that responds is used for the entire stack.
  4. If nothing responds, the container exits with an error and pushes a robot_unreachable alert to Cyberwave (if SDK credentials are available).
The default fallback list covers the two most common Go2 network configurations:
AddressScenario
192.168.12.1Wi-Fi AP / USB-Ethernet
192.168.123.161Ethernet direct-connect
Custom networks: If your Go2 is on a different subnet (e.g. behind a router), override the fallback list:
# .env file or Edge Core shared_env
ROBOT_IP_FALLBACKS=10.0.0.50,10.0.0.51
You can set both ROBOT_IP (preferred address) and ROBOT_IP_FALLBACKS (safety net). If the preferred IP is unreachable, the driver automatically falls through to the fallback list.
The probe uses a TCP socket connect on port 9991 (Go2 WebRTC signaling) with a 2-second timeout per address. No WebRTC handshake is attempted. Simulation launches skip the check entirely.

Config Profiles

ProfileWhen to use
jazzyDefault for ROS 2 Jazzy on desktop/server hardware
humbleROS 2 Humble ecosystem compatibility
jetsonNVIDIA Jetson: reduced costmap resolution, increased transform tolerances, lower rates
Set CONFIG_PROFILE=jetson or use the jetson-humble Docker image which sets this automatically.

Edge Core metadata

When using Cyberwave Edge Core for managed deployment, the driver stack is configured through twin/asset metadata. Edge Core reads this metadata, pulls images, and injects environment variables automatically.

Multi-container configuration

The Go2 ROS 2 stack runs as multiple cooperating containers. Define the stack in metadata.drivers using the services array:
{
  "drivers": {
    "linux-aarch64-jetson": {
      "services": [
        {
          "image": "cyberwaveos/go2-ros2-driver:jetson-humble",
          "name": "driver",
          "command": [
            "ros2",
            "launch",
            "cyberwave_go2_driver",
            "robot_driver.launch.py"
          ]
        },
        {
          "image": "cyberwaveos/go2-ros2-driver:jetson-humble",
          "name": "bridges",
          "command": [
            "ros2",
            "launch",
            "cyberwave_go2_driver",
            "robot_bridges.launch.py"
          ]
        },
        { "image": "cyberwaveos/ros2-nav2:jetson-humble", "name": "nav2" },
        { "image": "cyberwaveos/ros2-slam:jetson-humble", "name": "slam" }
      ],
      "shared_env": {
        "CONFIG_PROFILE": "jetson",
        "ROS_DOMAIN_ID": "0"
      },
      "shared_params": ["--network", "host", "-v", "/data:/data"]
    },
    "default": {
      "docker_image": "cyberwaveos/go2-ros2-driver:jazzy",
      "prefer_gpu": true
    }
  }
}
To add a service (e.g. elevation mapping), append to the services array. To set the robot IP or fallback list, add them to shared_env:
"shared_env": {
  "ROBOT_IP_FALLBACKS": "10.0.0.50,10.0.0.51",
  "CONFIG_PROFILE": "jetson"
}
See Drivers overview for the full metadata schema and Writing compatible drivers for the edge_configs per-device pattern.

Stream Recording

The Go2 driver streams video to the Cyberwave media service via WebRTC. Each stream can request server-side recording (producing MP4 artifacts for later replay).
VariableDefaultApplies to
CYBERWAVE_ENABLE_RECORDINGAll streams (global override)
CYBERWAVE_ENABLE_RECORDING_PREVIEWfalsePreview streams only (occupancy grid, local/global costmaps)
Default behavior (no env vars set):
  • camera_bridge — records by default (true).
  • occupancy_grid_bridge, local_costmap_bridge, global_costmap_bridge — do not record by default.
Resolution order per bridge:
  1. CYBERWAVE_ENABLE_RECORDING — if set, overrides everything.
  2. Per-bridge env var (e.g. CYBERWAVE_ENABLE_RECORDING_PREVIEW) — overrides the built-in default.
  3. Built-in default.
# Record everything including previews
CYBERWAVE_ENABLE_RECORDING_PREVIEW=true

# Disable all recording (e.g. for development)
CYBERWAVE_ENABLE_RECORDING=false
Recording is handled by the media service SFU, not on the edge device. Enabling recording adds negligible load to the robot’s hardware.

Jetson Performance Tuning

Running the full Go2 stack on a Jetson Orin Nano (or similar constrained hardware) requires tuning runtime rates and encoder settings. Add these to your .env file or Edge Core shared_env:
# ── Runtime rates (overrides vs. defaults) ───────────────────────────
GO2_STATE_PUBLISH_HZ=15          # default 10
GO2_POINTCLOUD_MAX_POINTS=4000   # default 25000
GO2_POINTCLOUD_STREAM_FPS=1      # default 5
GO2_SCAN_ANGLE_INCREMENT=0.01745 # default 0.00872
GO2_TRAV_COSTMAP_HZ=5            # default 10
GO2_TRAV_COSTMAP_GLOBAL_HZ=0.5   # default 1
GO2_LOCAL_COSTMAP_FPS=10         # default 5
GO2_GLOBAL_COSTMAP_FPS=10        # default 2

# ── Obstacle avoidance ──────────────────────────────────────────────
# Disable if Nav2 handles obstacle avoidance to save CPU.
GO2_OBSTACLE_AVOIDANCE=false     # default true

# ── H.264 encoding ──────────────────────────────────────────────────
# Jetson Orin Nano has NO hardware H.264 encoder (no NVENC).
# Skip codec probing and constrain libx264 to a single thread so it
# doesn't starve SLAM/Nav2. At 424x240@1fps ultrafast this uses <5%
# of one core.
CYBERWAVE_H264_ENCODER=libx264   # default auto
CYBERWAVE_H264_PRESET=ultrafast  # default veryfast
CYBERWAVE_H264_BITRATE_KBPS=800  # default 2500
CYBERWAVE_H264_THREADS=1         # default 0 (unlimited)
These values are tuned for a Jetson Orin Nano running the full stack (driver + Nav2 + SLAM). If your board has more headroom (e.g. Orin NX) or less (e.g. other services running), you can adjust camera and pointcloud rates accordingly.

NVIDIA Container Toolkit (Jetson / GPU)

GPU-accelerated containers (simulation, video decode, elevation mapping) require the NVIDIA Container Toolkit. This is especially important on Jetson (L4T / JetPack) where the toolkit must be installed and the runtime registered with Docker.
# Install
distribution=$(. /etc/os-release; echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit

# Register with Docker
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
On Jetson, set the NVIDIA runtime as the default so all containers get GPU access automatically:
sudo tee /etc/docker/daemon.json <<'EOF'
{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "args": [],
            "path": "nvidia-container-runtime"
        }
    }
}
EOF
sudo systemctl restart docker
If nvidia-container-toolkit is already installed but containers cannot access the GPU, re-run the nvidia-ctk runtime configure step, ensure daemon.json has the nvidia runtime, and restart Docker.