KISS-IMU: Self-supervised Inertial Odometry
with Motion-balanced Learning and Uncertainty-aware Inference
Jiwon Choi, Hogyun Kim, Geonmo Yang, Juhui Lee, Younggun Cho†
🤖 Spatial AI and Robotics Lab (SPARO)
<Keep IMU Stable and Strong>
- 🏆 May 6, 2026. Selected as an IEEE ICRA 2026 Award Finalist.
- 🎉 Jan 31, 2026. Accepted to IEEE ICRA 2026.
KISS-IMU denoises raw IMU streams against a self-generated LiDAR-odometry pseudo-label. A GMM-based motion-balanced sampler with a frequency gate keeps under-represented motion regimes from being drowned out during training.
🧪 Just want to see it run? See
RUNNING.mdfor a self-contained synthetic-data demo that needs no external dataset and no GPU, plus environment/CPU notes and thesrc/data/data contract.
The image sparolab/kiss-imu:v1.0 ships with all runtime dependencies (CUDA, PyTorch, pypose, kiss-icp, small_gicp, pygicp, scikit-learn).
git clone https://github.com/sparolab/KISS-IMU.git
cd KISS-IMUEdit docker/docker-compose.yml and replace {dataset_folder} under volumes: with the absolute path to your datasets (e.g. /mnt/hdd/datasets:/storage1). Then launch:
docker compose -f docker/docker-compose.yml up -d
docker exec -it kiss-imu-ws bashInside the container, pwd is already /home/test_ws/src:
bash scripts/train.shpip install -r requirements.txt
bash scripts/train.shOne top-level data_root with one sub-directory per sequence:
📁 <data_root>/
└── 📂 <SEQUENCE_NAME>/
├── 📄 imu.csv
├── 📄 gt_pose.csv
└── 📂 points/
├── 📂 data/
│ ├── 🟦 000000.bin
│ └── ...
└── 📄 timestamps.txt
The loader handles dataset-specific column indices and coordinate transforms once --data-type is set (kitti, mulran, diter_os, …). See examples/dataset_layout.md for custom formats.
bash scripts/train.shHyperparameters live as env vars at the top of scripts/train.sh:
| Variable | Notes |
|---|---|
DATA_DIR |
Root directory of your dataset |
DATA_TYPE |
diter_os | kitti | mulran | ... |
TRAIN_SEQS / VALID_SEQS |
Sequence names under DATA_DIR |
LO_MODEL |
kiss_icp | fast_gicp | small_gicp |
GMM_COMP_NUM |
0 = auto-pick K via BIC, otherwise fixed K |
USE_GT |
GT pose supervision (ablation only, no ICP/PGO) |
USE_SUBMAP |
Aggregate scans into a sub-map for small_gicp |
TRAIN_RATIO |
Fraction of training windows used |
-
GT supervision. Lets you isolate the GMM reweighting contribution from the LO pseudo-label.
USE_GT=true bash scripts/train.sh
-
Raw-IMU + PVGO. Reproduces the
Baseline*reported in the paper.bash scripts/raw_pvgo.sh
Evaluate the best checkpoint:
CKPT=results/.../best_model.ckpt \
EVAL_SEQS="Forest_new Lawn_lower_night Park_in_day" \
bash scripts/evaluate.shReports per-window endpoint RPE (translation, rotation) and end-point
APE, averaged per sequence. Run bash scripts/evaluate.sh --help for
all options.
Save full ICP / PGO trajectories as .npz + top-down .png for plotting or downstream stages:
CKPT=results/.../best_model.ckpt \
SEQS="Forest_new Park_in_day" \
bash scripts/inference.sh| Variable | Notes |
|---|---|
CKPT |
Path to best_model.ckpt (required) |
SEQS |
Sequence names to run inference on (required) |
LO_MODEL |
kiss_icp | fast_gicp | small_gicp |
USE_ADAPTIVE_WEIGHT |
Weight ICP factors by overlap, IMU by integrated cov |
USE_SUBMAP |
Aggregate scans into a sub-map for small_gicp |
Outputs land in <ckpt-dir>/inference/<seq>/{inference.npz, trajectory.png}.
Project encoder features to 2D and color by component id to verify motion-regime separation:
CKPT=results/.../best_model.ckpt \
TRAIN_SEQS="Forest_new" EVAL_SEQS="Park_in_day" \
bash scripts/tsne_encoder.sh| Variable | Notes |
|---|---|
CKPT |
Path to best_model.ckpt (required) |
GMM |
Override the fitted GMM (defaults to <ckpt-dir>/gmm.joblib) |
TRAIN_SEQS / EVAL_SEQS |
One t-SNE plot per split |
PAIR_MODE |
all plots every component. farthest keeps only the two components whose GMM means are most separated (focused separability check). |
PER_COMP |
Points per component (0 = auto, capped by MAX_WINDOWS) |
MAX_WINDOWS |
Total cap on plotted points |
MIN_PER_COMP |
Drop components with fewer windows than this |
PERPLEXITY |
Auto-clamped down if needed |
Outputs: <ckpt-dir>/tsne/{tsne_train.png, tsne_eval.png}. The fitted GMM is saved alongside best_model.ckpt during training, so the default path usually just works.
- 📄 arXiv
- 🌐 Project page
- 🎬 Video
@inproceedings{choi2026kissimu,
title = {KISS-IMU: Self-supervised Inertial Odometry with
Motion-balanced Learning and Uncertainty-aware Inference},
author = {Choi, Jiwon and Kim, Hogyun and Yang, Geonmo and Lee, Juhui and Cho, Younggun},
booktitle = {IEEE International Conference on Robotics and Automation (ICRA)},
year = {2026}
}Jiwon Choi: jiwon2@inha.edu
BSD 3.0 for academic use. For commercial use, please contact the authors.
