# How to Configure Camera Intrinsic Parameters for Depth Rendering in Peng

> Configure camera intrinsic parameters for depth rendering in Peng by setting resolution, FOV, and near/far planes in quad.yaml. Peng automatically derives focal lengths.

- Repository: [Yang Zhou/peng](https://github.com/makeecat/peng)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Configure camera intrinsic parameters for depth rendering in Peng by editing the `camera` section in [`config/quad.yaml`](https://github.com/makeecat/peng/blob/main/config/quad.yaml) to set resolution, vertical FOV, near/far planes, and rotation transform, while Peng automatically derives horizontal focal lengths and FOV from these values.**

To configure camera intrinsic parameters for depth rendering in Peng, you modify the YAML configuration file that defines the pin-hole camera model used for simulation. The Peng repository (`makeecat/peng`) implements a `CameraConfig` struct in [`src/config.rs`](https://github.com/makeecat/peng/blob/main/src/config.rs) that deserializes these settings and passes them to the rendering pipeline.

## Understanding Camera Intrinsics in Peng

Peng simulates depth perception using a **pin-hole camera model** attached to the quadrotor. The intrinsic parameters define how 3D world points project onto the 2D image plane. These settings are stored in the `CameraConfig` struct defined in [`src/config.rs`](https://github.com/makeecat/peng/blob/main/src/config.rs), which is populated from the YAML configuration file at runtime.

The intrinsics split into two categories:

- **User-specified values**: Resolution, vertical field of view (FOV), near/far clipping planes, and the camera-to-quad rotation matrix.
- **Derived values**: Horizontal FOV and focal lengths, computed automatically by the `Camera::new` constructor in [`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs).

## Configuring Intrinsics via YAML

All camera configuration happens in [`config/quad.yaml`](https://github.com/makeecat/peng/blob/main/config/quad.yaml). The `camera` block contains the fields that control depth rendering behavior.

### Resolution and Field of View

The `resolution` field sets the output image dimensions as `[width, height]`. The `fov_vertical` field specifies the vertical field of view in degrees. Peng uses these to calculate the aspect ratio and derive the horizontal FOV.

```yaml
camera:
  resolution: [640, 480]
  fov_vertical: 70

```

### Clipping Planes (Near and Far)

The `near` and `far` parameters define the depth range. Rays hitting surfaces closer than `near` or farther than `far` return infinity (no hit). These values are in meters.

```yaml
camera:
  near: 0.05
  far: 10.0

```

### Camera-to-Quad Rotation

The `rotation_transform` is a 3×3 row-major rotation matrix that aligns the camera frame with the quadrotor body frame. By default, the camera looks along the +Z axis; this matrix rotates rays to match the quad's orientation (typically looking forward along +X).

```yaml
camera:
  rotation_transform: [0.0, 0.0, 1.0,
                       -1.0, 0.0, 0.0,
                       0.0, -1.0, 0.0]

```

## How Peng Computes Derived Intrinsics

When you call `Camera::new` in [`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs), Peng automatically calculates the horizontal FOV and focal lengths from your YAML inputs. This ensures consistency between the resolution and field of view settings.

The calculation follows standard pin-hole camera geometry:

```rust
let (aspect_ratio, tan_half_fov) = (
    width as f32 / height as f32,
    (fov_vertical / 2.0).tan()
);
let fov_horizontal = (aspect_ratio * tan_half_fov).atan() * 2.0;
let horizontal_focal_length = (width as f32 / 2.0) / ((fov_horizontal / 2.0).tan());

```

The vertical focal length is computed similarly using the vertical FOV. These derived values are stored in the `Camera` struct and used when casting rays for depth rendering.

## Programmatic Access in Rust

You can inspect and verify the camera configuration programmatically by loading the config and instantiating the camera:

```rust
use peng_quad::{Config, Camera};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Load configuration from YAML
    let cfg = Config::from_yaml("config/quad.yaml")?;
    
    // Create camera with loaded intrinsics
    let cam = Camera::new(
        cfg.camera.resolution,
        cfg.camera.fov_vertical,
        cfg.camera.near,
        cfg.camera.far,
    );
    
    println!("Resolution: {:?}", cam.resolution);
    println!("Vertical FoV: {}°", cam.fov_vertical.to_degrees());
    println!("Horizontal FoV: {}°", cam.fov_horizontal.to_degrees());
    println!("Focal lengths: v={}, h={}", 
             cam.vertical_focal_length, 
             cam.horizontal_focal_length);
    
    Ok(())
}

```

This approach is useful for validating that your YAML changes produce the expected intrinsic parameters before running the full simulation.

## Summary

- **Configure camera intrinsic parameters for depth rendering in Peng** by modifying the `camera` block in [`config/quad.yaml`](https://github.com/makeecat/peng/blob/main/config/quad.yaml).
- Set `resolution`, `fov_vertical`, `near`, `far`, and `rotation_transform` to define the pin-hole camera model.
- Peng automatically derives horizontal FOV and focal lengths in `Camera::new` ([`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs)) based on the aspect ratio and vertical FOV.
- The `CameraConfig` struct in [`src/config.rs`](https://github.com/makeecat/peng/blob/main/src/config.rs) handles deserialization from YAML to Rust types.
- Use the `rotation_transform` matrix to align the camera frame with the quadrotor body frame for correct depth orientation.

## Frequently Asked Questions

### What file contains the CameraConfig struct definition?

The `CameraConfig` struct is defined in [`src/config.rs`](https://github.com/makeecat/peng/blob/main/src/config.rs). This file contains the Rust types that deserialize the `camera` section from the YAML configuration, including fields for resolution, vertical FOV, near/far planes, and the rotation transform matrix.

### How does Peng calculate the horizontal field of view?

Peng calculates the horizontal field of view automatically in the `Camera::new` method in [`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs). It first computes the aspect ratio from the resolution width and height, then uses trigonometric relationships: `fov_horizontal = 2.0 * atan(aspect_ratio * tan(fov_vertical / 2.0))`. This ensures the pixel aspect ratio matches the angular projection.

### Can I set the horizontal focal length directly?

No, you cannot set the horizontal focal length directly in the YAML configuration. Peng derives both horizontal and vertical focal lengths internally based on the resolution and vertical FOV you provide. If you need a specific horizontal focal length, you must calculate the required vertical FOV that produces that focal length given your resolution, then set that value in [`config/quad.yaml`](https://github.com/makeecat/peng/blob/main/config/quad.yaml).

### What is the purpose of the rotation_transform matrix?

The `rotation_transform` matrix aligns the camera's coordinate frame with the quadrotor's body frame. By default, the camera model assumes the optical axis points along the positive Z-axis. The 3×3 row-major rotation matrix rotates the camera rays so they point in the correct direction relative to the quad (typically forward along the positive X-axis). This transformation is applied in [`src/main.rs`](https://github.com/makeecat/peng/blob/main/src/main.rs) when calling `log_pinhole_depth`.