How to Configure Custom Camera Paths in YAML for the Offline Renderer Flythrough

The offline renderer in the lingbot-map repository creates fly-through animations by reading a camera_path list from the evaluation.traj section of your benchmark YAML configuration, where each entry defines a camera pose through position, orientation, and optional timestamp or FOV values.

The lingbot-map repository provides an offline renderer that generates smooth fly-through visualizations of mapped environments. When you need to showcase specific viewpoints or create presentation-quality camera movements, you can override the default dataset trajectory by defining custom camera paths directly in your benchmark configuration files.

Understanding the Camera Path Configuration

The renderer initializes its trajectory by inspecting the evaluation.traj block in your YAML configuration. When the parser encounters a camera_path key, it bypasses the default dataset poses and instead builds the animation sequence from your manually specified list.

According to the source code in benchmark/benchmark/io/trajectory.py, the parser expects camera_path to contain a list of pose dictionaries. The rendering loop in lingbot_map/vis/viser_wrapper.py then consumes this data to drive the visualization, while lingbot_map/vis/utils.py handles the conversion of YAML specifications into the transformation matrices required by the graphics pipeline.

Required YAML Fields for Camera Poses

Every entry in the camera_path list must define the camera's spatial properties using specific data types. The renderer validates these fields before constructing the interpolation spline.

Position and Orientation

The two mandatory fields define where the camera is and which direction it faces:

  • position: A list of three floats representing world-space XYZ coordinates (e.g., [1.2, 0.5, 2.0])
  • orientation: A list of four floats representing a quaternion in (w, x, y, z) format (e.g., [0.9239, 0.0, 0.3827, 0.0] for a 45-degree yaw)

Optional FOV and Timestamp Parameters

You can fine-tune the visualization with two additional fields:

  • fov: A float specifying the horizontal field-of-view in degrees. If omitted, the renderer uses the default intrinsics from the dataset configuration.
  • timestamp: A float indicating the exact time in seconds when the camera should reach this pose. When omitted, the renderer assumes poses are equally spaced at one-second intervals.

Step-by-Step Configuration Guide

To implement a custom camera trajectory:

  1. Open your benchmark configuration file (commonly located at benchmark/configs/oxford.yaml or similar paths).
  2. Locate the evaluation section and ensure traj is enabled with enable: true and vis: true.
  3. Add the camera_path key under evaluation.traj and populate it with your desired pose list.
  4. Save the file and execute the offline renderer (e.g., python benchmark/run.py --config benchmark/configs/oxford.yaml).

The renderer will automatically interpolate between your specified points, creating a smooth spline that the fly-through visualizer follows.

Complete YAML Configuration Examples

Below are production-ready configurations demonstrating both timestamped and evenly-spaced camera paths.

Example with Explicit Timestamps

Use this format when you need precise control over timing and velocity:


# benchmark/configs/oxford.yaml

workspace: /path/to/workspace/oxford

datasets:
  - oxford

methods:
  - lingbot_map

evaluation:
  traj:
    enable: true
    vis: true
    camera_path:
      - position: [0.0, 0.0, 0.0]
        orientation: [1.0, 0.0, 0.0, 0.0]   # Identity quaternion

        fov: 60.0
        timestamp: 0.0
      - position: [1.2, 0.5, 2.0]
        orientation: [0.9239, 0.0, 0.3827, 0.0]   # 45° yaw

        fov: 60.0
        timestamp: 2.0
      - position: [2.5, -0.3, 3.1]
        orientation: [0.7071, 0.0, 0.7071, 0.0]   # 90° yaw

        fov: 60.0
        timestamp: 4.5

The renderer interpolates from the origin to the second pose over two seconds, then takes an additional 2.5 seconds to reach the final position.

Example with Equally-Spaced Sampling

Omit timestamps for simpler scenarios where uniform timing is acceptable:

evaluation:
  traj:
    enable: true
    vis: true
    camera_path:
      - position: [0.0, 0.0, 0.0]
        orientation: [1.0, 0.0, 0.0, 0.0]
      - position: [1.0, 0.2, 1.5]
        orientation: [0.9659, 0.0, 0.2588, 0.0]
      - position: [2.0, -0.1, 2.8]
        orientation: [0.8660, 0.0, 0.5, 0.0]

The system automatically assigns timestamps of 0.0, 1.0, and 2.0 seconds to these three poses, creating a constant-speed fly-through.

How the Renderer Processes Camera Paths

When the offline renderer initializes, the trajectory parser in benchmark/benchmark/io/trajectory.py validates the YAML structure and instantiates a CameraTrajectory object containing your custom path. If the camera_path key is absent, the system falls back to the original trajectory data stored in the dataset files.

The visualization engine in lingbot_map/vis/viser_wrapper.py queries this trajectory object during each frame of the render loop. Using helper functions from lingbot_map/vis/utils.py, it converts the quaternion and position data into view matrices, then interpolates between keyframes using either your explicit timestamps or the default uniform spacing.

Summary

  • The offline renderer reads camera paths from the evaluation.traj.camera_path key in benchmark YAML files.
  • Each pose requires a position (3 floats) and orientation quaternion (4 floats in w, x, y, z order).
  • Optional FOV and timestamp fields allow fine-tuning of the camera lens and animation timing.
  • The parser in benchmark/benchmark/io/trajectory.py creates the trajectory object, while lingbot_map/vis/viser_wrapper.py executes the rendering loop.
  • If no camera_path is specified, the renderer defaults to the dataset's original camera poses.

Frequently Asked Questions

What happens if I specify a camera path but omit the orientation field?

The renderer will fail to initialize the trajectory. According to the validation logic in benchmark/benchmark/io/trajectory.py, both position and orientation are mandatory fields for every entry in the camera_path list. You must provide a valid quaternion even if you only want positional movement.

Can I mix timestamps and non-timestamped poses in the same camera path?

No, the renderer expects a consistent timing strategy for the entire sequence. If any pose contains a timestamp field, the system assumes all poses use explicit timing. Mixing the two approaches will result in interpolation errors or unexpected animation speeds.

How do I calculate quaternion values for specific rotation angles?

You can convert Euler angles (roll, pitch, yaw) to the required (w, x, y, z) quaternion format using standard conversion formulas or ROS/SciPy utilities. For example, a 90-degree rotation around the Y-axis (yaw) converts to [0.7071, 0.0, 0.7071, 0.0] in the YAML configuration.

Where does the renderer look if I don't provide a custom camera path?

When the camera_path key is absent from evaluation.traj, the offline renderer in lingbot_map/vis/viser_wrapper.py automatically falls back to the camera poses stored in the original dataset trajectory files, using the same loading mechanism as the standard evaluation pipeline.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →