# How to Configure a Custom Camera Path with YAML Presets in Offline Rendering

> Learn to configure a custom camera path in offline rendering using YAML presets. Easily define camera movements and integrate them with rgbd_scan_render.py for stunning visuals.

- Repository: [Robbyant/lingbot-map](https://github.com/Robbyant/lingbot-map)
- Tags: how-to-guide
- Published: 2026-07-26

---

**To configure a custom camera path in LingBot-Map's offline renderer, create a YAML preset file defining timestamped camera positions and orientations, then pass it to [`rgbd_scan_render.py`](https://github.com/Robbyant/lingbot-map/blob/main/rgbd_scan_render.py) using the `--preset` flag.**

The LingBot-Map repository provides an offline rendering pipeline that converts trained models into RGB-D sequences using predefined camera trajectories. By leveraging YAML presets, you can precisely control every frame's viewpoint without modifying the underlying Python source code. This workflow allows you to define complex camera motions through simple configuration files that the batch renderer consumes directly.

## Understanding the Camera Path Schema

The offline rendering system expects a specific YAML structure defined in the `camera` block. This schema supports both sparse keyframes with interpolation and fully defined frame sequences.

### Required Camera Parameters

Each frame entry in the `camera` list must declare:

- **`position`**: A 3-element list representing Cartesian coordinates `[x, y, z]`
- **`orientation`**: A 4-element quaternion in the format `[qw, qx, qy, qz]` representing the rotation

The loader validates these fields strictly; missing entries will raise a validation error during initialization.

### Optional Configuration Fields

You can augment each frame with additional metadata:

- **`timestamp`**: A float indicating the frame time
- **`intrinsics`**: A nested dictionary containing camera parameters (`fx`, `fy`, `cx`, `cy`)
- **`interpolate`**: A boolean flag at the root level that enables linear interpolation between sparse keyframes

## Creating Your Custom Camera Path File

Create a YAML file (e.g., [`my_camera_path.yaml`](https://github.com/Robbyant/lingbot-map/blob/main/my_camera_path.yaml)) anywhere in your filesystem. The following example defines a three-keyframe trajectory with explicit intrinsics and interpolation enabled:

```yaml

# my_camera_path.yaml

camera:
  - timestamp: 0.0
    position: [0.0, 0.0, 0.0]
    orientation: [1.0, 0.0, 0.0, 0.0]   # w, x, y, z quaternion

    intrinsics:
      fx: 500.0
      fy: 500.0
      cx: 320.0
      cy: 240.0
  - timestamp: 2.0
    position: [1.0, 0.5, 0.2]
    orientation: [0.9239, 0.0, 0.3827, 0.0]
  - timestamp: 4.0
    position: [2.0, 0.0, 0.0]
    orientation: [0.7071, 0.0, 0.7071, 0.0]
interpolate: true        # ask the renderer to fill in intermediate frames

```

## Executing the Renderer with Custom Presets

Pass your preset file to [`demo_render/rgbd_scan_render.py`](https://github.com/Robbyant/lingbot-map/blob/main/demo_render/rgbd_scan_render.py) using the `--preset` argument. The renderer merges your configuration with defaults from [`benchmark/configs/base.yaml`](https://github.com/Robbyant/lingbot-map/blob/main/benchmark/configs/base.yaml), so you only need to specify fields you wish to override.

```bash
python demo_render/rgbd_scan_render.py \
    --model_path /path/to/lingbot-map.pt \
    --image_folder example/university \
    --preset my_camera_path.yaml \
    --keyframe_interval 1   # generate a frame for every timestamp step

```

If you specified `interpolate: true` in your preset, the renderer will generate intermediate frames between your defined timestamps based on the `--keyframe_interval` value.

## How Configuration Loading Works

According to the LingBot-Map source code, the preset parsing happens in [`benchmark/benchmark/core/config.py`](https://github.com/Robbyant/lingbot-map/blob/main/benchmark/benchmark/core/config.py). The `_load_yaml` function (lines 75-84) uses `yaml.safe_load` to deserialize your file, then merges it with global defaults. This architecture ensures that your custom camera path inherits standard parameters (such as default intrinsics) while allowing precise overrides for specific frames.

The batch renderer scripts ([`demo_render/batch_demo.py`](https://github.com/Robbyant/lingbot-map/blob/main/demo_render/batch_demo.py) or [`demo_render/rgbd_scan_render.py`](https://github.com/Robbyant/lingbot-map/blob/main/demo_render/rgbd_scan_render.py)) consume this merged configuration to initialize the camera trajectory before generating RGB-D outputs.

## Summary

- **Create a YAML preset** with a top-level `camera` key containing a list of frame dictionaries
- **Define required fields** (`position` and `orientation`) for each keyframe, optionally adding `timestamp` and `intrinsics`
- **Enable interpolation** by setting `interpolate: true` to generate intermediate frames between sparse keyframes
- **Execute via command line** using `--preset /path/to/your/file.yaml` when running the rendering scripts
- **Leverage configuration merging** to inherit defaults from [`benchmark/configs/base.yaml`](https://github.com/Robbyant/lingbot-map/blob/main/benchmark/configs/base.yaml) while overriding specific trajectory parameters

## Frequently Asked Questions

### Where does LingBot-Map load YAML preset configurations?

The configuration loading logic resides in [`benchmark/benchmark/core/config.py`](https://github.com/Robbyant/lingbot-map/blob/main/benchmark/benchmark/core/config.py) within the `_load_yaml` function, which uses `yaml.safe_load` to parse files and merges them with global defaults from [`benchmark/configs/base.yaml`](https://github.com/Robbyant/lingbot-map/blob/main/benchmark/configs/base.yaml).

### What are the required fields for each camera frame in the preset?

Each frame entry must include `position` as a 3-element list `[x, y, z]` and `orientation` as a 4-element quaternion `[qw, qx, qy, qz]`. While the schema documentation mentions Euler angles as an alternative, the quaternion format is the primary supported standard for rotation representation.

### How do I execute the offline renderer with my custom camera path?

Pass the path to your YAML file using the `--preset` argument when running either [`demo_render/rgbd_scan_render.py`](https://github.com/Robbyant/lingbot-map/blob/main/demo_render/rgbd_scan_render.py) or [`demo_render/batch_demo.py`](https://github.com/Robbyant/lingbot-map/blob/main/demo_render/batch_demo.py), along with your model path and image folder.

### Can the renderer interpolate between sparse keyframes?

Yes, set `interpolate: true` in your preset file and specify the desired frame density using the `--keyframe_interval` command-line flag to automatically generate intermediate frames between your defined timestamps.