Skip to content

Commit 16daab6

Browse files
committed
Support initialization from state estimator
1 parent 054944b commit 16daab6

12 files changed

Lines changed: 441 additions & 191 deletions

docs/mola_lo_ros_node.rst

Lines changed: 92 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -119,29 +119,29 @@ runs **MOLA-LO** live on point clouds received from a ROS 2 topic, **demonstrati
119119
$ ros2 launch mola_lidar_odometry ros2-lidar-odometry.launch.py --show-args
120120
Arguments (pass arguments as '<name>:=<value>'):
121121
122-
'namespace':
123-
Top-level namespace
124-
(default: '')
122+
'namespace':
123+
Top-level namespace
124+
(default: '')
125125
126-
'use_namespace':
127-
Whether to apply a namespace to the navigation stack
128-
(default: 'false')
126+
'use_namespace':
127+
Whether to apply a namespace to the navigation stack
128+
(default: 'false')
129129
130-
'enforce_planar_motion':
131-
Whether to enforce z, pitch, and roll to be zero.
132-
(default: 'False')
130+
'enforce_planar_motion':
131+
Whether to enforce z, pitch, and roll to be zero.
132+
(default: 'False')
133133
134-
'forward_ros_tf_odom_to_mola':
135-
Whether to import an existing /tf 'odom'->'base_link' odometry into the MOLA subsystem.
136-
(default: 'False')
134+
'forward_ros_tf_odom_to_mola':
135+
Whether to import an existing /tf 'odom'->'base_link' odometry.
136+
(default: 'False')
137137
138-
'generate_simplemap':
139-
Whether to create a '.simplemap', useful for map post-processing. Refer to online tutorials.
140-
(default: 'False')
138+
'generate_simplemap':
139+
Whether to create a '.simplemap'
140+
(default: 'False')
141141
142-
'gnss_topic_name':
143-
Topic name to listen for NavSatFix input from a GNSS (for example '/gps')
144-
(default: 'gps')
142+
'gnss_topic_name':
143+
Topic name to listen for NavSatFix input from a GNSS (for example '/gps')
144+
(default: 'gps')
145145
146146
'gpsfix_topic_name':
147147
Topic name to listen for gps_msgs/GPSFix input from a GNSS (for example '/gpsfix')
@@ -151,24 +151,24 @@ runs **MOLA-LO** live on point clouds received from a ROS 2 topic, **demonstrati
151151
If true, the IMU pose will be assumed to be at the origin (base_link). Set to false (default) if you want to read the actual sensor pose from /tf
152152
(default: 'false')
153153
154-
'ignore_lidar_pose_from_tf':
155-
If true, the LiDAR pose will be assumed to be at the origin (base_link). Set to false (default) if you want to read the actual sensor pose from /tf
156-
(default: 'false')
154+
'ignore_lidar_pose_from_tf':
155+
If true, the LiDAR pose will be assumed to be at the origin (base_link). Set to false (default) if you want to read the actual sensor pose from /tf
156+
(default: 'false')
157157
158-
'imu_topic_name':
159-
Topic name to listen for Imu input (for example '/imu')
160-
(default: 'imu')
158+
'imu_topic_name':
159+
Topic name to listen for Imu input (for example '/imu')
160+
(default: 'imu')
161161
162-
'initial_localization_method':
163-
What method to use for initialization. See https://docs.mola-slam.org/latest/ros2api.html#initial-localization
164-
(default: 'InitLocalization::FixedPose')
162+
'initial_localization_method':
163+
Method for initialization.
164+
(default: 'InitLocalization::FixedPose')
165165
166-
'lidar_scan_validity_minimum_point_count':
167-
Minimum number of points in each LiDAR raw scan for it to be considered valid; otherwise, it is ignored.
168-
(default: '100')
166+
'lidar_scan_validity_minimum_point_count':
167+
Minimum number of points in each LiDAR raw scan for it to be considered valid; otherwise, it is ignored.
168+
(default: '100')
169169
170-
'lidar_topic_name':
171-
Topic name to listen for PointCloud2 input from the LiDAR (for example '/ouster/points')
170+
'lidar_topic_name':
171+
Topic name to listen for PointCloud2 input from the LiDAR (for example '/ouster/points')
172172
173173
'lidar_topic_type':
174174
The type of LiDAR topic to subscribe to. Options: 'PointCloud2' (default) or 'LaserScan'
@@ -178,65 +178,81 @@ runs **MOLA-LO** live on point clouds received from a ROS 2 topic, **demonstrati
178178
Which motion-compensation method to use to align LiDAR scans more precisely
179179
(default: 'MotionCompensationMethod::Linear')
180180
181-
'mola_footprint_to_base_link_tf':
182-
Can be used to define a custom transformation between base_footprint and base_link. The coordinates are [x, y, z, yaw_deg, pitch_deg, roll_deg].
183-
(default: '[0, 0, 0, 0, 0, 0]')
181+
'mola_footprint_to_base_link_tf':
182+
Can be used to define a custom transformation between base_footprint and base_link. The coordinates are [x, y, z, yaw_deg, pitch_deg, roll_deg].
183+
(default: '[0, 0, 0, 0, 0, 0]')
184+
185+
'mola_initial_map_mm_file':
186+
Can be used to provide a metric map '.mm' file to be loaded as initial map. Refer to online tutorials.
187+
(default: '""')
188+
189+
'mola_initial_map_sm_file':
190+
Initial keyframes map '.simplemap' file.
191+
(default: '""')
192+
193+
'mola_lo_pipeline':
194+
The LiDAR-Odometry pipeline configuration YAML file defining the LO system.
195+
(default: '../pipelines/lidar3d-default.yaml')
184196
185-
'mola_initial_map_mm_file':
186-
Can be used to provide a metric map '.mm' file to be loaded as initial map. Refer to online tutorials.
187-
(default: '""')
197+
'mola_lo_reference_frame':
198+
The /tf frame name to be used for MOLA-LO localization updates
199+
(default: 'map')
188200
189-
'mola_initial_map_sm_file':
190-
Can be used to provide a keyframes map '.simplemap' file to be loaded as initial map. Refer to online tutorials.
191-
(default: '""')
201+
'mola_state_estimator_reference_frame':
202+
The /tf frame name to be used as reference for MOLA State Estimators to publish pose updates
203+
(default: 'map')
192204
193-
'mola_lo_pipeline':
194-
The LiDAR-Odometry pipeline configuration YAML file defining the LO system. Absolute path, or relative to 'mola-cli-launchs/lidar_odometry_ros2.yaml'. Default is the 'lidar3d-default.yaml' system described in the IJRR 2025 paper.
195-
(default: '../pipelines/lidar3d-default.yaml')
205+
'mola_tf_base_link':
206+
The /tf frame name for the robot base link.
207+
(default: 'base_link')
196208
197-
'mola_lo_reference_frame':
198-
The /tf frame name to be used for MOLA-LO localization updates
199-
(default: 'map')
209+
'publish_localization_following_rep105':
210+
Whether to publish localization TFs in between map->odom (true) or directly map->base_link (false)
211+
(default: 'True')
200212
201-
'mola_state_estimator_reference_frame':
202-
The /tf frame name to be used as reference for MOLA State Estimators to publish pose updates
203-
(default: 'map')
213+
'start_active':
214+
Whether MOLA-LO should start active, that is, processing incoming sensor data (true), or ignoring them (false)
215+
(default: 'True')
204216
205-
'mola_tf_base_link':
206-
The /tf frame name for the robot base link.
207-
(default: 'base_link')
217+
'start_mapping_enabled':
218+
Whether MOLA-LO should start with map update enabled (true), or in localization-only mode (false)
219+
(default: 'True')
208220
209-
'publish_localization_following_rep105':
210-
Whether to publish localization TFs in between map->odom (true) or directly map->base_link (false)
211-
(default: 'True')
221+
'use_mola_gui':
222+
Whether to open MolaViz GUI interface for watching live mapping and control UI
223+
(default: 'True')
212224
213-
'start_active':
214-
Whether MOLA-LO should start active, that is, processing incoming sensor data (true), or ignoring them (false)
215-
(default: 'True')
225+
'use_rviz':
226+
Whether to launch RViz2 with default lidar-odometry.rviz configuration
227+
(default: 'True')
216228
217-
'start_mapping_enabled':
218-
Whether MOLA-LO should start with map update enabled (true), or in localization-only mode (false)
219-
(default: 'True')
229+
'use_state_estimator':
230+
If true, uses StateEstimationSmoother (requires optional package).
231+
(default: 'False')
220232
221-
'state_estimator_config_yaml':
222-
A YAML file with settings for the state estimator. Absolute path or relative to 'mola-cli-launchs/lidar_odometry_ros2.yaml'
223-
(default: PythonExpr(''../state-estimator-params/state-estimation-smoother.yaml' if ' + LaunchConfig('use_state_estimator') + ' else '../state-estimator-params/state-estimation-simple.yaml''))
233+
'navstate_kinematic_model':
234+
[Smoother only] Kinematic model for internal motion model factors. Options: KinematicModel::ConstantVelocity, KinematicModel::Tricycle.
235+
(default: 'KinematicModel::ConstantVelocity')
224236
225-
'use_mola_gui':
226-
Whether to open MolaViz GUI interface for watching live mapping and control UI
227-
(default: 'True')
237+
'navstate_sliding_window_sec':
238+
[Smoother only] Time window to keep past observations in the filter [seconds].
239+
(default: '2.5')
228240
229-
'use_rviz':
230-
Whether to launch RViz2 with default lidar-odometry.rviz configuration
231-
(default: 'True')
241+
'navstate_sigma_random_walk_linacc':
242+
[Smoother only] Random walk model for linear acceleration uncertainty [m/s²].
243+
(default: '1.0')
232244
233-
'use_state_estimator':
234-
If false, the basic state estimator 'mola::state_estimation_simple::StateEstimationSimple' will be used. If true, 'mola::state_estimation_smoother::StateEstimationSmoother' is used instead.
235-
(default: 'False')
245+
'navstate_sigma_random_walk_angacc':
246+
[Smoother only] Random walk angular acceleration uncertainty [rad/s²].
247+
(default: '10.0')
236248
237-
'state_estimator_config_yaml':
238-
A YAML file with settings for the state estimator. Absolute path or relative to 'mola-cli-launchs/lidar_odometry_ros2.yaml'
249+
'estimate_geo_reference':
250+
[Smoother only] Whether to estimate the best geo-referencing for {enu} -> {map} from incoming GNSS readings.
251+
(default: 'False')
239252
253+
'state_estimator_config_yaml':
254+
Path to estimator YAML. If empty, it is auto-resolved based on use_state_estimator.
255+
(default: '')
240256
241257
.. _mola_lo_ros_mola-cli-env-vars:
242258

