Dataset Format

What's inside every SIMaaS dataset and how to use it.

R2 directory structure

Every run uploads to R2 under jobs/<job_id>/. The tree includes per-vehicle sensor data, ground-truth metadata, and scenario snapshots.

jobs/<job_id>/ ├── vehicle_0/ (one per ego vehicle) │ ├── rgb/ │ │ ├── 000001.bin (BGRA raw frames) │ │ ├── 000002.bin │ │ └── ... │ ├── depth/ │ │ ├── 000001.bin │ │ └── ... │ ├── semantic/ (class ID segmentation) │ ├── lidar/ (3D point clouds) │ │ ├── 000001.bin │ │ └── ... │ ├── radar.csv (detections per frame) │ ├── imu.csv (inertial sensors) │ ├── gnss.csv (GPS fixes) │ ├── collision.csv (event log) │ ├── lane_invasion.csv (event log) │ └── obstacle.csv (event log) ├── actors.csv (ground-truth per tick) ├── _landmarks.json (OpenDRIVE landmarks) ├── scenario.yaml (input config snapshot) ├── carla_recorder.log (CARLA replay log) ├── _meta/ │ └── summary.json (run metadata) └── cameras/ (demo-reel only) └── <camera_name>/ ├── video.mp4 └── frames/

Frame numbering: Binary files are zero-padded to 6 digits (e.g., 000042.bin). Frame is the primary key across all sensors — all sensors reporting frame N are synchronised to the same simulation tick.

CSV sensor schemas

actors.csv

Ground-truth per-tick actor manifest. One row per actor per frame.

ColumnUnit / TypeDescription
frameintegerCARLA frame number
timestampsecondsSimulation time since world init
actor_idintegerUnique CARLA actor ID
type_idstringActor type (vehicle.car, walker.pedestrian, etc.)
rolestringActor role (ego, npc, pedestrian)
vehicle_indexintegerWhich ego vehicle (0, 1, …)
x, y, zmetersWorld position
pitch, yaw, rolldegreesRotation in world frame
vx, vy, vzm/sVelocity in world frame
wx, wy, wzrad/sAngular velocity
bbox_ext_x, _y, _zmetersBounding box extent (half-width)
Sample row:
1,0.05,103,vehicle.tesla.model3,ego,0,456.2,789.1,0.5,5.2,180.0,0.0,12.3,0.0,0.0,0.1,0.0,0.0,0.9,1.8,1.45

radar.csv

Automotive radar detections. Multiple rows per frame (one per detection); empty frames have zero rows.

ColumnUnit / TypeDescription
frameintegerCARLA frame number
timestampsecondsSimulation time
azimuthradiansBearing angle to detection
altituderadiansElevation angle to detection
depthmetersRadial range to detection
velocitym/sRadial velocity (+ = approaching)
Sample rows:
42,2.1,0.15,-0.05,45.2,5.8
42,2.1,0.22,0.03,62.1,-3.2

imu.csv & gnss.csv

IMU: Inertial measurement unit (acceleration, angular velocity, compass). ~20 rows/sec (one per frame).

frame,timestamp,ax,ay,az,gx,gy,gz,compass
1,0.05,0.2,0.1,9.81,0.01,-0.02,0.0,3.14159

GNSS: Simulated GPS (latitude, longitude, altitude). ~20 rows/sec. Coordinates are CARLA synthetic, not real-world.

frame,timestamp,latitude,longitude,altitude
1,0.05,52.1,0.5,10.2

Metadata files

_landmarks.json

OpenDRIVE landmarks (traffic lights, stop signs, speed limits). Exported from the map at run start.

{ "map": "Town01", "landmarks": [ { "id": "1_landmark_123", "type": "1001", "name": "stop", "x": 456.2, "y": 789.1, "z": 0.0, "yaw": 0.0 }, { "id": "1_landmark_124", "type": "1000", "name": "traffic_light", "x": 500.0, "y": 800.0, "z": 3.0, "yaw": 1.57 } ] }

_meta/summary.json

Single-line run summary with exit code, frame counts, and cost estimate.

{ "job_id": "job_abc123def", "status": "complete", "frames": 400, "bytes": 5242880000, "wallclock_seconds": 1234, "cost_estimate_gbp": 0.34, "exit_code": 0, "schema_version": 1 }

Binary sensors (RGB, depth, lidar)

Raw CARLA byte buffers without re-encoding. One file per frame.

  • RGB: 800×600 BGRA, 4 bytes/pixel.
    np.frombuffer(b, dtype=np.uint8).reshape(600, 800, 4)
  • Depth: 800×600 BGRA-encoded depth in meters.
    depth_m = (R + G×256 + B×65536) / (256³ - 1) × 1000.0
  • Lidar: Float32 quartets (x, y, z, intensity).
    np.frombuffer(b, dtype=np.float32).reshape(-1, 4)

Key notes

  • Synchronisation: All sensors align by frame number (primary key). Join on frame to align across modalities.
  • Frame rate: 20 Hz fixed. Each tick = 50 ms.
  • Reproducibility: Same scenario + seed + CARLA version = identical sensor output.
  • IMU note: Frame 1 contains spawn noise. Skip frames 1–2 or filter on |ax| < 100 during analysis.