Python

Python Bindings: Python Bindings

The Python interface is a convenient way to run the odometry on pre-recorded data.

Setup

Install from PyPI

pip install rko_lio

Wheels are published for Linux, macOS, and Windows (PyPI page).

To use any of the dataloaders or visualization, install the matching extras. You’ll be prompted at runtime if a required package is missing. For example, to use the rosbag dataloader and visualize the results:

pip install rko_lio rosbags rerun-sdk

Or install everything at once:

pip install "rko_lio[all]"

Build from source

Clone the repository and:

pip install .

For all optional dependencies:

pip install ".[all]"

Or use the convenience recipes in the Makefile:

make install    # installs all optional deps
make editable   # installs an editable version with all deps

The Python build uses scikit-build-core. You only need Python >= 3.10 and pip (or another frontend). Core C++ dependencies (Eigen, Sophus, TBB, nlohmann_json) are fetched automatically; Bonxai is always fetched. If you want to build against system libraries instead, set RKO_LIO_FETCH_CONTENT_DEPS=OFF via the scikit-build CMake args – the default for the Python build is ON.

Usage

For all CLI flags:

rko_lio --help

The most common invocation is just:

rko_lio /path/to/data

Add -v to enable visualization (uses rerun; install the rerun-sdk extra).

There are three dataloaders: rosbag (ROS1 or ROS2), raw, and HeLiPR (deprecated). The system tries to detect the right one from the data path; choose explicitly with -d.

A config file is passed with --config / -c. Dump a default config to inspect or edit:

rko_lio --dump_config

Extrinsics are specified in the config under these keys:

extrinsic_imu2base_quat_xyzw_xyz:   [0.0, 0.0, 0.0, 1.0,  0.0, 0.0, 0.0]
extrinsic_lidar2base_quat_xyzw_xyz: [0.0, 0.0, 0.0, 1.0,  0.1, 0.0, 0.05]

Both keys are required, unless the dataloader can supply the extrinsics itself (e.g. the rosbag dataloader can pull them from a static TF tree in the bag). The format is [qx, qy, qz, qw, x, y, z], with the convention described under Extrinsics & convention.

Warning

If the dataloader provides extrinsics but you specify them in the config, the config values take priority.

If your platform starts at rest, set initialization_phase: true in the LIO config. The system uses the IMU between the first two scans to initialise roll / pitch and IMU biases, which makes a noticeable difference – especially when starting on an inclined surface.

For the full list of LIO and pipeline parameters, see Configuring the odometry. For data assumptions (units, conventions, timestamps), see The sensor data.

Dataloaders

Rosbag Dataloader

The rosbag dataloader works with both ROS1 and ROS2 bags. Place split ROS1 bags together in a single folder and use that folder as the data path. ROS2 bags especially require a metadata.yaml file.

Note

It is not supported to run RKO LIO on partial or incomplete bags, though you may try and are encouraged to raise an issue if you require this supported.

There are certain reasonable defaults:

  • The bag contains one IMU topic and one LiDAR topic (otherwise specify with --imu or --lidar flags).

  • A static TF tree is in the bag. We build a static TF tree from topic frame ids and query it for extrinsic between IMU and LiDAR.

    The odometry estimates the robot pose with respect to a base frame, by default assumed to be the LiDAR frame unless you override this with --base_frame. The TF tree is queried for the necessary transformations.

If there is no TF tree, you must supply extrinsics for IMU-to-base and LiDAR-to-base. Set one transformation to identity if you want that frame to be the reference, but both must be given.

Message header frame IDs must match the TF tree frame names. If they do not, override with --lidar_frame or --imu_frame.

# The config should provide extrinsics if they can't be inferred
rko_lio -v -c config.yaml --imu imu_topic --lidar lidar_topic /path/to/rosbag_folder

Raw Dataloader

When using the raw dataloader, arrange your dataset directory as follows:

dataset_root/
├── transforms.yaml                 # required: contains 4x4 matrices
├── imu.csv / imu.txt               # must match required columns
└── lidar/                          # folder of point clouds
    ├── 1662622237000000000.ply
    ├── 1662622238000000000.ply
    └── ...
  • transforms.yaml: defines two keys (T_imu_to_base, T_lidar_to_base), each a 4x4 matrix. See Extrinsics and conventions.

  • IMU file: Only one file (CSV or TXT) is allowed. Required columns: timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z. Extra columns are allowed. timestamp in nanoseconds, others in SI units.

  • lidar/: contains scans as PLY files. Each filename is a timestamp (ns) for the scan. Each PLY file must have a time field (accepted names: time, timestamp, timestamps, or t) in seconds.

Note the unit difference: filenames are in nanoseconds, the per-point time field inside each PLY is in seconds. This is intentional (filenames are easier to sort as integers) but easy to get wrong.

HeLiPR Dataloader

This loader is deprecated and will be removed in a future release. If you need it supported, please open an issue.

Python API

The full module-level API reference is auto-generated: see python.