Multiple cameras

Each world starts off with a single camera, but if you need to generate a collection with synchronized views of the same scene in a single render, you can add more cameras to the world.

Satellite worlds do not support multiple cameras.

Terminology

  • Default camera: the camera every world starts with. Its id is "camera".

  • Earliest inserted camera: what world.camera refers to. This is the default camera until you remove it.

  • Active camera: the camera the live viewport looks through. It affects only the editor view, never the render.

world.camera is not the active camera. Switching the viewport to another camera does not change what world.camera references.

Add cameras

Add cameras with world.add_camera. Each camera needs a unique ID and starts with the world’s default camera transform, field of view, resolution, and sensor preset.

Adding cameras
world.add_camera("port", exist_ok=True)
world.add_camera("starboard", exist_ok=True)

Access any camera by its ID through world.cameras, which lists cameras in insertion order.

Accessing cameras
# dictionary of cameras by ID in insertion order
world.cameras

# access a camera's properties
world.cameras["starboard"].fov

Attention

A world holds at most five cameras.

Camera IDs may contain letters, digits, hyphens, and underscores.

Remove cameras

Use world.remove_camera to remove a camera. If the camera ID does not exist, it emits a warning instead of raising an error.

world.camera (singular) always refers to the earliest inserted camera still in the world. If the default camera is removed, world.camera resolves to the earliest camera added.

Tip

Every world starts with a single camera with ID "camera". If you do not want the default camera in your dataset, remove it explicitly:

world.remove_camera("camera")

Attention

A world must have at least one camera. Attempting to remove the last camera will raise an error.

Switch the viewport camera

The live viewport looks through one camera at a time, called the active camera. Switch between cameras with the camera dropdown in the editor, or via world.set_active_camera.

Switching the viewport camera via code
world.set_active_camera("starboard")

A sync dot next to the dropdown shows whether the viewport still matches the camera’s set pose. Switching the viewport is purely visual. It does not change which camera world.camera refers to, and it has no effect on the properties of the camera.

Configure cameras independently

Each camera carries its own transform (position + rotation), field of view, resolution, preset and post processing settings. Set them per camera, exactly as you would for a single camera.

A wide establishing shot and a tight zoom
wide = world.cameras["port"]
wide.set_position(Vector3(-40, 0, 15))
wide.set_fov(90)

zoom = world.cameras["starboard"]
zoom.set_position(Vector3(-12, 5, 3))
zoom.set_fov(20)
zoom.set_resolution((1920, 1080))

Animate cameras in a scenario

You can keyframe the properties of each camera independently.

Fly one camera while the other holds steady
scenario = world.new_scenario(num_frames=100)

for i in range(scenario.num_frames):
    scenario.set_keyframe(
        instance=world.cameras["port"],
        frame_id=i,
        position=Vector3(i, 0, 10),
    )

Render

By default, scenario.render() renders every camera in the world. To render only a subset, pass a list of camera IDs to the cameras parameter.

Rendering all cameras, or just one
scenario.render() # renders all cameras
scenario.render(cameras=["port", "starboard"]) # renders only the port and starboard cameras

Each image in the COCO annotation file records the camera that captured it in the bifrost_camera_id field. See Bifrost metadata.

Attention

All cameras in a single render share the same output type. To capture RGB from one camera and thermal from another, run a separate render for each.

Render time

Each additional camera adds roughly 40% to render time, scaling linearly from the single-camera baseline. A five-camera render takes about 2.6x as long as a one-camera render. (1 → 1.4 → 1.8 → 2.2 → 2.6)