LiDAR-Inertial Odometry: LIO-SAM vs FAST-LIO2 vs KISS-ICP for Robot Localization (2026)

LiDAR-Inertial Odometry: LIO-SAM vs FAST-LIO2 vs KISS-ICP for Robot Localization (2026)

LiDAR Inertial Odometry: LIO-SAM vs FAST-LIO2 vs KISS-ICP for Robot Localization (2026)

Pick the wrong odometry front end and your robot will not tell you at the bench. It tells you three weeks later, in a long corridor, at 2 a.m., when the pose estimate slides forward while the wheels are stationary. Lidar inertial odometry is the layer that turns a stream of range scans and IMU samples into a smooth, drift-limited pose, and the three open-source stacks most teams evaluate (LIO-SAM, FAST-LIO2 and KISS-ICP) make three very different bets about what that layer should be.

This matters in 2026 because the choice is no longer academic. Cheap solid-state and mechanical LiDARs, ARM compute modules and ROS 2 distributions have made on-robot 3D localization routine, and the failure modes of each algorithm now decide whether a fleet ships. Published benchmarks are mostly from 2020 to 2023 and are not directly comparable, so you need to reason from mechanism.

You will leave with a clear model of how each system works, what each demands from your hardware, where each breaks, and a decision procedure you can run against your own logs.

What this covers: the odometry problem and its limits, the architecture of all three systems, a side-by-side decision matrix, a validation harness, failure modes, and recommendations.

Context and Background

Odometry answers one question: given everything I have sensed so far, how far did I move since a moment ago? It is not localization against a prior map, and it is not full SLAM. Odometry is local, continuous and fast, and it accepts that error will accumulate. A downstream layer (loop closure, map matching, GPS or a prior map) bounds that error. Our overview of SLAM architecture for autonomous robots places odometry in that wider stack, and this post zooms into the front end.

Pure LiDAR odometry registers consecutive scans against each other or against a local map, typically with some variant of Iterative Closest Point (ICP). It works well when geometry is rich. It degrades when it is not: a long featureless corridor, an open field, or a tunnel gives the optimizer a direction in which the cost function is flat, so motion along that direction is unobservable. This is the classic degeneracy problem. The physics of why a scan looks the way it does, including motion distortion from a rotating sensor, is covered in how LiDAR actually works.

An IMU (inertial measurement unit, a gyroscope plus accelerometer) fills two gaps. First, it gives a short-horizon motion prior at hundreds of hertz, so the optimizer starts close to the answer. Second, it lets you undo motion distortion: a mechanical LiDAR takes roughly 100 ms to sweep one revolution at 10 Hz, and during that time the robot moves, so each point was measured from a slightly different pose. Knowing the motion within the sweep lets you re-project all points to a common instant (“deskewing” or “undistortion”).

Tight coupling is the key distinction in this field. A loosely coupled system runs LiDAR odometry and IMU integration separately and blends the outputs afterwards. A tightly coupled system feeds raw LiDAR residuals and IMU measurements into one estimator, so each sensor can constrain the other’s weakness. Both LIO-SAM and FAST-LIO2 are tightly coupled; they just implement the estimator differently. KISS-ICP is LiDAR-only and takes a different philosophy: do one thing with almost no tuning.

The three systems, with the primary sources used for this article:

  • LIO-SAM by Tixiao Shan and colleagues (IROS 2020, arXiv 2007.00258). A factor-graph smoother built on GTSAM with iSAM2. BSD-3-Clause per the repository.
  • FAST-LIO2 by Wei Xu and colleagues from the HKU Mars lab (arXiv 2107.06829, IEEE T-RO 2022). An iterated error-state Kalman filter with an incremental k-d tree. GPL-2.0 per the repository.
  • KISS-ICP by Ignacio Vizzo and colleagues at the University of Bonn (RA-L 2023, arXiv 2209.15397). A LiDAR-only point-to-point ICP pipeline. MIT licence.

Licensing deserves a sentence on its own because it surprises teams late. GPL-2.0 on FAST-LIO2 is a procurement question if you ship a closed-source product that links the code. I am not a lawyer, so have yours read the repository terms before you build on it.

Three Architectures, Three Bets

The most useful framing is not “which is best” but “what does each system bet on”. LIO-SAM bets that a smoother over a factor graph, fed by cheap feature matching, gives the best global consistency and the easiest sensor fusion. FAST-LIO2 bets that a filter with a very fast map data structure and raw points gives the best accuracy per CPU cycle. KISS-ICP bets that a classical algorithm, done carefully, removes the need for an IMU and most tuning.

Direct answer: LIO-SAM is a factor-graph smoother that adds GPS and loop closure easily but needs a 9-axis IMU and more CPU. FAST-LIO2 is an iterated Kalman filter on raw points with an incremental k-d tree, the lightest tightly coupled option. KISS-ICP is LiDAR-only point-to-point ICP with adaptive thresholds, the easiest to deploy but with no inertial help.

lidar inertial odometry generic pipeline from sensor streams to pose output

Figure 1: The common skeleton of a lidar inertial odometry system. IMU propagation gives a prior, deskewing corrects the scan, registration against a local map refines the pose, and the map is updated incrementally.

Figure 1 shows the structure all three share. Scans and IMU samples arrive asynchronously, the IMU prior is used to deskew and to seed registration, a scan-to-local-map match refines the pose, and the local map grows. The differences are in what “update pose” and “update map” mean. In the long description for accessibility: the diagram flows left to right from two input streams to a pose that is published to a navigation stack or an extended Kalman filter, with a feedback loop between registration and the map.

LIO-SAM: a smoother with a factor graph

LIO-SAM extracts edge and planar features from each scan by local roughness: high roughness points become edge features, low roughness points become planar features. It then matches those features against a local map. The local map is built from a sliding window of the most recent keyframes; the paper uses the 25 most recent keyframes merged into a voxel map downsampled at 0.2 m for edges and 0.4 m for planar features.

A new keyframe is created only when the robot has moved more than 1 m or rotated more than 10 degrees, according to the paper. This is a design choice with real consequences: it bounds the size of the graph and the map, which keeps runtime tied to feature density rather than trajectory length, but it also means that in very slow or very small motion the system does little work and relies on the IMU.

The estimator is a pair of graphs. According to the repository, one graph in imuPreintegration.cpp holds IMU preintegration and LiDAR odometry factors and estimates IMU bias; it is reset periodically. The other, in mapOptimization.cpp, holds LiDAR odometry factors plus optional GPS and loop closure factors and persists for the entire run. Both are solved incrementally with iSAM2, which re-linearizes only the affected part of a Bayes tree when new factors arrive.

LIO-SAM style factor graph with IMU, LiDAR, GPS and loop closure factors feeding iSAM2

Figure 2: LIO-SAM style factor-graph architecture. Four factor types feed a single incremental smoother, which is what makes GPS and loop closure plug-in rather than a redesign.

The four factor types in the paper are IMU preintegration, LiDAR odometry, GPS and loop closure. The strength of the design is visible in Figure 2: adding a new absolute measurement means adding a factor, not rewriting the estimator. That is why LIO-SAM’s published results are strongest in long outdoor runs with GPS. The paper reports end-to-end translation errors of 0.12 m on its Campus dataset, 0.04 m on Park and 0.17 m on Amsterdam, using LIO-SAM with GPS and loop closure. Those are the authors’ numbers on their own datasets and sensors (Velodyne VLP-16, a MicroStrain 3DM-GX5-25 IMU and a Reach M GPS, on an Intel i7-10710U laptop); treat them as evidence that the architecture can reach that accuracy, not as a forecast for your robot.

The paper’s runtime table is also informative. LIO-SAM ran at 41.9 ms to 100.5 ms per scan across its five datasets, with the longer times on the feature-dense Campus and Park runs. In their analysis, runtime depended more on feature density than on graph size: Park produced 4,573 nodes and 9,365 factors, Amsterdam 23,304 nodes and 49,617 factors, yet Amsterdam ran faster per scan.

The practical costs sit in the README. LIO-SAM expects a 9-axis IMU that supplies orientation (roll, pitch and yaw), recommends at least 200 Hz, and does not natively support 6-axis IMUs; the README points to a third-party fork called liorf for that. The README also says only mechanical LiDARs are currently supported, with Livox Horizon described as lightly tested. Dependencies include GTSAM 4.0, and the README reports that crashes in mapOptimization are usually GTSAM-related. The original implementation targets ROS 1 (Kinetic and Melodic tested); a ROS 2 port lives on a ros2 branch. The repository also listed 175 open issues at the time I read it, which is a maintenance signal worth weighing.

FAST-LIO2: a filter, a k-d tree and raw points

FAST-LIO2 makes three decisions that distinguish it from LIO-SAM. It estimates the state with an iterated error-state Kalman filter (IESKF) on a manifold, rather than smoothing a graph. It registers raw points, skipping feature extraction. And it stores the map in an incremental k-d tree (ikd-Tree) that supports insertion, deletion and rebalancing without rebuilding.

