Views
No views yet
IMUNet: 6-ch CNN + 2×GRU
with accel/gyro correction heads and per-axis uncertainty heads), trained
self-supervised against Hilti LiDAR odometry via the --use-gt path.imu_encoder.py.relative_poses.npz) expressed in a gravity-aligned, z-up IMU body world
frame (LiDAR→IMU extrinsic estimated from data by gyro/LiDAR hand-eye;
consistent euler ≈ (-178°,-1°,-89.5°) across all sequences).site1_handheld_1,2,3,4, site2_handheld_4 (~9.3k windows)site1_handheld_5| metric (val: site1_handheld_5) | RAW IMU | encoder (run3, ep2) |
|---|---|---|
| per-window relative-motion RRE (pypose, 8-win) | 1.82° | 1.72° (better) |
| per-axis covariance (usable as factor weight) | none | calibrated (~0.6 acc, ~0.1–0.2 gyr) |
| RPE@1s endpoint RTE / RRE | 1.45 m / 5.95° | 1.57 m / 6.00° (≈ raw) |
| RPE@5s endpoint RTE / RRE | 33 m / 13.3° | 36 m / 15.2° (slightly worse) |
--use-gt label
(raw LiDAR odometry) carries a slow vertical (z) drift that a point-correction
network partially fits. The principled fix is the full self-supervised
pipeline (ICP + pose-graph optimization fuses IMU+LiDAR to produce
gravity-consistent, drift-reduced labels) — supported in this repo
(--use-gt off) once a live LiDAR-odometry backend is wired in.1from imu_encoder import IMUEncoder # uses modeling_imunet.py
2import numpy as np
3enc = IMUEncoder("best_model.ckpt", device="cuda:0")
4acc = np.zeros((40,3), np.float32); acc[:,2] = 9.81 # (T,3) m/s^2, IMU body frame (gravity incl.)
5gyr = np.zeros((40,3), np.float32) # (T,3) rad/s
6feat = enc.encode(acc, gyr) # (D,128) motion features
7out = enc.correct(acc, gyr) # corrected acc/gyr + per-axis covariance
8mot = enc.preintegrate(acc, gyr, dt=np.full(40,1/400.,np.float32)) # rel pose