Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

3D Visualization

The kinetic-viewer crate provides an interactive 3D viewer for robot visualization, motion planning, and trajectory playback. It includes both a windowed GUI (with egui panels) and a headless renderer for CI pipelines and screenshot generation.

Quick Start

Launch the viewer for a built-in robot:

cargo run -p kinetic-viewer --features cli -- --robot ur5e

List all 54 supported robots:

cargo run -p kinetic-viewer --features cli -- --list-robots

Load a custom URDF file:

cargo run -p kinetic-viewer --features cli -- --robot path/to/robot.urdf

Features

Interactive GUI

The viewer opens a wgpu-rendered window with egui side panels:

  • Joint sliders – drag individual joints to see the robot move in real time
  • Planning panel – set start/goal configurations and run RRT, PRM, or other planners
  • Servo panel – real-time velocity-based end-effector control
  • Constraint panel – visualize joint limits and workspace constraints
  • Scene objects – add/remove obstacles and inspection targets
  • Trajectory playback – animate planned paths with speed control and looping
  • Collision debug – toggle sphere model visualization

Rendering

  • Hardware-accelerated via wgpu (Vulkan, Metal, DX12)
  • Grid floor, coordinate axes, and wireframe overlays
  • Per-link coloring and transparency for ghost robots
  • Trajectory trail visualization

Headless Rendering

The HeadlessRenderer renders to an offscreen texture without a window. It works with software Vulkan (lavapipe) for CI environments and with NVIDIA/AMD GPUs for production screenshots.

Keyboard Shortcuts

KeyAction
GToggle grid
AToggle coordinate axes
TToggle trajectory trail
CToggle collision debug spheres
WToggle collision wireframe
VToggle voxel display
PToggle point cloud
RReset camera to default position
FFocus camera on goal marker
ZUndo last interaction
SpacePlay/pause trajectory
F1Show/hide keyboard shortcuts
F3Show/hide stats overlay
EscQuit

Mouse controls: left-drag to orbit, right-drag to pan, scroll to zoom.

Screenshots

Headless screenshots of robots at their zero joint configuration, rendered using collision geometry primitives with per-link color gradients.

RobotScreenshot
UR5eUR5e
Franka PandaFranka Panda
KUKA iiwa14KUKA iiwa14
xArm7xArm7

To regenerate screenshots:

VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json \
  cargo run -p kinetic-viewer --example capture_screenshots --features visual

API Usage

Embedding in Custom Applications

Use kinetic-viewer as a library to render robots in your own application:

#![allow(unused)]
fn main() {
use kinetic_viewer::{robot_scene_graph, Camera, MeshRegistry, ViewerSettings};
use kinetic_viewer::app::{run_viewer, ViewerConfig};
use kinetic_robot::Robot;

let robot = Robot::from_name("ur5e")?;
let camera = Camera::perspective([1.5, 1.0, 1.5], [0.0, 0.3, 0.0], 45.0);
let config = ViewerConfig {
    title: "My Robot Viewer".into(),
    ..Default::default()
};
run_viewer(config, robot, camera)?;
}

Headless Rendering (Screenshots, CI)

Render to PNG without a window:

#![allow(unused)]
fn main() {
use kinetic_viewer::test_utils::HeadlessRenderer;
use kinetic_viewer::{robot_scene_graph, Camera, MeshRegistry, ViewerSettings};
use kinetic_robot::Robot;

let robot = Robot::from_name("ur5e").unwrap();
let mut meshes = MeshRegistry::new();
let scene = robot_scene_graph(&robot, &mut meshes);
let camera = Camera::perspective([1.5, 1.0, 1.5], [0.0, 0.3, 0.0], 45.0);
let settings = ViewerSettings::default();

let mut renderer = HeadlessRenderer::new(1280, 720).unwrap();
renderer.upload_meshes(&meshes);
let pixels = renderer.render(&scene, &camera, &settings);

// Save as PNG (requires `image` crate)
image::save_buffer(
    "screenshot.png", &pixels, 1280, 720,
    image::ColorType::Rgba8,
).unwrap();
}

Visual Regression Testing

Compare two renders for pixel-level differences:

#![allow(unused)]
fn main() {
use kinetic_viewer::test_utils::{compare_screenshots, diff_image};

let result = compare_screenshots(&actual, &expected, 1280, 720, 2);
assert!(result.rmse < 5.0, "Visual regression: RMSE={}", result.rmse);

// Generate a red/green diff image for inspection
let diff = diff_image(&actual, &expected, 1280, 720);
}

Crate Features

FeatureDescription
visualGPU rendering, mesh loading, image export
cliCommand-line interface (--robot, --list-robots)

The visual feature is enabled by default. Use --no-default-features for data-model-only usage (scene graph, camera math, render commands) without GPU dependencies.

Architecture

kinetic-viewer
  +-- lib.rs         Scene graph, Camera, MeshData, ViewerSettings, RenderCommand
  +-- app.rs         Windowed viewer (winit + wgpu + egui)
  +-- gpu_context.rs wgpu device/surface setup
  +-- pipeline.rs    Mesh, wireframe, and line render pipelines
  +-- gpu_buffers.rs GPU buffer management (instances, lines, uniforms)
  +-- test_utils.rs  HeadlessRenderer + screenshot comparison
  +-- egui_ui.rs     Joint sliders, planning panel, servo panel
  +-- gizmo.rs       3D gizmo interaction (translate/rotate handles)
  +-- interaction.rs Markers, selection, undo
  +-- collision_viz.rs  Collision sphere debug overlays
  +-- trajectory_viz.rs Trajectory playback + ghost robots
  +-- perception_viz.rs Point cloud + voxel display
  +-- web_export.rs  Scene export for web viewers