The filter works like this. IMU measurements propagate the state at IMU rate. When a LiDAR scan arrives, points are undistorted by back-propagating the IMU measurements to the scan-end time. Each point is transformed by the predicted pose, matched to its five nearest map points, and those neighbors define a local plane. The residual is the signed point-to-plane distance. The update is iterated until the state converges, because the measurement model is nonlinear in the pose. The paper states that the state lives on a manifold of dimension 24 and that the LiDAR-IMU extrinsic is estimated online, which is useful when your calibration is imperfect.

FAST-LIO2 iterated error-state Kalman filter loop with ikd-Tree map and point-to-plane residuals

Figure 3: The FAST-LIO2 inner loop. The iteration between nearest-neighbour search and the state update is what the paper calls the iterated update; only after convergence are points inserted into the ikd-Tree.

There is a neat computational trick here. A scan can contain thousands of points, so the measurement dimension is large. The paper uses an equivalent form of the Kalman gain in which the matrix to invert has the size of the state, not of the measurement. Because the state is fixed and small while the measurement count varies, the cost of the update stops scaling badly with point count. The paper states this is mathematically equivalent to the conventional gain.

The ikd-Tree is the other half of the speed story. It is based on a scapegoat k-d tree and stores points in both internal and leaf nodes. It supports point insertion with on-tree downsampling (the paper uses a 0.5 m resolution), box-wise deletion using lazy labels, and dynamic rebalancing. Subtrees above a size threshold are rebuilt in a parallel thread, and an operation log keeps queries correct during the rebuild. The paper gives insertion and nearest-neighbour search as O(log n). Compared with rebuilding a static tree such as nanoflann each scan, the paper reports the ikd-Tree peaked at 2 million and 3.6 million points on two sequences where the static tree reached over 6 million and 10 million.

Map management is simple: a local map cube, 1000 m by default per the paper, and points that drift outside the boundary are deleted in cuboid batches. The paper also tested 2000 m, 800 m and 600 m and found that gains from larger maps were not consistent beyond 2000 m, which makes sense, since drift can cause false matches to old map points.

On speed, the paper reports total processing of 1.82 ms per scan on an Intel i7 (quad-core, 4 threads) and 5.23 ms on an ARM Cortex-A73 (2 threads) for a 756-points-per-scan setup, with ARM occasionally exceeding the 10 ms scan period. It also claims roughly 8x, 10x and 6x speed-ups relative to LILI-OM, LIO-SAM and LINS respectively in its own comparison. These numbers use the authors’ hardware, point counts and downsampling, and the 756-point figure reflects a heavily downsampled scan; do not extrapolate to a dense 128-beam sensor without measuring.

On accuracy the paper reports FAST-LIO2 or a variant best on 18 of its 19 benchmark sequences, with LILI-OM slightly ahead on one (2.29 m against 2.57 m on ulhk 4). One concrete data point: on its liosam 1 sequence it reports 4.58 m RMSE against LIO-SAM’s 4.75 m. Note the scale: these are metres of end-to-end error over long trajectories without loop closure. The paper also describes FAST-LIO2 as odometry only: no loop closure and no global correction, so drift accumulates.

The practical notes from the repository: it supports Livox, Velodyne and Ouster sensors (16, 32 and 64 lines tested; 128 lines and above not), accepts internal or external IMUs, and the Velodyne config accepts 6-axis or 9-axis IMUs. That last point is a key operational difference from LIO-SAM: FAST-LIO2 only needs angular rate and acceleration, not a magnetometer-fused heading. It needs per-point timestamps for undistortion; missing them triggers a “Failed to find match for field ‘time'” warning, and Livox data must come in the custom message format. The extrinsic is the LiDAR pose in the IMU frame, entered as extrinsic_T and a rotation matrix, and the repository recommends turning off online estimation when the extrinsic is well known.

KISS-ICP: do the classical thing correctly

KISS-ICP stands for “Keep It Small and Simple” ICP. Its paper, “In Defense of Point-to-Point ICP”, argues that a classical point-to-point ICP, combined with a handful of careful engineering decisions, matches far more complicated systems. The abstract names adaptive thresholding for correspondence matching, a simple motion compensation approach, and a point cloud subsampling strategy. It reports the same parameters across automotive vehicles, UAVs, Segway-type vehicles and handheld LiDARs, with no IMU input, and states that the open-source system runs faster than the sensor frame rate on all presented datasets.

From my reading of the method in the paper body (not just the abstract, so check it yourself before quoting), the pipeline is: deskew the incoming scan using the previous frame-to-frame velocity as a constant-velocity prediction, subsample it, register it to a local map using point-to-point ICP with a correspondence distance threshold that adapts to how much the prediction has been wrong lately, then update the pose and the map. The adaptive threshold is the central trick. A fixed threshold forces you to guess how far apart correct correspondences might be; an adaptive threshold derived from recent motion error removes that guess.

The repository describes it as a LiDAR odometry pipeline that “just works on most of the cases without tunning any parameter”, per the README text. It is MIT licensed, installable with pip install kiss-icp, and ships ROS 2 support. The README states ROS 1 support is deprecated, with v0.3.0 the last release to carry it. A PyPI listing I fetched for version 0.2.3 (released March 2023) noted that a newer 1.3.0 existed at crawl time; check PyPI for the current release when you read this.

What you give up is anything inertial. Without an IMU, the motion prior is a constant-velocity guess; abrupt changes of motion, such as a quadruped stumbling or a drone flipping, break that guess, and the deskewing of the scan inherits the error. Without an IMU there is also no gravity direction, so there is nothing to keep pitch and roll honest over long runs beyond what scan geometry gives.

The Estimator Differences That Matter in Practice

Architecture diagrams hide the operational differences, so this section translates them into the questions you will actually face on a robot. I mark opinion as opinion; everything else traces to the sources above or to first principles.

Filter versus smoother

A filter keeps a single current state and a covariance; once a measurement is incorporated, it is gone. A smoother keeps a window or the entire history of states and re-optimizes them when new information arrives. The trade-off is classical.

The filter in FAST-LIO2 is cheap, with a fixed-size state and no growing structure other than the map. Its weakness is that errors linearized into the past cannot be revisited. If a bad match is incorporated, it stays incorporated.

The smoother in LIO-SAM can revise past poses when a loop closure or a GPS factor arrives, and iSAM2 does this incrementally without re-solving everything. Its weakness is cost and complexity: more state, more tuning around keyframe selection, and a heavier dependency stack.

KISS-ICP is neither. It is a pure scan-to-map pipeline with no probabilistic state estimate beyond the pose. That makes it easy to reason about and also means there is no principled uncertainty to hand to a downstream filter. If you need a covariance for sensor fusion, you will be inventing one.

Features versus raw points

LIO-SAM extracts edge and planar features, which reduces the number of points matched and gives the optimizer well-conditioned residuals in structured scenes. The cost is that feature extraction depends on the LiDAR’s scan pattern. It assumes a ring structure and a roughness measure computed along a scan line. That is why the README lists mechanical LiDARs as the supported class.

FAST-LIO2’s raw-point approach removes that dependency, which is why it works on non-repetitive-scan solid-state sensors like the Livox Avia, tested with a 70.4 by 77.2 degree field of view in the paper. The authors argue it also helps in small-field-of-view and structure-poor scenes since no information is thrown away by a feature selection step. The paper’s own evidence is mixed in a useful way: the earlier feature-based FAST-LIO was slightly better on one sequence in open areas with trees, and in most sequences the two performed similarly. So “raw points are strictly better” is not what the data say; “raw points remove a tuning and sensor-specific step at no accuracy cost on average” is closer.

KISS-ICP subsamples with voxels and uses points directly, so it too is sensor-agnostic. The implementation details (a voxel-hash-based map in the current code) are from my own familiarity with the repository and are not something I verified from the pages I fetched this run.

Timing and synchronization: the failure everyone hits

All three systems are sensitive to timestamps, and LIO-SAM and FAST-LIO2 are the most sensitive because of tight coupling. The LIO-SAM README lists zigzag motion as likely caused by unsynchronized LiDAR and IMU timestamps and start-up jumping as a sign of wrong IMU extrinsics, such as a negative gravity reading. The FAST-LIO README warns about missing per-point times and recommends hardware synchronization over its software time-sync option.

Here is a first-principles estimate of why this matters. Suppose the robot rotates at 100 degrees per second, a plausible figure for a handheld or legged platform (the FAST-LIO2 paper’s fast handheld run reports about 100 degrees per second). A 10 ms timestamp offset between IMU and LiDAR then misattributes about one degree of rotation. At 20 m range, one degree of angular error displaces a point by roughly 0.35 m (20 m times the tangent of one degree). That is far above the centimetre-level noise of the sensor, and it is systematic rather than random, so the optimizer will fight it with bias terms and extrinsics. The arithmetic is mine and illustrative, but the direction is robust: time offsets scale with angular velocity and range.

