Oxford Spires
Oxford Spires Dataset (https://dynamic.robots.ox.ac.uk/datasets/oxford-spires): a hand-held/backpack VILENS payload walked around Oxford colleges.
A sequence is a directory containing raw/ros2bag/, under which the recording may be split across several ros2bag part directories. All parts must be replayed, or the run silently covers only a fraction of the ground truth. Part directories end in “_<n>”; they are ordered by that number, not lexicographically, so a sequence with ten or more parts still replays in order.
There is no /tf or /tf_static in these bags, so fixed sensor poses are mandatory. lidar_odometry_from_oxford_spires.yaml carries the same values as its defaults.
Those poses are in the dataset’s BASE frame, NOT the raw LiDAR frame, and the difference is a 180 deg yaw. Getting that wrong – placing the LiDAR at identity, as if base and lidar were the same frame – leaves every reported pose a body yaw away from the dataset’s own ground truth. APE hides it (a body yaw moves position only by the 0.124 m lever arm, and evo’s –align absorbs the rest); it negates the horizontal part of every RELATIVE motion, so vertical-drift and tilt metrics blow up. Symptom if it ever comes back: relative vertical drift in the tens-to-hundreds of mm/m on a run whose APE looks perfectly good.
T_base_lidar is sensor.yaml’s own value. T_base_imu is the LiDAR-frame IMU pose composed through it (T_base_lidar . T_lidar_imu), which reproduces sensor.yaml’s independently recorded T_base_imu to ~1 mm and 0.6 deg, so the two calibrations agree.
Number of OXFORD_SPIRES_BAG_N slots the launch YAML defines:
Running it
Online replay with the 3D GUI:
mola-lo-gui-oxford-spires /path/to/data/sequences/<sequence-name>/ [--headless] [additional flags]
Offline batch run, writing a trajectory file:
mola-lo-cli-oxford-spires /path/to/data/sequences/<sequence-name>/ [--headless] [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_driver_ros/imu
MOLA_CAMERA_TOPIC
Default: /alphasense_driver_ros/cam0/debayered/image/compressed
MOLA_TF_BASE_LINK
Default: base_link
LIDAR_POSE_X
Default: 0}" ; : "${LIDAR_POSE_Y:=0}" ; : "${LIDAR_POSE_Z:=0.124
LIDAR_POSE_YAW
Default: 180}" ; : "${LIDAR_POSE_PITCH:=0}" ; : "${LIDAR_POSE_ROLL:=0
MOLA_USE_FIXED_LIDAR_POSE
Default: true
IMU_POSE_X
Default: -0.018771
IMU_POSE_Y
Default: 0.008218
IMU_POSE_Z
Default: 0.053526
IMU_POSE_YAW
Default: 89.3737
IMU_POSE_PITCH
Default: -0.1665
IMU_POSE_ROLL
Default: -0.1287
MOLA_USE_FIXED_IMU_POSE
Default: true
MOLA_LO_INITIAL_LOCALIZATION_METHOD
Default: InitLocalization::PitchAndRollFromIMU
Handheld/backpack platform: lean on the IMU for the initial pitch/roll estimate and for deskewing, same as the ConSLAM wrapper. The Alphasense IMU does not publish an onboard-fused orientation (its Imu messages carry an all-zero quaternion), so the pitch/roll initializer automatically falls back to leveling from raw accelerometer readings.
MOLA_DESKEW_METHOD
Default: MotionCompensationMethod::IMU
Handheld/backpack platform: lean on the IMU for the initial pitch/roll estimate and for deskewing, same as the ConSLAM wrapper. The Alphasense IMU does not publish an onboard-fused orientation (its Imu messages carry an all-zero quaternion), so the pitch/roll initializer automatically falls back to leveling from raw accelerometer readings.
MOLA_DESKEW_IGNORE_ACCELEROMETER
Default: false
Keep the accelerometer in the deskew. This used to be suppressed, on evidence that gyro-only deskew cut path-length error and improved APE. Re-measured on all 13 sequences against today’s pipeline, both halves of that are gone: est/gt is identical to three decimals either way, and suppressing the accelerometer now COSTS about 11% of APE (median 0.886x in its favour, better on 9 of 13). The defect it compensated for has since been fixed elsewhere, so the override no longer earns its keep. Left explicit rather than deleted so the measurement is not lost.
MOLA_CLOUD_DECIMATION_VOXEL_SIZE_MAP
Default: 0.45
GICP-pipeline decimation tuning – per-dataset, not a shipped pipeline default. See the KITTI profile for the shared rationale/evidence; this dataset independently confirmed the same configuration (56% cut in pooled vertical drift at a third of the cost, 12-13/13 sequences).
MOLA_CLOUD_DECIMATION_VOXEL_SIZE_ICP
Default: 0.45
GICP-pipeline decimation tuning – per-dataset, not a shipped pipeline default. See the KITTI profile for the shared rationale/evidence; this dataset independently confirmed the same configuration (56% cut in pooled vertical drift at a third of the cost, 12-13/13 sequences).
MOLA_VOXEL_STRIDE_MAP
Default: 1
GICP-pipeline decimation tuning – per-dataset, not a shipped pipeline default. See the KITTI profile for the shared rationale/evidence; this dataset independently confirmed the same configuration (56% cut in pooled vertical drift at a third of the cost, 12-13/13 sequences).
MOLA_VOXEL_STRIDE_ICP
Default: 2
GICP-pipeline decimation tuning – per-dataset, not a shipped pipeline default. See the KITTI profile for the shared rationale/evidence; this dataset independently confirmed the same configuration (56% cut in pooled vertical drift at a third of the cost, 12-13/13 sequences).
MOLA_LOCALMAP_K_CORRESPONDENCES_FOR_COV
Default: 10
GICP-pipeline decimation tuning – per-dataset, not a shipped pipeline default. See the KITTI profile for the shared rationale/evidence; this dataset independently confirmed the same configuration (56% cut in pooled vertical drift at a third of the cost, 12-13/13 sequences).
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):
MOLA_SMOOTHER_SIGMA_REL_POSE_LIN
Default: 0.1
Smoother-only relative-pose prior floor (no-op for `simple`), same values as KITTI. Measured over all 13 sequences it costs nothing here (0.96x vs the unfloored smoother, 10/13 improving) and beats `simple` overall (1.06x vs 1.11x unfloored): well-conditioned geometry doesn’t need the unfloored prior’s ICP-pinning the way degenerate scenes do, so raising the floor is close to free. See the KITTI profile for the fuller case.
MOLA_SMOOTHER_SIGMA_REL_POSE_ANG
Default: 0.02
Smoother-only relative-pose prior floor (no-op for `simple`), same values as KITTI. Measured over all 13 sequences it costs nothing here (0.96x vs the unfloored smoother, 10/13 improving) and beats `simple` overall (1.06x vs 1.11x unfloored): well-conditioned geometry doesn’t need the unfloored prior’s ICP-pinning the way degenerate scenes do, so raising the floor is close to free. See the KITTI profile for the fuller case.
Under the hood
Online launch file |
|
Offline CLI input |
|
Profile source |