A modern robotics visualization tool built in Rust, combining Makepad UI, Rerun 3D visualization, and Zenoh distributed networking for debugging robots and autonomous systems.
- Distributed-first architecture: Debug robots remotely over LAN using Zenoh auto-discovery
- Dora dataflow integration: Visualize sensor pipelines and node activity
- Rerun 3D visualization: Point clouds, transforms, markers, robot models
- ROS bag playback: Multi-sensor support (LiDAR, IMU, GPS, TF)
- URDF robot models: Load and visualize robot meshes
# Rust (nightly required for Makepad) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh rustup install nightly rustup default nightly # Dora CLI cargo install dora-cli # Python dependencies (for example dataflows) pip install dora-rs pyyaml numpy pyarrowgit clone https://github.com/bobd988/dviz.git cd dviz cargo build --releaseThis builds:
dviz- Main visualization shelldviz-dora-bridge- Dora node that publishes data via Zenoh
# Terminal 1: Start Dora daemon dora up # Terminal 2: Run a dataflow dora start dataflow.yml --name dviz # Terminal 3: Run DViz cargo run -p dviz-shell --releaseIn the DViz UI:
- Click Spawn Rerun to open the 3D viewer
- Zenoh auto-connects on startup (status shows "Zenoh: Connected")
- View vehicle simulation data in Rerun
This example runs a vehicle path-following simulation with:
bicycle_model- Vehicle physics simulatorsimple_planner- Pure pursuit path followingimu_synthesizer- Synthetic IMU generationdviz_bridge- Publishes data via Zenoh
# Terminal 1 dora up # Terminal 2 dora start examples/dataflow-path-following.yml --name pathfollow # Terminal 3 cargo run -p dviz-shell --releaseThe visualization shows:
- Vehicle pose: Arrow showing position and heading
- Waypoints: Line strip showing planned path
- Target point: Current pursuit target
- IMU data: Acceleration/gyroscope scalars
This example runs a vehicle mapping pipeline that builds a 3D map from point cloud data using ICP odometry.
# Additional Python dependencies pip install open3d # Clone dora-examples (contains the mapping operators) git clone https://github.com/dora-rs/dora-examples.git ~/dora-examples# Terminal 1: Start Dora daemon dora up # Terminal 2: Run the mapping dataflow dora start examples/dataflow-mapping.yml --name mapping # Terminal 3: Run DViz cargo run -p dviz-shell --releaseIn the DViz UI:
- Click Spawn Rerun to open the 3D viewer
- Zenoh auto-connects and receives mapping data
The visualization shows:
- Point clouds: LiDAR scans from PCD files
- Odometry pose: Vehicle position estimated by ICP
- Trajectory: Path traveled by the vehicle
DViz can play back ROS1 bag files with multi-sensor visualization support.
- PointCloud2: LiDAR point clouds (e.g., Velodyne)
- Imu: Accelerometer and gyroscope data
- NMEA Sentence: GPS position from NMEA messages
- TimeReference: GPS time synchronization
- Temperature: Temperature sensor readings
# Terminal 1: Run DViz cargo run -p dviz-shell --releaseIn the DViz UI:
- Click Spawn Rerun to open the 3D viewer
- Click File → Open Bag (or use the File button)
- Select the bag file:
examples/hdl_400.bag - Click Play to start playback
- Play/Pause: Toggle playback
- Stop: Reset to beginning
- Seek: Jump to specific time in the bag
The hdl_400.bag example displays:
- world/lidar: Velodyne point cloud (height-colored)
- world/imu/accel_arrow: Acceleration vector (cyan)
- world/imu/gyro_arrow: Angular velocity vector (orange)
- world/imu/accel_x,y,z: Acceleration scalars
- world/imu/gyro_x,y,z: Gyroscope scalars
- world/gps/position: GPS position (green point)
- world/gps/latitude,longitude,altitude: GPS scalars
- world/temperature/celsius: Temperature reading
DViz is designed for remote debugging where:
- Robot runs the dataflow headlessly (no display)
- Debug PC runs DViz to visualize robot data over LAN
┌─────────────────────┐ Zenoh (LAN) ┌─────────────────────┐ │ ROBOT │ ─────────────────────────── │ DEBUG PC │ │ (192.168.1.10) │ UDP Multicast │ (192.168.1.20) │ │ │ 224.0.0.225:7446 │ │ │ dora up │ │ cargo run -p │ │ dora start │ │ dviz-shell │ │ dataflow-robot │ ────────────> │ │ │ .yml │ sensor data │ Rerun 3D viewer │ └─────────────────────┘ └─────────────────────┘ SSH into the robot and run:
cd /path/to/dviz # Build the bridge (first time only) cargo build --release -p dviz-rerun-bridge # Start Dora daemon dora up # Run the robot dataflow dora start examples/dataflow-robot.yml --name robotThe robot will publish data to Zenoh topics:
dviz/pose- Vehicle positiondviz/state- Vehicle statedviz/imu- IMU readingsdviz/waypoints- Planned path
cd /path/to/dviz # Run DViz cargo run -p dviz-shell --releaseDViz auto-connects via Zenoh multicast scouting. Both machines must be on the same LAN subnet.
Zenoh uses multicast scouting by default:
- UDP multicast on
224.0.0.225:7446 - Works automatically on the same LAN subnet
- No configuration needed
If machines are on different subnets or multicast is blocked:
Set environment variable on the subscriber (debug PC):
ZENOH_CONNECT=tcp/192.168.1.10:7447 cargo run -p dviz-shellOr in the dataflow YAML on the robot:
nodes: - id: dviz_bridge path: target/release/dviz-dora-bridge env: ZENOH_CONNECT: tcp/192.168.1.20:7447 # Debug PC addressRun a Zenoh router as a central hub:
# On any machine accessible by both robot and PC zenohdThen configure both sides to connect:
# Robot ZENOH_CONNECT=tcp/router-ip:7447 dora start dataflow-robot.yml # PC ZENOH_CONNECT=tcp/router-ip:7447 cargo run -p dviz-shell- Find new robot IP:
ip addrorhostname -I - If using direct connection, update debug PC:
ZENOH_CONNECT=tcp/<new-robot-ip>:7447 cargo run -p dviz-shell
- If using auto-discovery, no changes needed (same subnet)
- If robot is configured to connect to PC:
# Update dataflow-robot.yml env: ZENOH_CONNECT: tcp/<new-pc-ip>:7447
- Restart the dataflow:
dora stop robot dora start examples/dataflow-robot.yml --name robot
Use a Zenoh router with a static IP that both can reach:
# Router machine (e.g., 192.168.1.1) zenohd --listen tcp/0.0.0.0:7447 # Robot (any subnet) ZENOH_CONNECT=tcp/192.168.1.1:7447 dora start ... # PC (any subnet) ZENOH_CONNECT=tcp/192.168.1.1:7447 cargo run -p dviz-shell| Symptom | Cause | Solution |
|---|---|---|
| "Zenoh: Connecting..." hangs | Multicast blocked | Use ZENOH_CONNECT |
| No data in Rerun | Firewall blocking | Open UDP 7446, TCP 7447 |
| Intermittent data | Network congestion | Use wired connection |
| Works locally, not remote | Different subnets | Use Zenoh router |
# Linux (robot and PC) sudo ufw allow 7446/udp # Zenoh scouting sudo ufw allow 7447/tcp # Zenoh data # Or disable firewall for testing sudo ufw disable| Variable | Default | Description |
|---|---|---|
ZENOH_CONNECT | (auto-discovery) | Router address, e.g., tcp/192.168.1.100:7447 |
ZENOH_TOPIC_PREFIX | dviz | Topic namespace for all messages |
RUST_LOG | info | Log level (debug, info, warn, error) |
| File | Description |
|---|---|
dataflow.yml | Local simulation with DViz bridge |
examples/dataflow-path-following.yml | Vehicle path following (same as above) |
examples/dataflow-robot.yml | Headless robot dataflow for remote debug |
examples/dataflow-ros2.yml | ROS2 bridge integration |
examples/dataflow-mapping.yml | Point cloud mapping pipeline |
dviz/ ├── dviz-core/ # Core types (Transform, PointCloud, Marker) ├── dviz-transform/ # Coordinate frame system ├── dviz-displays/ # Display plugins (Grid, TF, PointCloud, etc.) ├── dviz-urdf/ # URDF parsing and robot models ├── dviz-shell/ # Main application (Makepad UI) ├── dviz-widgets/ # Reusable UI components ├── dviz-rerun-bridge/ # Dora-to-Zenoh bridge node ├── dviz-rosbag/ # ROS bag playback ├── examples/ # Dataflow configurations └── docs/ # Design documentation DViz uses a universal JSON protocol that any application can publish:
{ "type": "points3d", "timestamp": 1.5, "data": { "positions": [[0, 0, 0], [1, 1, 1]], "color": [255, 0, 0, 255] } }Supported types: points3d, arrows3d, linestrips3d, boxes3d, transform3d, scalar, image, log
Topic format: {prefix}/{entity_path} (e.g., dviz/world/vehicle/lidar)
Apache-2.0