Practical advice: before you compare algorithms, measure your sensor latency chain. Use PTP or hardware triggering where the LiDAR supports it, check that the driver stamps packets at acquisition and not at publish, and verify that per-point times are present and in the units the odometry expects.

IMU grade and what each system assumes

LIO-SAM wants orientation from the IMU. The README states roll and pitch initialize attitude and yaw sets heading when GPS is used, and notes that Ouster’s built-in IMU is 6-axis and so needs an external 9-axis unit. The author’s own setup used a MicroStrain 3DM-GX5-25 at 500 Hz, which is a tactical-grade-adjacent unit rather than a hobby breakout. If your robot carries a consumer MEMS IMU with a poor magnetometer next to motors and steel, expect trouble.

FAST-LIO2 only consumes angular velocity and linear acceleration and estimates bias online. It tolerates cheaper IMUs, though bias stability still limits how long it can bridge degenerate geometry.

KISS-ICP ignores the IMU entirely, which is a feature when your IMU is the problem.

Degeneracy, Drift and the Corridor Test

Every point-registration method suffers when the scene underconstrains the pose. Think of ICP as minimizing a sum of squared distances. In a long straight corridor, the walls constrain lateral position and the vertical; the floor and ceiling constrain height; nothing constrains position along the corridor axis. The Hessian of the cost has a near-zero eigenvalue in that direction, and small noise or a bad association pushes the solution arbitrarily far along it.

An IMU rescues this partly: accelerometer integration gives a motion estimate along the corridor, but only for as long as bias and noise are small. Double integration of acceleration error grows quadratically with time. A constant accelerometer bias of 0.01 m/s^2 (an illustrative figure, not tied to any specific device) accumulates 0.5 times 0.01 times t squared: 0.5 m of position error after 10 s and 2 m after 20 s. That is why tight coupling buys seconds of resilience, not minutes, in true degeneracy, and why the wheel odometry or a prior map belong in your architecture as well.

The three systems respond differently. FAST-LIO2’s Kalman update will, in a degenerate direction, rely on the prior from IMU propagation because the measurement carries no information there; the state covariance in that direction grows. LIO-SAM’s factor graph likewise leans on IMU factors, but its feature-based front end can lose the few features that exist and fail to produce a LiDAR factor at all; the code has threshold parameters such as edgeFeatureMinValidNum for that reason. KISS-ICP, lacking an inertial prior, extends its constant-velocity guess, which in a corridor is often not terrible until the robot accelerates or stops.

One safeguard that is cheap and independent of algorithm: compute the degeneracy of the registration problem yourself (eigenvalues of the point-to-plane normal matrix) and publish it. If the smallest eigenvalue falls below a threshold, inflate the odometry covariance in the robot’s fusion filter or stop trusting it along that axis. This is advice, not something any of the three ships by default as far as I verified.

Side-by-Side Comparison

The matrix below uses only facts from the sources named above or labelled judgement. “Judgement” means my opinion from first principles.

Dimension LIO-SAM FAST-LIO2 KISS-ICP
Sensor input LiDAR plus 9-axis IMU LiDAR plus IMU (6 or 9 axis in Velodyne config) LiDAR only
Estimator Factor graph, iSAM2 Iterated error-state Kalman filter Point-to-point ICP with adaptive threshold
Front end Edge and planar features Raw points, point-to-plane Raw subsampled points
Map structure Sliding window of keyframes, voxel maps ikd-Tree, 1000 m local map default Local voxel map (implementation detail, unverified this run)
Global correction GPS and ICP loop closure built in None, odometry only None, odometry only
LiDAR types Mechanical (README); Livox lightly tested Livox, Velodyne, Ouster Broad, parameter-free claim
ROS ROS 1 original, ros2 branch ROS 1 original (ROS 2 unverified) ROS 2 supported, ROS 1 deprecated
Licence BSD-3-Clause GPL-2.0 MIT
CPU cost (paper claims) 41.9 to 100.5 ms per scan on i7 laptop 1.82 ms on i7, 5.23 ms on Cortex-A73 (downsampled) Faster than sensor rate per authors
Main dependency risk GTSAM build, 9-axis IMU Timestamps, GPL licence No IMU prior

Treat the CPU row with caution. The three papers use different hardware, different downsampling and different point counts per scan, so their milliseconds cannot be ranked against one another without a common benchmark. The FAST-LIO2 paper does run a head-to-head against LIO-SAM and others on shared datasets, which is why I cited its claimed ratios earlier, but that is the FAST-LIO2 authors’ benchmark of their rivals. Independent replication matters.

A decision flow follows, then a harness to produce your own numbers.

