struct mola::LidarOdometry::Parameters
Overview
#include <LidarOdometry.h> struct Parameters: public mp2p_icp::Parameterizable { // structs struct AdaptiveThreshold; struct Diagnostics; struct ICP_case; struct IMUGravityCorrection; struct InitialLocalizationOptions; struct MapUpdateOptions; struct MultipleLidarOptions; struct ObservationValidityChecks; struct SimpleMapOptions; struct TraceOutputOptions; struct TrajectoryOutputOptions; struct Visualization; // fields std::vector<std::regex> lidar_sensor_labels; std::optional<std::regex> imu_sensor_label; std::optional<std::regex> gnss_sensor_label; double min_time_between_scans = 0.05; double observation_radius_filter_coefficient = 0.999; double absolute_minimum_observation_radius = 5.0; double observation_radius_quantile = 1.0; uint32_t observation_radius_quantile_max_samples = 8000; bool optimize_twist = false; double optimize_twist_rerun_min_trans = 0.1; double optimize_twist_rerun_min_rot_deg = 0.5; size_t optimize_twist_max_corrections = 8; MultipleLidarOptions multiple_lidars; MapUpdateOptions local_map_updates; double min_icp_goodness = 0.4; std::optional<double> write_debug_icp_log_if_quality_under; bool pipeline_profiler_enabled = false; bool icp_profiler_enabled = false; bool icp_profiler_full_history = false; Visualization visualization; AdaptiveThreshold adaptive_threshold; Diagnostics diagnostics; std::map<AlignKind, ICP_case> icp; SimpleMapOptions simplemap; bool drop_stale_scans = true; TrajectoryOutputOptions estimated_trajectory; TraceOutputOptions debug_traces; InitialLocalizationOptions initial_localization; ObservationValidityChecks observation_validity_checks; IMUGravityCorrection imu_gravity_correction; bool start_active = true; uint32_t max_lidar_queue_before_drop = 15; double max_time_to_wait_for_imu = 0.5; uint32_t gnss_queue_max_size = 100; double min_motion_model_xyz_cov_inv = 1.0; std::string publish_reference_frame = "odom"; std::string publish_vehicle_frame = "base_link"; bool publish_deskewed_scans = false; // methods void load_keyframe_policy(mola::KeyframeDecisionOptions& o, const Yaml& cfg, const char* section_name, bool distances_required); };
Fields
std::vector<std::regex> lidar_sensor_labels
List of sensor labels or regex’s to be matched to input observations to be used as raw lidar observations.
std::optional<std::regex> imu_sensor_label
Sensor labels or regex to be matched to input observations to be used as raw IMU observations.
std::optional<std::regex> gnss_sensor_label
Sensor labels or regex to be matched to input observations to be used as GNSS (GPS) observations.
double min_time_between_scans = 0.05
Minimum time (seconds) between scans for being attempted to be aligned. Scans faster than this rate will be just silently ignored.
double observation_radius_quantile = 1.0
Quantile of the per-point norms used as ESTIMATED_OBSERVATION_RADIUS, in (0, 1]. 1.0 means the bounding-box max-norm, which is what this estimate has always been and remains the default.
The max-norm is an outlier statistic, not a scene scale: one far return sets it. Measured on three lidars recorded simultaneously in one room, it reads 13.8, 18.0 and 101.8 m a 7.4x disagreement about a fixed scene while across every outdoor sequence measured it spans only 69.8-91.2 m. Six shipped parameters are derived from it (range_min, range_max, the keyframe distances, the local-map extent), so an estimate with that failure mode has almost no leverage where tuning is needed and a great deal of spurious leverage where it is not.
A quantile below 1.0 (0.98 is a reasonable choice) reads the same on scenes whose returns really do reach that far, and stops one stray return from setting the scale of a room.
uint32_t observation_radius_quantile_max_samples = 8000
Cap on how many points are sampled to evaluate observation_radius_quantile. The quantile needs a distribution, not every point; a strided sample of a few thousand from a 60k-point scan settles it to well under a metre, and keeps this O(sample) rather than O(scan) on every frame. Ignored when the quantile is 1.0.
bool optimize_twist = false
If enabled (slower), vehicle twist will be optimized during ICP enabling better and more robust odometry in high dynamics motion.
double min_icp_goodness = 0.4
Minimum ICP “goodness” (in the range [0,1]) for a new KeyFrame to be accepted during regular lidar odometry & mapping
std::optional<double> write_debug_icp_log_if_quality_under
If defined, .icplog files will be saved if ICP quality drops below the given threshold
bool drop_stale_scans = true
When a new scan arrives while the worker is still busy, the default is to keep only the freshest one. That is the right behavior on a robot, where a stale scan is worth less than keeping up with the world, and the wrong one for an offline batch run, whose whole point is that every scan gets processed and the result is reproducible: how many scans are dropped then depends on the replay rate and on whatever else the machine happens to be doing, so two runs over the same data are not comparable.
Setting this to false makes the producer block until the worker is free, instead of the queue evicting the older scan. The replay is then lossless at any replay rate. Nothing else changes: the pipeline itself is untouched, and the run simply takes as long as it takes.
uint32_t max_lidar_queue_before_drop = 15
Under overload, incoming scans are processed with a “drop stale, keep freshest” policy: the single worker thread always advances to the newest ready scan, dropping older ones, so latency stays near one processing period regardless of this value. This parameter only bounds the auxiliary wait list used while a scan waits for its IMU data (IMU de-skew pipelines): if IMU delivery lags, no more than this many scans are kept waiting before the oldest are dropped.
double max_time_to_wait_for_imu = 0.5
How long [s] a LiDAR scan may be held waiting for the IMU data covering its time span before it is processed without it. Measured in sensor time: the newest timestamp received on any input, not the wall clock, so a given input always yields the same trajectory whatever the machine load, offline or online.
Without this bound, an IMU that stops mid-run stalls the odometry permanently, since the scans behind it never become ready. With it, the odometry degrades to LiDAR-only after the timeout and recovers by itself when IMU data comes back. Set to 0 to disable and wait indefinitely.
double min_motion_model_xyz_cov_inv = 1.0
Minimum inverse covariance in (X,Y,Z) for a valid motion model.
std::string publish_reference_frame = "odom"
When publishing pose updates, the reference frame for both, estimated robot poses, and the local map.
std::string publish_vehicle_frame = "base_link"
When publishing pose updates, the vehicle frame name.
Methods
void load_keyframe_policy( mola::KeyframeDecisionOptions& o, const Yaml& cfg, const char* section_name, bool distances_required )
Loads the keyframe-creation policy shared by the local-map and simplemap sections. Lives here, and not in KeyframeDecisionOptions itself, because the two distance thresholds may be formulas and must register into THIS object’s dynamic-parameter pool.
Parameters:
section_name |
Only used in error messages. |
distances_required |
Whether the two distance thresholds must be present in the YAML. Kept per-section for backwards compatibility: the local-map section demands them, the simplemap one defaults them. |