Examples¶
This page contains complete examples demonstrating the MIMIC Data API.
Creating a Complete Scene¶
This example shows how to create a scene with cameras, LiDAR, radar, and actors:
# Creating a scene with a camera and an actor
from mimic_data_api import (
Camera,
CameraIntrinsics,
DistortionParameters,
RollingShutterParameters,
ImageData,
Actor,
ActorDimensions,
Scene,
EgoVehicle,
Sensors,
WorldTrajectory,
Radar,
RadarIntrinsics,
RadarPointCloudData,
Lidar,
LidarIntrinsics,
LidarPointCloudData,
VerticalResolution,
)
import numpy as np
from pathlib import Path
# Define timestamps and trajectory
timestamps = np.array([0.0, 1.0, 2.0])
poses = np.array(3 * np.eye(4).tolist()).reshape(3, 4, 4)
ego_trajectory = WorldTrajectory(
timestamps=timestamps,
object2world=poses,
)
# Create image data entries
images = [
ImageData(
filepath=f"camera/{i:08d}.png",
timestamp=float(i),
undistorded=True,
rolling_shutter=RollingShutterParameters()
)
for i in range(3)
]
# Create a camera
camera = Camera(
id=1,
name="Front Camera",
camera_model="pinhole",
intrinsics=CameraIntrinsics(
fx=1000.0,
fy=1000.0,
cx=640.0,
cy=360.0,
skew=0.0,
height=720.0,
width=1280.0,
),
distortion_parameters=DistortionParameters(),
trajectory=WorldTrajectory(
timestamps=timestamps,
object2world=poses,
),
images_data=images,
extrinsics=np.eye(4),
)
# Create LiDAR point cloud data entries
lidar_pcds = [
LidarPointCloudData(
filepath=f"lidar/{i:08d}.ply",
timestamp=float(i),
egomotion_compensated=True,
has_missing_points=False
)
for i in range(3)
]
# Create a LiDAR sensor
lidar = Lidar(
id=1,
name="top_lidar",
extrinsics=np.eye(4),
intrinsics=LidarIntrinsics(
vertical_fov=np.pi / 4, # 45 degrees
horizontal_fov=2 * np.pi, # 360 degrees
horizontal_resolution=0.01,
vertical_resolution=VerticalResolution(vertical_resolution=0.01),
max_range=100.0,
min_range=0.1,
rotation_type="clockwise",
lidar_type="rotating"
),
trajectory=WorldTrajectory(
timestamps=timestamps,
object2world=poses,
),
lidar_pcds_data=lidar_pcds,
min_cut_off_range=1.5
)
# Create radar point cloud data entries
radar_pcds = [
RadarPointCloudData(
filepath=f"radar/{i:08d}.ply",
timestamp=float(i)
)
for i in range(3)
]
# Create a radar sensor
radar = Radar(
id=1,
name="front_radar",
extrinsics=np.eye(4),
intrinsics=RadarIntrinsics(
range=200,
azimuth_fov=np.pi / 3, # 60 degrees
elevation_fov=np.pi / 6, # 30 degrees
azimuth_resolution=[(0.0, 0.01), (np.pi / 6, 0.02)],
elevation_resolution=None,
min_speed_resolution=-50.0,
max_speed_resolution=50.0,
),
trajectory=WorldTrajectory(
timestamps=timestamps,
object2world=poses,
),
radar_pcds_data=radar_pcds,
)
# Create an actor (vehicle)
actor = Actor(
id=1,
name="Vehicle_001",
dimensions=ActorDimensions(length=4.5, width=2.0, height=1.5),
boxtype="vehicle",
original_boxtype="sedan",
dynamic=True,
trajectory=WorldTrajectory(
timestamps=timestamps,
object2world=poses,
),
description="A sedan traveling in the adjacent lane"
)
# Assemble the scene
sensors = Sensors(
cameras=[camera],
lidars=[lidar],
radars=[radar]
)
scene = Scene(
ego_vehicle=EgoVehicle(
trajectory=ego_trajectory,
sensors=sensors,
),
actors=[actor],
)
# Export to JSON
with open("scene.json", "w") as f:
f.write(scene.model_dump_json(indent=2))
print("Scene created and saved to scene.json")
Loading and Inspecting a Scene¶
Load an existing scene and inspect its contents:
from mimic_data_api import Scene
from pathlib import Path
# Load scene from JSON
scene_json = Path("scene.json").read_text()
scene = Scene.model_validate_json(scene_json)
# Inspect ego vehicle
ego = scene.ego_vehicle
print(f"Ego trajectory: {len(ego.trajectory.timestamps)} frames")
print(f"Duration: {ego.trajectory.timestamps[-1] - ego.trajectory.timestamps[0]:.1f} seconds")
# List sensors
print(f"\nCameras: {len(ego.sensors.cameras)}")
for cam in ego.sensors.cameras:
print(f" - {cam.name}: {cam.camera_model}, {cam.intrinsics.width}x{cam.intrinsics.height}")
if ego.sensors.lidars:
print(f"\nLiDARs: {len(ego.sensors.lidars)}")
for lidar in ego.sensors.lidars:
print(f" - {lidar.name}: {lidar.intrinsics.lidar_type}, range={lidar.intrinsics.max_range}m")
if ego.sensors.radars:
print(f"\nRadars: {len(ego.sensors.radars)}")
for radar in ego.sensors.radars:
print(f" - {radar.name}: range={radar.intrinsics.range}m")
# List actors
print(f"\nActors: {len(scene.actors)}")
for actor in scene.actors:
status = "dynamic" if actor.dynamic else "static"
print(f" - [{actor.id}] {actor.name}: {actor.boxtype} ({status})")
print(f" Dimensions: {actor.dimensions.length}m x {actor.dimensions.width}m x {actor.dimensions.height}m")
Working with Camera Intrinsics¶
Project 3D points to image coordinates:
import numpy as np
from mimic_data_api import Camera, CameraIntrinsics
# Get intrinsic matrix
intrinsics = CameraIntrinsics(
fx=1000, fy=1000,
cx=640, cy=360,
skew=0,
width=1280, height=720
)
K = intrinsics.as_K()
# 3D point in camera coordinates
point_3d = np.array([1.0, 0.5, 5.0]) # x=1m right, y=0.5m down, z=5m forward
# Project to 2D (homogeneous coordinates)
point_2d_h = K @ point_3d
point_2d = point_2d_h[:2] / point_2d_h[2]
print(f"3D point: {point_3d}")
print(f"2D projection: ({point_2d[0]:.1f}, {point_2d[1]:.1f}) pixels")
Transforming Points Between Frames¶
Transform points between sensor, vehicle, and world frames:
import numpy as np
# Example: Point in LiDAR sensor frame
point_sensor = np.array([10.0, 2.0, 0.5, 1.0]) # Homogeneous coordinates
# Sensor to vehicle transform (extrinsics)
# Example: LiDAR mounted 1.5m above vehicle origin
T_sensor_to_vehicle = np.array([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 1.5],
[0, 0, 0, 1]
], dtype=np.float64)
# Vehicle to world transform (from trajectory)
# Example: Vehicle at position (100, 50, 0) with 45° yaw
angle = np.pi / 4
T_vehicle_to_world = np.array([
[np.cos(angle), -np.sin(angle), 0, 100],
[np.sin(angle), np.cos(angle), 0, 50],
[0, 0, 1, 0],
[0, 0, 0, 1]
], dtype=np.float64)
# Transform point to vehicle frame
point_vehicle = T_sensor_to_vehicle @ point_sensor
print(f"Point in vehicle frame: {point_vehicle[:3]}")
# Transform point to world frame
point_world = T_vehicle_to_world @ point_vehicle
print(f"Point in world frame: {point_world[:3]}")
# Or compose transforms first
T_sensor_to_world = T_vehicle_to_world @ T_sensor_to_vehicle
point_world_direct = T_sensor_to_world @ point_sensor
print(f"Point in world frame (direct): {point_world_direct[:3]}")
Filtering Dynamic Actors¶
Find and analyze dynamic actors:
from mimic_data_api import Scene
import numpy as np
# Load scene
scene = Scene.model_validate_json(open("scene.json").read())
# Get only dynamic actors
dynamic_actors = [a for a in scene.actors if a.dynamic]
print(f"Found {len(dynamic_actors)} dynamic actors")
for actor in dynamic_actors:
# Calculate approximate speed from trajectory
positions = actor.trajectory.object2world[:, :3, 3] # Extract translations
timestamps = actor.trajectory.timestamps
if len(timestamps) > 1:
distances = np.linalg.norm(np.diff(positions, axis=0), axis=1)
dt = np.diff(timestamps)
speeds = distances / dt
avg_speed = np.mean(speeds)
print(f"\n{actor.name} ({actor.boxtype}):")
print(f" Average speed: {avg_speed:.1f} m/s ({avg_speed * 3.6:.1f} km/h)")
print(f" Track length: {np.sum(distances):.1f} m")
Multi-Camera Setup¶
Create a surround-view camera configuration:
import numpy as np
from mimic_data_api import (
Camera, CameraIntrinsics, DistortionParameters,
ImageData, WorldTrajectory, Sensors, EgoVehicle, Scene
)
def create_camera(name: str, yaw_deg: float, trajectory: WorldTrajectory) -> Camera:
"""Create a camera with given orientation."""
yaw = np.radians(yaw_deg)
# Rotation matrix (yaw only)
R = np.array([
[np.cos(yaw), -np.sin(yaw), 0],
[np.sin(yaw), np.cos(yaw), 0],
[0, 0, 1]
])
# Extrinsics: camera mounted at vehicle center, different orientations
extrinsics = np.eye(4)
extrinsics[:3, :3] = R
# Create image data for each timestamp
images = [
ImageData(
filepath=f"{name.lower()}/{i:08d}.png",
timestamp=t,
undistorded=True
)
for i, t in enumerate(trajectory.timestamps)
]
return Camera(
id=hash(name) % 1000,
name=name,
camera_model="pinhole",
intrinsics=CameraIntrinsics(
fx=800, fy=800, cx=640, cy=360,
skew=0, width=1280, height=720
),
distortion_parameters=DistortionParameters(),
extrinsics=extrinsics,
trajectory=trajectory,
images_data=images
)
# Create trajectory
n_frames = 100
trajectory = WorldTrajectory(
timestamps=np.linspace(0, 10, n_frames),
object2world=np.stack([np.eye(4)] * n_frames)
)
# Create surround-view cameras
cameras = [
create_camera("FRONT", 0, trajectory),
create_camera("FRONT_LEFT", 45, trajectory),
create_camera("FRONT_RIGHT", -45, trajectory),
create_camera("REAR", 180, trajectory),
create_camera("REAR_LEFT", 135, trajectory),
create_camera("REAR_RIGHT", -135, trajectory),
]
# Create scene
scene = Scene(
ego_vehicle=EgoVehicle(
trajectory=trajectory,
sensors=Sensors(cameras=cameras)
),
actors=[]
)
print(f"Created scene with {len(cameras)} cameras:")
for cam in cameras:
print(f" - {cam.name}")
Round-Trip Validation¶
Verify that serialization preserves data:
from copy import deepcopy
from mimic_data_api import Scene, Camera
# Load or create scene
scene = Scene.model_validate_json(open("scene.json").read())
# Make a deep copy
scene_copy = deepcopy(scene)
# Serialize and deserialize
json_str = scene.model_dump_json(indent=2)
scene_roundtrip = Scene.model_validate_json(json_str)
# Verify cameras match
for orig_cam, rt_cam in zip(
scene.ego_vehicle.sensors.cameras,
scene_roundtrip.ego_vehicle.sensors.cameras
):
assert orig_cam == rt_cam, f"Camera {orig_cam.name} mismatch!"
# Verify actors match
for orig_actor, rt_actor in zip(scene.actors, scene_roundtrip.actors):
assert orig_actor.id == rt_actor.id
assert orig_actor.boxtype == rt_actor.boxtype
print("Round-trip validation successful!")
Note
For more detailed API documentation, see the Scene Module reference pages.