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: .. code-block:: python # 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: .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python 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 :doc:`api/scene` reference pages.