module/include/mola_lidar_odometry/LidarOdometry.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,18 @@ class LidarOdometry : public mola::FrontEndBase,
436436
/// If provided by the IMU, prefer gravity-aligned orientation from the sensor instead of accelerometer data.
437437
bool use_imu_orientation = true;
438438

439+
/// Maximum position sigma (m) to accept state estimator as converged
440+
/// Used when method == FromStateEstimator
441+
double from_state_estimator_max_position_sigma = 0.5; // [m]
442+
443+
/// Maximum orientation sigma (deg) to accept state estimator as converged
444+
/// Used when method == FromStateEstimator
445+
double from_state_estimator_max_orientation_sigma_deg = 3.0; // [deg]
446+
447+
/// Timeout (seconds) waiting for state estimator to converge
448+
/// If <=0, wait indefinitely
449+
double from_state_estimator_timeout = 60.0; // [s]
450+
439451
void initialize(const Yaml & c);
440452
};
441453

@@ -673,6 +685,12 @@ class LidarOdometry : public mola::FrontEndBase,
673685
std::optional<mrpt::Clock::time_point> last_obs_timestamp;
674686
std::optional<mrpt::Clock::time_point> last_icp_timestamp;
675687

688+
/// Timestamp when we started waiting for state estimator convergence
689+
std::optional<mrpt::Clock::time_point> waiting_for_state_estimator_since;
690+
691+
/// Received georeferencing from external state estimator
692+
std::optional<mola::Georeferencing> external_georef;
693+
676694
/// Cache for multiple LIDAR synchronization:
677695
std::map<std::string /*label*/, mrpt::obs::CObservation::ConstPtr> sync_obs;
678696