decision flow for choosing between LIO-SAM, FAST-LIO2 and KISS-ICP for lidar inertial odometry

Figure 4: A practical decision flow for lidar inertial odometry stack selection. Start from what sensors you can trust, then from what correction layers you need.

Reading Figure 4 in words: if you have no trustworthy IMU, or your LiDAR changes between robots, start with KISS-ICP. If you have a good IMU and a tight compute budget, start with FAST-LIO2. If you need GPS fusion and loop closure inside the same estimator and can supply a 9-axis IMU, start with LIO-SAM. In every branch, validate on your own logs.

Building a Fair Evaluation Harness

Published numbers are conditional on their datasets. The only evidence that matters is your robot on your routes. A minimal harness has four parts: recorded bags, ground truth, a trajectory metric, and a runtime profile.

Recorded bags. Record raw sensor topics, not processed ones: LiDAR packets or point clouds with per-point times, IMU at its native rate, and any wheel odometry. Include at least one route that is deliberately hostile: a long corridor, an open lot, a fast turn, and one stationary period of several minutes to expose bias drift.

Ground truth. Use whatever you have. RTK GPS outdoors is good to a few centimetres when it has a fix. Indoors, a total station or a motion-capture room is ideal; failing that, loop the route and measure how far the end pose is from the start pose, which gives an end-to-end drift figure like the one in the LIO-SAM paper.

Metrics. Absolute trajectory error (ATE) after rigid alignment is the headline number, and relative pose error (RPE) over fixed distances is the one that predicts navigation quality. The evo Python package computes both from TUM-format trajectories.

Here is a compact script that converts three odometry output files to a comparison table. It is a sketch to adapt, not a drop-in tool, and it assumes you have exported each algorithm’s trajectory as TUM text (timestamp, x, y, z, qx, qy, qz, qw).

# compare_odometry.py  -- run: python compare_odometry.py gt.tum liosam.tum fastlio2.tum kiss.tum
import sys
import numpy as np
from evo.core import metrics, sync
from evo.tools import file_interface

def ape_rmse(gt_path, est_path):
    gt = file_interface.read_tum_trajectory_file(gt_path)
    est = file_interface.read_tum_trajectory_file(est_path)
    gt, est = sync.associate_trajectories(gt, est, max_diff=0.02)
    est.align(gt, correct_scale=False)           # rigid SE(3) alignment
    ape = metrics.APE(metrics.PoseRelation.translation_part)
    ape.process_data((gt, est))
    return ape.get_statistic(metrics.StatisticsType.rmse)

def rpe_mean(gt_path, est_path, delta_m=10.0):
    gt = file_interface.read_tum_trajectory_file(gt_path)
    est = file_interface.read_tum_trajectory_file(est_path)
    gt, est = sync.associate_trajectories(gt, est, max_diff=0.02)
    rpe = metrics.RPE(metrics.PoseRelation.translation_part,
                      delta=delta_m, delta_unit=metrics.Unit.meters,
                      all_pairs=False)
    rpe.process_data((gt, est))
    return rpe.get_statistic(metrics.StatisticsType.mean)

if __name__ == "__main__":
    gt = sys.argv[1]
    print(f"{'method':<14}{'ATE RMSE m':>12}{'RPE 10m mean':>14}")
    for est in sys.argv[2:]:
        print(f"{est:<14}{ape_rmse(gt, est):>12.3f}{rpe_mean(gt, est):>14.3f}")

Runtime profile. Log per-scan processing time and the maximum, not only the mean. The FAST-LIO2 paper itself notes that on ARM, processing occasionally exceeded the 10 ms period. A navigation stack cares about the worst case. Also log CPU load of the whole robot, because odometry shares the machine with perception and planning.

For ROS 2 deployments, the KISS-ICP ROS wrapper follows the standard pattern: build in a workspace and launch the node with your topic remapped. The topic and launch argument names below follow the repository’s documented style as I recall them; confirm against the README for your version.

# KISS-ICP, ROS 2 (confirm exact names in the README of your checkout)
mkdir -p ~/ws/src && cd ~/ws/src
git clone https://github.com/PRBonn/kiss-icp.git
cd ~/ws && colcon build --packages-select kiss_icp
source install/setup.bash
ros2 launch kiss_icp odometry.launch.py topic:=/lidar/points

Two warnings on interpreting your results. First, align on a common time base; offsets of tens of milliseconds between ground truth and estimate show up as spurious error at speed. Second, run each algorithm with its own authors’ recommended configuration for your LiDAR before concluding anything. A badly configured LIO-SAM will lose to a default KISS-ICP, and that says something about configuration cost, which is legitimate to count, but it does not say the architecture is worse.

