Skip to main content

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

Project description

kitti2mcap

PyPI Python License: MIT

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

Available on PyPI:

# as a standalone CLI tool (recommended)
uv tool install kitti2mcap     # or: pipx install kitti2mcap

# or into the current environment
pip install kitti2mcap

You can also run it without installing:

uvx kitti2mcap --help

From source

Uses uv:

git clone https://github.com/AdityaSrinivasManohar/kitti2mcap
cd kitti2mcap
uv sync

This 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

kitti2mcap --date 2011_09_26 --drive 0001 --kitti-dir ./data --output out.mcap

(From a source checkout, prefix with uv run, e.g. uv run kitti2mcap ....)

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
kitti2mcap --date 2011_09_26 --drive 0001 --kitti-dir ./data --output test.mcap --frames 5

# Both grayscale + color left cameras, no IMU
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: 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.1.tar.gz (12.0 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.1-py3-none-any.whl (16.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: kitti2mcap-0.1.1.tar.gz
  • Upload date:
  • Size: 12.0 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.1.tar.gz
Algorithm Hash digest
SHA256 3c640950dfb338505d4fa1ca8a3436bfcb9578e92db3d0fc34ea068873115cac
MD5 f71a02edbb7698b2a40c3f292a950b65
BLAKE2b-256 3895e71245b46ebd82697540324bb20974b76ea7bb4cbccf63cb6d772c1afe1a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kitti2mcap-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 16.3 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b8898849e41e34f57e2fff33c6d73c2eb68801c3d2b72ca3dd3a936efa93f495
MD5 e5aacb37fdfff30bb7bd2535526ad87f
BLAKE2b-256 02295d1b06e5786105996d21eec24792c23ccc396013e84951d6e994a288c3c4

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