@@ -901,6 +919,9 @@ class LidarOdometry : public mola::FrontEndBase,
901919

902920
void doRemoveCloudsWithDecay();
903921

922+
void onExternalMapUpdate(const MapSourceBase::MapUpdate & mu);
923+
void onExternalLocalizationUpdate(const LocalizationSourceBase::LocalizationUpdate & lu);
924+
904925
void doPublishUpdatedLocalization(const mrpt::Clock::time_point & this_obs_tim);
905926

906927
void doPublishUpdatedLocalMap(const mrpt::Clock::time_point & this_obs_tim);
@@ -916,6 +937,9 @@ class LidarOdometry : public mola::FrontEndBase,
916937

917938
void onPublishDiagnostics();
918939
void handleInitialLocalization();
940+
void handleInitialLocalizationStateEstimation();
941+
void handleInitialLocalizationDoInitFromPose(
942+
const mrpt::poses::CPose3DPDFGaussian & initPose, bool resetStateEstimator);
919943

920944
bool isPipelineUsingIMU() const;
921945
void sendLidarScanToProcessQueue(const CObservation::ConstPtr & o);

module/src/LidarOdometry_GUI.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ void LidarOdometry::internalBuildGUI_Legacy()
459459

460460
void LidarOdometry::doRemoveCloudsWithDecay()
461461
{
462+
// Remove possible old 3D objects if the user disabled visualization on the fly:
462463
if (visualizer_) {
463464
visualizer_->clear_all_point_clouds_with_decay();
464465
}

0 commit comments

Comments
 (0)