Integration: What the Output Is and Where It Goes

An odometry node is a component in a localization pipeline. In a typical ROS stack, the LiDAR-inertial odometry publishes a pose or an odom to base_link transform at scan rate. A navigation stack such as Nav2 consumes a smooth local pose and a global map-frame pose from a separate localizer, the usual REP-105 frame split of map, odom and base_link. Our look at Nav2 controllers and trajectory validation shows how the controller layer depends on that pose being continuous.

Continuity is the property that favours odometry here. A planner tolerates drift, since a slowly wrong pose is still a smooth pose, but it does not tolerate jumps. This is a quiet argument against placing a smoother’s global corrections directly in the odom frame. LIO-SAM’s loop closure and GPS factors can cause the optimized trajectory to jump when they fire. The conventional answer is to publish the smooth, drifting estimate as odom and the corrected estimate as the map to odom correction, so the jump is absorbed in the transform that downstream consumers already treat as discontinuous.

Fusion with wheel odometry is the other integration decision. For a wheeled robot, a pragmatic design runs an extended Kalman filter (for example robot_localization, which LIO-SAM itself lists as a dependency) that combines wheel velocities, the IMU and the LiDAR odometry pose. In that arrangement you feed the LiDAR odometry as a pose or twist measurement with an honest covariance, which loops back to the point above: FAST-LIO2 gives you a filter covariance you can use, LIO-SAM’s output needs one derived, and KISS-ICP needs one invented or estimated from residuals. This is a small practical point that quietly decides how clean your fusion layer is.

Finally, consider the data path. At 10 Hz with 100,000 points per scan, a point cloud message is several megabytes, so transport matters: use shared-memory transports or intra-process communication where your middleware supports it, and keep the odometry node and the LiDAR driver on the same host if you can. Latency added by serialization shows up as exactly the timestamp-offset error discussed earlier, if the odometry node uses arrival time instead of acquisition time.

Trade-offs, Gotchas, and What Goes Wrong

Drift is guaranteed; the question is the rate. The FAST-LIO2 paper reports the large-scale handheld run of about 650 m with 0.14 m drift, and the fast handheld run under 0.06 m over 81 m. Both are impressive and both are specific to the authors’ setup. In a 24-hour fleet deployment, odometry-only systems drift without bound, and you need a relocalization or map-matching layer. Do not let a good benchmark number persuade you otherwise.

Dynamic scenes. Point-to-plane and point-to-point registration both assume a static world. A busy warehouse with moving forklifts, or a crowd, puts non-static points into the local map. Maps built from these scans carry ghosts that later corrupt registration. FAST-LIO2’s lazy deletion and local map window help by forgetting old regions, and KISS-ICP’s adaptive threshold limits how far a bad correspondence can reach, but neither removes moving objects. If your environment is dynamic, test it specifically.

Initialization. Tightly coupled systems need to start stationary or with a known gravity direction. FAST-LIO’s documentation mentions automatic initialization in steady environments, and the LiDAR_IMU_Init tool is pointed to for extrinsics. Starting while moving is the classic way to poison the bias estimate for the rest of a run.

Extrinsic errors. A rotation error of one degree between LiDAR and IMU frames corrupts every deskew and every gravity alignment. LIO-SAM’s README flags wrong extrinsics as the cause of jumping at startup. FAST-LIO2 can estimate extrinsics online, but online estimation can also absorb other errors, so calibrate offline and fix the value when you can.

Unobserved features of the sensor. Highly reflective surfaces, glass, rain and dust produce spurious returns. The LIO-SAM paper itself reports sunlight causing false detections about 20% of the time on one dataset, and degenerate scenes under bridges. These are sensor and environment effects that no choice among the three eliminates; filtering belongs in your driver and preprocessing.

Maintenance and ecosystem risk. LIO-SAM’s repository reported 175 open issues, an unresolved bug listed in its TODO for the IMU preintegration module, and a ROS 1 heritage. FAST-LIO’s ROS 2 story was not documented on the page I read, although community ports exist; I did not verify any of them, so evaluate their maintenance yourself. KISS-ICP deprecated ROS 1 and focuses on ROS 2. A fork, a vendor-maintained build or an in-house port is a legitimate answer for any of them, and you should budget the engineering time.

Anti-pattern: tuning to the benchmark. Teams often replay the authors’ public datasets, get a good result and stop. The datasets use specific sensors and motion profiles. The more useful experiment is to deliberately break your configuration (delay the IMU, degrade the extrinsic, remove the IMU) and watch how each system fails. A system that degrades gracefully is worth more than one that is precise on an ideal day.

