Hilti 2022
Hilti SLAM Challenge 2022 / Hilti-Oxford (a hand-held survey pole walked through construction sites and Oxford’s Sheldonian Theatre).
Named for the year on purpose: the Hilti challenge datasets are NOT one family with one sensor suite. 2021 is a different rig entirely (Ouster OS0-64 + Livox MID70, IMUs on /imu, /imu_adis and /os_imu). 2023 ships two platforms: its hand-held one reuses these topic and frame names but runs the IMU at 200 Hz rather than ~400 Hz and carries its own calibration, while its robot platform is a RoboSense BPearl + Xsens MTi-670. The 2026 Hilti-Trimble challenge has no LiDAR in its bags at all. Anything other than 2022 wants its own profile, not a re-use of this one.
One monolithic ROS 1 bag per sequence: a Hesai PandarXT-32 lidar, a Sevensense Alphasense IMU, and five cameras. There is no /tf or /tf_static in the bags at all, so every sensor pose has to be fixed here.
base_link is the IMU, and that is not an arbitrary choice: the dataset’s own calibration/calibration_files/lidar_calibration.yaml declares the IMU as base_link at identity, and every ground-truth file is expressed in the IMU frame. Reporting in the IMU frame therefore lands the estimate in the reference’s own frame, with no offset to compose afterwards. The lidar sits at T_imu_pandar below, taken from that same file (translation [-0.001, -0.00855, 0.055], quaternion x,y,z,w [0.7071068, -0.7071068, 0, 0], i.e. a 5.6 cm lever arm).
Ground truth is worth reading before picking a sequence: only exp14_basement_2, exp16_attic_to_upper_gallery_2 and exp18_corridor_lower_gallery_2 ship a dense 6-DoF trajectory (~10 Hz). The other thirteen sequences ship surveyed control points – a handful of positions with a placeholder identity quaternion, not poses.
Running it
Online replay with the 3D GUI:
mola-lo-gui-hilti2022 /path/to/expNN_name.bag [additional flags]
Offline batch run, writing a trajectory file:
mola-lo-cli-hilti2022 /path/to/expNN_name.bag [additional flags]
What this profile sets, and why
These are defaults, not overrides: exporting any of these variables before running the wrapper takes precedence.
MOLA_LIDAR_TOPIC
Default: /hesai/pandar
MOLA_IMU_TOPIC
Default: /alphasense/imu
MOLA_CAMERA_TOPIC
Default: /alphasense/cam0/image_raw
MOLA_USE_FIXED_CAMERA_POSE
Default: 1
MOLA_USE_FIXED_IMU_POSE
Default: 1
MOLA_USE_FIXED_LIDAR_POSE
Default: 1
HILTI2022_BASE_FRAME
Default: imu
MOLA_TF_BASE_LINK
Default: imu
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
LIDAR_POSE_X
Default: -0.001
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
LIDAR_POSE_Y
Default: -0.00855
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
LIDAR_POSE_Z
Default: 0.055
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
LIDAR_POSE_YAW
Default: -90
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
LIDAR_POSE_PITCH
Default: 0
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
LIDAR_POSE_ROLL
Default: 180
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
IMU_POSE_X
Default: 0}" ; : "${IMU_POSE_Y:=0}" ; : "${IMU_POSE_Z:=0
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
IMU_POSE_YAW
Default: 0}" ; : "${IMU_POSE_PITCH:=0}" ; : "${IMU_POSE_ROLL:=0
T_imu_pandar, from the dataset’s lidar_calibration.yaml.
MOLA_TF_BASE_LINK
Default: lidar
T_pandar_imu, the inverse of the above.
LIDAR_POSE_X
Default: 0}" ; : "${LIDAR_POSE_Y:=0}" ; : "${LIDAR_POSE_Z:=0
T_pandar_imu, the inverse of the above.
LIDAR_POSE_YAW
Default: 0}" ; : "${LIDAR_POSE_PITCH:=0}" ; : "${LIDAR_POSE_ROLL:=0
T_pandar_imu, the inverse of the above.
IMU_POSE_X
Default: -0.00855
T_pandar_imu, the inverse of the above.
IMU_POSE_Y
Default: -0.001
T_pandar_imu, the inverse of the above.
IMU_POSE_Z
Default: 0.055
T_pandar_imu, the inverse of the above.
IMU_POSE_YAW
Default: -90
This rotation is its own inverse (R^T == R), hence the same angles as the imu branch above; only the translation changes.
IMU_POSE_PITCH
Default: 0
This rotation is its own inverse (R^T == R), hence the same angles as the imu branch above; only the translation changes.
IMU_POSE_ROLL
Default: 180
This rotation is its own inverse (R^T == R), hence the same angles as the imu branch above; only the translation changes.
MOLA_LO_INITIAL_LOCALIZATION_METHOD
Default: InitLocalization::PitchAndRollFromIMU
Hand-held rig, like conslam: larger and faster rotations than a vehicle, so lean on the IMU both for deskewing and for the initial pitch/roll. The clouds do carry genuine per-point timestamps (an f64 ‘timestamp’ field plus ‘ring’), so deskewing has real data to work with here.
MOLA_DESKEW_METHOD
Default: MotionCompensationMethod::IMU
Hand-held rig, like conslam: larger and faster rotations than a vehicle, so lean on the IMU both for deskewing and for the initial pitch/roll. The clouds do carry genuine per-point timestamps (an f64 ‘timestamp’ field plus ‘ring’), so deskewing has real data to work with here.
MOLA_LINK_FIRST_POSE_SIGMA
Default: 1e-6
No GNSS in this dataset: pin the first pose to the map origin, or the smoother’s GTSAM graph is left with a rank-deficient null-space (IndeterminantLinearSystemException). Same as conslam and botanicgarden.
Under the hood
Online launch file |
|
Offline CLI input |
|
Profile source |