Configuration¶
All parameters live in config/far-lio.yml.
The compose setup bind-mounts the config/ directory into the container at /config and both
nodes are started with --params-file /config/far-lio.yml, so you can edit the file on the host
and simply restart — no rebuild needed.
The file has one block per node, both under the /core/state namespace:
LidarOdometry— the CUDA GICP odometry node.StateEstimation— the 3D-EKF backend.
Running on a new bag¶
At minimum you must point FAR-LIO at the topics in your bag and set the frames that match your sensor setup.
Topics¶
| Node | Parameter | Type | Meaning |
|---|---|---|---|
LidarOdometry |
node.input_pointcloud |
sensor_msgs/PointCloud2 |
LiDAR point-cloud topic to register. Required. |
StateEstimation |
inputs.imus.primary.message.topic |
sensor_msgs/Imu |
IMU topic fused in the EKF. Required. |
LidarOdometry |
node.output_odom |
nav_msgs/Odometry |
Odometry output topic (default lidar_odometry; the EKF subscribes to it — usually leave as is). |
/core/state:
LidarOdometry:
ros__parameters:
node:
input_pointcloud: "/sensor/lidar/points" # <- your PointCloud2 topic
StateEstimation:
ros__parameters:
inputs:
imus:
primary:
message:
topic: "/sensor/imu/data" # <- your Imu topic
Frames¶
The state estimation operates in the robots base link, so child_frame and
odom_frame are assumed fixed — leave them at their defaults. You only need to set
cloud_frame to match your sensor.
| Parameter | Meaning |
|---|---|
node.cloud_frame |
Set this to the frame_id of your LiDAR PointCloud2. The node blocks until the static transform cloud_frame → child_frame is available on /tf_static and transforms each incoming cloud before registration. |
node.child_frame |
Base frame the estimator works in (base_link). Do not change. |
node.odom_frame |
Fixed world/odometry frame the pose is published in (local_cartesian). Do not change. |
/core/state:
LidarOdometry:
ros__parameters:
node:
odom_frame: "local_cartesian" # keep
child_frame: "base_link" # keep
cloud_frame: "lidar_link" # <- set to your PointCloud2 frame_id
wait_tf: false
Important
FAR-LIO needs the static transform from cloud_frame to base_link (on /tf_static) to
place the LiDAR relative to the vehicle, so your bag must contain it. Find a cloud's
frame with ros2 topic echo --field header.frame_id <pointcloud_topic>. If the bag has no
suitable /tf_static, you can inject one — e.g. with
kappe.
Odometry vs. localization mode¶
LidarOdometry can either build a map online or localize against a prior map:
| Parameter | Effect |
|---|---|
pipeline.update_map: true |
Odometry mode — builds and continuously updates a local map (start at the origin). |
pipeline.update_map: false + node.input_map |
Localization mode — loads a prior map from the given folder (containing map.pcd and origin.yml) and localizes against it. |
Other useful parameters¶
| Parameter | Default | Description |
|---|---|---|
use_sim_time |
true |
Use /clock (required for bag playback; run.sh plays bags with --clock). Set false for live sensors. |
map.voxel_size |
4.0 |
Voxel edge length of the cuVoxelMap (m). |
map.max_distance |
1000.0 |
Voxels farther than this from the current pose are pruned (m). |
registration.max_time |
200.0 |
Per-scan registration time budget (ms). |
registration.convergence_criterion |
5.0e-3 |
GICP convergence threshold on the pose update. |
preprocessing.crop_range |
[0.0] |
[min, max] range crop in m (disabled unless size 2). |
preprocessing.crop_footprint |
[0.0] |
[longitudinal, lateral] vehicle-body crop in m (disabled unless size 2). |