Model or dataset
PRBonn/rko_lio avatar
PRBonn/rko_lio

RKO-LIO: LiDAR-inertial odometry without a sensor model

A Robust Approach for LiDAR-Inertial Odometry Without Sensor-Specific Modelling

681 stars79 forksC++MIT

At a glance

What is it?
RKO-LIO is a C++ and Python LiDAR-inertial odometry system from the University of Bonn that ships as a pip package and as a ROS 2 package, and it deliberately avoids modelling a specific LiDAR. It suits robotics teams that want accurate odometry across mixed sensor platforms, and it does not replace a full SLAM system.
Who is it for?
Adopt RKO-LIO if you need accurate LiDAR-inertial odometry on hardware that changes between platforms, you can supply the IMU to LiDAR extrinsics, and you are willing to treat the system as odometry rather than a full SLAM stack. Do not adopt it expecting loop closures or drift correction, which the author points at the separate rko_slam project for, and do not rely on the ral_submission branch, which the README marks as unsupported.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Odometry that is not tied to one LiDAR vendor

RKO-LIO is described in its own title as an approach to LiDAR-inertial odometry without sensor-specific modelling, and the demonstration image in the README makes the point: four different platforms, four different environments, one odometry system. The topic tags cover lidar, imu, odometry, mapping, slam, ros, ros2 and robotics, and the homepage sits under the PRBonn GitHub Pages site.

The problem being solved is the classic one in applied robotics. A robot has a spinning LiDAR and an IMU, and it needs a continuous estimate of where it is. Almost every practical system needs to know something about the sensor: how the rotating beam maps to a range, how the scan is triggered, what the timing model is. That knowledge is where a lot of lidar-inertial odometry implementations get brittle, because the moment you swap hardware or change the mount, the assumptions break.

RKO-LIO's claim is that it does not need that. If the system can run on a vehicle, a handheld rig and a robot across four environments without per-sensor tuning, then a team deploying a fleet does not have to maintain a branch per sensor. The README's stated goal for the project is a simple LiDAR-inertial odometry system that works with minimal friction, and it names the goal in the phrase it just works.

The audience is robotics engineers and researchers who need an odometry front end they can trust across hardware, with the option of running it standalone on recorded data or as a node inside a ROS 2 system.

A C++ core with a Python and a ROS 2 front end

The repository layout explains the architecture better than a diagram would. The primary language is C++, and there is an rko_lio/ directory holding the implementation, a launch/ directory for ROS launch files, a config/ directory for configuration, cmake/ for CMake modules, tests/ for the test suite, and docs/ for the documentation site.

The Python distribution is a binding layer over that core rather than a reimplementation. The pyproject.toml declares scikit-build-core and pybind11 as build requirements, with scikit_build_core.build as the build backend, and it sets the CMake source directory to rko_lio/python/pybind. So the Python package compiles the C++ library and exposes it through pybind11.

The build configuration is explicit and adjustable. The CMake section sets a minimum version of 3.28, a Release build type, and defines RKO_LIO_FETCH_CONTENT_DEPS, RKO_LIO_BUILD_ROS and RKO_LIO_SCALAR, with the scalar set to double. RKO_LIO_BUILD_ROS being OFF by default is the switch that separates a plain Python install from a ROS build, and RKO_LIO_FETCH_CONTENT_DEPS controls whether dependencies are pulled in at build time.

The Python side itself is thin. The runtime dependencies are numpy, typer for the command line, pyyaml for configuration files, pyquaternion for rotations, and tqdm. The console script is declared as rko_lio = "rko_lio.cli:app", which means the entry point is a Typer application, and the optional extras add plyfile, rerun-sdk and rosbags, with the all extra pulling in the other optional dependencies as well.

First run: install with pip and point it at a rosbag

The quick start is written for someone with a bag file already on disk. The README assumes a rosbag, either ROS 1 or ROS 2, that contains a TF tree, and gives the install and run as one sequence:

bash
pip install "rko_lio[all]"
# or
pip install rko_lio rosbags "rerun-sdk>=0.31"
# data path should be a directory with *.bag files (ROS1) or a metadata.yaml (ROS2)
rko_lio -v /path/to/data

