Skip to main content

Convert KITTI raw drives to self-contained ROS2 MCAP files (no ROS install required)

Project description

kitti2mcap

Convert a KITTI raw drive into a single, self-contained ROS2 MCAP file — no ROS installation required.

The output carries all the standard sensor topics (camera, LiDAR, IMU, TF) and embeds every ROS2 message schema inline, so it opens directly in any MCAP-based tool — Foxglove, the mcap CLI, and most calibration/visualization pipelines — without a sourced ROS workspace.


Install

Uses uv:

uv sync

This creates a virtual environment and installs the pinned dependencies from pyproject.toml: pykitti, mcap, mcap-ros2-support, numpy, Pillow, and opencv-python-headless (pulled in by pykitti's package import).


Usage

uv run kitti2mcap --date 2011_09_26 --drive 0001 --kitti-dir ./data --output out.mcap
Flag Description
--date KITTI date folder (e.g. 2011_09_26)
--drive Drive sequence number (e.g. 0001)
--kitti-dir Root directory containing the date folder
--output Output .mcap path
--frames Number of frames to convert (default: all)
--cameras Cameras to include, e.g. 0,1 (default: 2 — left color)
--no-lidar Skip velodyne data
--no-imu Skip IMU/OXTS data

Examples

# First 5 frames only, quick smoke test
uv run kitti2mcap --date 2011_09_26 --drive 0001 --kitti-dir ./data --output test.mcap --frames 5

# Both grayscale + color left cameras, no IMU
uv run kitti2mcap --date 2011_09_26 --drive 0001 --kitti-dir ./data --output out.mcap --cameras 0,2 --no-imu

You can also run it as a module: uv run python -m kitti2mcap ....

Camera indices

Index Frame Topic basename Encoding
0 camera_gray_left camera_gray_left mono8
1 camera_gray_right camera_gray_right mono8
2 camera_color_left camera_color_left rgb8
3 camera_color_right camera_color_right rgb8

Expected input layout

--kitti-dir must follow pykitti's canonical layout — calibration files live inside the date folder, alongside the drive:

<kitti-dir>/
└── 2011_09_26/
    ├── calib_cam_to_cam.txt
    ├── calib_imu_to_velo.txt
    ├── calib_velo_to_cam.txt
    └── 2011_09_26_drive_0001_sync/
        ├── image_00/  image_01/  image_02/  image_03/
        ├── oxts/
        └── velodyne_points/

Downloading a drive + its calibration from the KITTI raw archive and unzipping both into the same directory produces exactly this structure.


Topics written

Topic Type Notes
/kitti/camera_color_left/image_raw sensor_msgs/Image Camera 2 (left color), rgb8. Other cameras via --cameras
/kitti/camera_color_left/camera_info sensor_msgs/CameraInfo Rectified intrinsics (P_rect / R_rect / K)
/kitti/velodyne_points sensor_msgs/PointCloud2 x, y, z, intensity (float32)
/tf_static tf2_msgs/TFMessage Sensor extrinsics, latched
/tf tf2_msgs/TFMessage Ego pose map → base_link from OXTS (optional)
/kitti/imu sensor_msgs/Imu Orientation, angular velocity, linear acceleration (optional)

Transform tree

map ──(/tf, per frame)──▶ base_link ──(/tf_static)──┬──▶ velodyne
                                                     └──▶ camera_*

base_link is coincident with the OXTS/IMU unit. Static extrinsics are expressed relative to base_link so the dynamic ego pose has a single, conflict-free child to drive — a valid single-parent tree.


How it works

  • No ROS dependency. pykitti reads the data; mcap + mcap-ros2-support write the file. All ROS2 message schemas are emitted from inline .msg definitions (ros2_defs.py), so the MCAP is fully self-describing.
  • Schemas registered up front, so the file is readable without a ROS environment.
  • Lazy, prefix frame loading — one frame at a time, so long drives don't exhaust RAM.
  • Faithful timestamps. Each sensor's timestamps.txt is parsed directly to nanosecond precision (pykitti truncates to microseconds), so per-sensor timing and playback rate are preserved.
  • Rectified camera model. KITTI sync images are already rectified, so CameraInfo uses P_rect/R_rect/K with zero distortion.
  • /tf_static latched at the first frame's timestamp so the transform tree is available immediately on load.

Project structure

kitti2mcap/
├── cli.py            # CLI entrypoint, arg parsing, orchestration
├── reader.py         # Wraps pykitti; per-sensor nanosecond timestamps
├── calibration.py    # pykitti calib → CameraInfo + static transform tree
├── ros2_defs.py      # Concatenated ROS2 .msg schema text (self-contained)
├── mcap_writer.py    # Wraps mcap-ros2-support; schema registration + writing
└── writers/
    ├── image.py      # PIL image → sensor_msgs/Image
    ├── pointcloud.py # velodyne .bin → sensor_msgs/PointCloud2
    ├── imu.py        # OXTS packet → sensor_msgs/Imu
    └── tf.py         # quaternion/transform helpers, TFMessage builders

Inspecting the output

With the mcap CLI:

mcap info out.mcap
mcap doctor out.mcap

Or trim a slice for a quick test:

mcap filter out.mcap tiny.mcap --start-secs 0 --end-secs 1

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kitti2mcap-0.1.0.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kitti2mcap-0.1.0-py3-none-any.whl (16.1 kB view details)

Uploaded Python 3

File details

Details for the file kitti2mcap-0.1.0.tar.gz.

File metadata

  • Download URL: kitti2mcap-0.1.0.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for kitti2mcap-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a2f509303e847f54c7410f35b8ffeacc6f8ba587a3a448de937373160fe7a28f
MD5 e67dc74b0869727d32fc21bafc370e74
BLAKE2b-256 b8b8adf423f5f072db5fda027c79436ddf62102b1d09584221b8c9947656d962

See more details on using hashes here.

File details

Details for the file kitti2mcap-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: kitti2mcap-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for kitti2mcap-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b6b23324bf4e3784b895665c38cbda80ec1fc00ed0bf19f1989f817793753f65
MD5 9023609d2175ba2d1e7b8a7a48e4196f
BLAKE2b-256 45613b3ad046047771ad47c8a4164ffe45e60bbf74971fbb81ea422555612d24

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page