Anti-pattern: trusting odometry timing as ground truth. A system that runs at 1.8 ms per scan on a laptop-class CPU tells you nothing about its latency on your embedded board with a loaded bus and thermal throttling. Measure on target.

Practical Recommendations

If I had to give one opinionated rule, it is this: choose by constraints first and accuracy second, because on a sound installation the three systems are closer than their fan bases suggest, and the constraints are what actually differ.

Choose KISS-ICP when you cannot rely on an IMU, when you run multiple LiDAR models across a fleet, when your team is small and tuning time is the scarce resource, or when you want a clean MIT-licensed baseline. It is also the right first experiment on any new robot: if KISS-ICP already gives smooth odometry, an inertial system may be unnecessary complexity.

Choose FAST-LIO2 when you have a good, time-synchronized IMU and a tight CPU budget, when your platform moves aggressively (the paper’s flip and fast-handheld experiments are the relevant evidence), or when you are using a non-repetitive solid-state LiDAR. Plan for an external loop closure or relocalization layer, and have counsel review the GPL-2.0 terms if you ship commercially.

Choose LIO-SAM when you need GPS fusion and loop closure in a single estimator, when you operate outdoors over long routes with a mechanical LiDAR and a 9-axis IMU, and when you are comfortable owning a GTSAM-based codebase. Its factor-graph design is the one that most easily accepts new absolute measurements.

A practical checklist before you commit:

  • Measure LiDAR and IMU latency and confirm per-point timestamps exist and have the right units.
  • Calibrate the LiDAR-IMU extrinsic offline and verify gravity direction on the bench.
  • Record a hostile route set: corridor, open area, fast rotation, long stationary period.
  • Run all three with default configurations first, then with authors’ recommended settings for your sensor.
  • Score ATE, RPE and worst-case scan time on target hardware, not a laptop.
  • Publish a covariance or degeneracy flag from whichever you choose, and feed it to your fusion filter.
  • Decide where global correction lives (map matching, loop closure, GPS) before you pick the front end.
  • Review licence terms for your distribution model.

Frequently Asked Questions

What is lidar inertial odometry?

It is the estimation of a robot’s incremental motion by combining LiDAR scans with IMU measurements in one estimator. The IMU supplies a high-rate motion prior and lets the system correct distortion within a scan, while the LiDAR constrains drift by registering points against a local map. Tight coupling means both sensors enter a single optimization or filter rather than being blended afterwards.

Is FAST-LIO2 better than LIO-SAM?

On the FAST-LIO2 authors’ benchmark it was best or near best on 18 of 19 sequences and far cheaper on CPU, but that is the authors’ own comparison. LIO-SAM brings GPS and loop closure that FAST-LIO2 lacks as shipped. If you need those, LIO-SAM can be the better system despite higher cost. If you need low compute and aggressive motion, FAST-LIO2 usually wins.

Does KISS-ICP need an IMU?

No. KISS-ICP uses only LiDAR point clouds, according to its paper’s abstract. It deskews scans with a simple motion model and adapts its correspondence threshold, so it does not require IMU input or per-sensor tuning. The trade-off is that without an inertial prior it handles sudden accelerations and long featureless stretches less well than a tightly coupled system with a good IMU.

Can I use a 6-axis IMU with LIO-SAM?

Not with the original code. The README says LIO-SAM expects a 9-axis IMU that provides orientation, and that 6-axis IMUs are not natively supported. It points to a derived project, liorf, that adds 6-axis support. FAST-LIO2’s Velodyne configuration, by contrast, accepts 6-axis or 9-axis IMUs, which can make it the easier choice for sensors with built-in 6-axis units.

Do these systems do loop closure?

LIO-SAM does, using an ICP-based proof of concept adapted from LeGO-LOAM, and its README suggests ScanContext for more serious use. FAST-LIO2 is odometry only per its paper, so drift accumulates until another layer corrects it. KISS-ICP is likewise odometry. For long deployments, add a loop closure or map-matching module around whichever front end you pick.

Which one runs best on a Raspberry Pi class computer?

I do not have a verified benchmark for that board and will not guess. The FAST-LIO2 paper reports 5.23 ms per scan on a 2.2 GHz quad-core Cortex-A73 with a downsampled 756-point scan, which is the strongest published ARM evidence among the three. KISS-ICP’s authors claim faster-than-sensor-rate operation but the sources I read gave no ARM figures. Measure on your hardware.

Further Reading

By Riju — about

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *