HomeNDT Scan Matcher
Core Modules

NDT Scan Matcher

NDT Scan Matcher

NDT (Normal Distributions Transform) Scan Matcher is the primary absolute localization algorithm in Autoware. It divides the pre-built 3D point cloud map (PCD Map) into voxel grids and computes the normal distribution (mean vector and covariance matrix) for points within each voxel. At runtime, the algorithm finds a rigid body transformation that maximizes the probability of current LiDAR scan points falling within the map voxel distributions.

NDT Algorithm Visualization

NDT Voxel Grid and Gaussian Distribution Alignment Visualization

Algorithm Flow

100%

No

Yes

Timeout / Too Close

Valid

No

Yes

No

Yes

LiDAR PointCloud2
Received

Map Loaded?

Request Map via
pcd_loader_service

Get Initial Pose
from SmartPoseBuffer
(EKF interpolation)

Sensor Points
Valid?

Skip & Publish
Diagnostics Warning

Voxel Grid
Downsampling

Transform Points
sensor_frame → base_link

NDT Alignment
(pclomp::MultiGridNDT)
Newton Optimization

Converged?
Score > Threshold?

Publish Warning
Diagnostics

Result Distance
< Tolerance?

Reject: Initial-to-Result
Distance Too Large

Estimate Covariance
(Fixed / Laplace / Multi-NDT)

Publish ndt_pose_with_covariance
+ Debug Topics

NDT Scan Matcher Complete Runtime Flow

NDT Mathematical Principles

Info

Score = Σᵢ exp(-½ (xᵢ - μⱼ)ᵀ Σⱼ⁻¹ (xᵢ - μⱼ)) — where xᵢ is the transformed scan point, μⱼ and Σⱼ are the mean and covariance of the containing voxel. Optimization uses Newton's method for iterative pose updates.

ROS 2 Interfaces

Subscribers

TopicMessage TypeDescription
ekf_pose_with_covariancePoseWithCovarianceStampedEKF predicted pose, used as NDT optimization initial value
points_rawPointCloud2LiDAR raw point cloud
regularization_pose_with_covariancePoseWithCovarianceStampedOptional GNSS regularization pose

Publishers

TopicMessage TypeDescription
ndt_posePoseStampedNDT estimated pose
ndt_pose_with_covariancePoseWithCovarianceStampedNDT estimated pose (with covariance)
points_alignedPointCloud2Aligned point cloud (for debugging)
transform_probabilityFloat32StampedMatching score
iteration_numInt32StampedNumber of iterations
initial_to_result_distanceFloat32StampedDistance from initial to result
exe_time_msFloat32StampedExecution time (milliseconds)

Services

ServiceTypeDescription
ndt_align_srvPoseWithCovarianceStampedMonte Carlo initial pose estimation
trigger_node_srvSetBoolActivate/deactivate node

Key Parameters

ParameterDefaultDescriptionPort Tuning Suggestion
resolution2.0 mNDT voxel grid resolutionOpen areas 3.0m, dense areas 1.5m
max_iterations30Maximum iterationsFrequent ceiling hits indicate poor initial pose
trans_epsilon0.01Convergence thresholdUsually no modification needed
num_threads4Parallel thread countAdjust based on CPU core count
converged_param_type1 (NVTL)Score evaluation methodKeep NVTL unchanged
converged_param_nearest_voxel_transformation_likelihood2.3NVTL convergence thresholdAdjust based on field test data
initial_to_result_distance_tolerance_m3.0 mMax distance from initial to resultTighten for repetitive scenarios
particles_num200Monte Carlo particle countIncrease to 500 for repetitive scenarios
dynamic_map_loading.update_distance20.0 mTravel distance to trigger map updateAdjust based on site size
dynamic_map_loading.map_radius150.0 mMap loading radiusKeep larger than effective LiDAR range

Source Code Reading Order

  1. config/ndt_scan_matcher.param.yaml — Understand all configurable parameters
  2. src/ndt_scan_matcher_core.cpp constructor — Node initialization
  3. callback_sensor_points_main — Main runtime path
  4. service_ndt_align_main + align_pose — Initialization service
  5. estimate_covariance — Covariance estimation strategy
  6. map_update_module.cpp — Dynamic map loading
  7. particle.cpp + ndt_omp/* — Underlying optimization implementation