The three packages in the second line have separate jobs. rko_lio is the odometry package itself, rosbags is the dataloader that reads both ROS 1 and ROS 2 bags, and rerun-sdk is for the optional visualizer behind the -v flag. Installing the all extra fetches the other optional dependencies in one go, which is what most users want on a workstation.

What you should see on a first run is the visualisation. With -v the trajectory is drawn in the rerun viewer, and the whole point of the release is to see one odometry system working across different platforms and environments, which is the scenario the README illustrates.

Two command-line details are worth knowing before you get stuck. Further options are listed with rko_lio --help, and a default configuration can be dumped with rko_lio --dump_config, which gives you a file to edit and pass back with --config. That is the normal path when the dataloader cannot work out the sensor geometry by itself, which is the subject of the next section.

Extrinsics are the part that will cost you an afternoon

The README is direct about this: the system needs the extrinsic to be specified between the IMU and the LiDAR. Either the data carries that information in some format, in which case the dataloaders try to read it automatically, or you supply it in a config file, which the README says is required if it is missing from the data.

The config file is passed on the command line:

bash
rko_lio --config config_file.yaml

It needs exactly two keys, extrinsic_imu2base_quat_xyzw_xyz and extrinsic_lidar2base_quat_xyzw_xyz, each of which must be a list. The README gives the identity case as the example [0,0,0,1,0,0,0], which reads as a quaternion followed by a translation.

The naming convention is the other half of the difficulty. The author states that throughout the package transformations are referred to as transform_<from-frame>2<to-frame>, meaning a transformation that converts a vector expressed in the from-frame into the to-frame, and gives the matrix form for the relationship. Getting a transform backwards is the classic silent failure in this kind of system: nothing crashes, the trajectory just looks wrong.

For ROS users the README offers a mitigating note, pointing out that a well defined TF tree probably means you need not worry about this. The same note applies to the ROS path as to the Python path, which is the right way to read it: the friction is in the standalone case where the bag has no usable calibration.

ROS 2 across five distributions, with experimental topic autodetection

The ROS side is a first-class distribution path. Supported distros are Humble, Jazzy, Kilted, Lyrical and Rolling, and each has a version badge in the README. Installation is a binary package:

bash
sudo apt install ros-$ROS_DISTRO-rko-lio

Building from source in a colcon workspace is the alternative, and the README gives both the dependency resolution and the build:

bash
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select rko_lio  # --symlink-install --event-handlers console_direct+

If rosdep cannot supply the dependencies on your system, there is a second path that builds them during the RKO-LIO build itself, controlled by the same CMake define used in the Python build:

bash
colcon build --packages-select rko_lio --cmake-args -DRKO_LIO_FETCH_CONTENT_DEPS=ON

Running it is a launch file:

bash
ros2 launch rko_lio odometry.launch.py

The topics and frames are autodetected, and the README marks that behaviour as experimental. To set them yourself, autodetection is switched off and the three values you need are given on the command line:

bash
ros2 launch rko_lio odometry.launch.py autodetect:=false \
    imu_topic:=<topic> lidar_topic:=<topic> base_frame:=base_link

Everything else can be passed through a config file with config_file:=file.yaml, and the full set of launch options is listed with ros2 launch rko_lio odometry.launch.py -s. The experimental label on autodetection is the one caveat to carry into a deployment, because a wrong guess about which topic is the IMU produces a plausible-looking but wrong trajectory.

Odometry only, and the separate project that adds a SLAM back end

The README is explicit that this is not a complete SLAM system. The author writes that if you want a SLAM system with loop closures, a pose graph back end and drift correction, you should look at rko_slam, a separate repository. That boundary is worth keeping in view, because the word odometry and the word SLAM get used interchangeably in the field and they are not the same thing.

What RKO-LIO provides is the front end: a continuous, locally consistent trajectory from LiDAR and IMU data. Drift accumulates over a long run, and correcting it needs loop closures and pose graph optimisation, which live in the companion project. If your evaluation is a few minutes of accurate trajectory, this is the right layer. If it is a long mapping run in a building where you need loop closure, it is the wrong layer.

The repository also shows care about the parts that matter for a robotics codebase. There is a tests/ directory, and the Makefile has a core target that configures a CMake build without ROS, enables tests, and a core-test target that runs ctest with the output-on-failure option. A .clang-format and .clang-tidy configuration are present for C++ style and lint, a pre-commit configuration, a CHANGELOG.rst, and a renovate.json for dependency updates. The Makefile also has an install target that installs the package with all extras and an editable target for development.

The author also maintains the ral_submission branch, which holds the code used for the RA-L submission. The README says plainly that it is an as-is reproduction, is not supported, and that master and the release versions are the recommended way to use the system.

Release cadence, citation requirements and the MIT licence

The project is not archived and the last push was on 2026-10-18. The release tags move regularly: v0.3.1 on 2026-07-16, v0.3.2 on 2026-07-28, and v0.4.0 on 2026-09-01, with the Python package version reading 0.4.2 in pyproject.toml. The pace suggests an active line of work on a young project, and the version numbering between the git tags and the package metadata is worth watching when you pin a dependency.

The academic side is documented in the README as well. The work was published in IEEE Robotics and Automation Letters in 2026, with a citation block giving volume 11, number 6, pages 7420 to 7427, and a DOI, alongside an arXiv preprint at 2509.06593. The paper supplementary page on the project site collects extra figures and explanations for the same paper. If you use this in research, the citation is the citation to use, and the README asks for it alongside the paper rather than treating it as optional.

The licence is MIT, stated in the README badge, in the LICENSE file at the repository root, and in the pyproject metadata as a licence text of MIT. For commercial use in a robot product that is a straightforward, permissive choice, with the usual obligation to retain the licence and copyright notice, which is a matter for your own legal review rather than this article.

The documentation is split across the two entry points the README links to, one page for the Python usage and one for ROS, plus the paper supplementary page. That is where to look when a configuration key or a launch argument does not behave the way the README summary suggests.

Editorial conclusion

Adopt RKO-LIO if you need accurate LiDAR-inertial odometry on hardware that changes between platforms, you can supply the IMU to LiDAR extrinsics, and you are willing to treat the system as odometry rather than a full SLAM stack. Do not adopt it expecting loop closures or drift correction, which the author points at the separate rko_slam project for, and do not rely on the ral_submission branch, which the README marks as unsupported. Verify first that your ROS distribution is one of Humble, Jazzy, Kilted, Lyrical or Rolling, that your Python is 3.10 or newer, and that the extrinsic keys in your config file are the ones the loader expects, since the project uses the MIT licence and the last push was on 2026-10-18.

Frequently asked questions

How do I install RKO-LIO and run it on a rosbag?

The README gives pip install "rko_lio[all]" or pip install rko_lio rosbags "rerun-sdk>=0.31", then rko_lio -v /path/to/data, where the data path is a directory of ROS 1 .bag files or a ROS 2 metadata.yaml. The -v flag opens the optional rerun visualizer.

Which ROS 2 distributions does RKO-LIO support?

The README lists Humble, Jazzy, Kilted, Lyrical and Rolling. It can be installed with sudo apt install ros-$ROS_DISTRO-rko-lio or built in a colcon workspace with colcon build --packages-select rko_lio.

What configuration does RKO-LIO require?

The extrinsic between IMU and LiDAR must be known. If it is not in the data, you pass a config file with --config containing the keys extrinsic_imu2base_quat_xyzw_xyz and extrinsic_lidar2base_quat_xyzw_xyz, each a list such as [0,0,0,1,0,0,0] for identity.

Does RKO-LIO do loop closure and SLAM?

No. The README states that if you want a SLAM system with loop closures, a pose graph back end and drift correction, you should look at the separate rko_slam project, and describes the current project as still early days.

Official sources

  1. License: MIT
  2. PRBonn/rko_lio on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/prbonn-rko-lio.svg)](https://hysenlabs.com/projects/prbonn-rko-lio)

Was this useful?