Choosing a Point-Cloud Registration Method: ICP, NDT & Global

Point-cloud registration is where a pipeline either aligns two LiDAR scans to centimetres or silently converges to a plausible-looking wrong answer — and the difference is almost always method selection, not tuning. This decision guide, part of the sensor fusion and spatial data alignment domain, frames the choice between iterative closest point (ICP), the normal distributions transform (NDT), and a global feature-based pass. The selection is driven by two questions — how good is the initial pose, and how dense is the scan — against a hard ≤0.05 m RMSE alignment budget. The concrete implementations are covered in point cloud registration techniques; this page decides which to run.

Registration method follows from initial-pose quality and scan density:

Point-Cloud Registration Method Decision Flow Top box is two point clouds. Arrow to a diamond asking if a good initial pose exists. A no branch goes right to a global FPFH plus RANSAC box. A yes branch goes down to a second diamond asking if the scan is dense and structured. Its yes branch goes to point-to-plane ICP; its no branch goes to NDT. The global box feeds down into the second diamond. A gate at the bottom checks fitness and RMSE. Two point clouds source · target Good initial pose? within basin no Global FPFH+RANSAC coarse from scratch yes Dense & structured? planar surfaces yes Point-to-plane ICP no NDT gate: fitness · RMSE ≤ 0.05 m

Method Overview #

The three methods occupy different niches along the axes of initial-pose tolerance and scan density:

Method Needs initial guess Scan density Compute Best fit
Point-to-plane ICP Yes (local) Dense, structured Low per iteration Refinement on planar AV scenes
NDT Moderate (local) Sparse tolerant Medium (voxel grid) Sparse/noisy scans, moderate error
Global FPFH+RANSAC No Any with features High (features + RANSAC) Coarse alignment from scratch

ICP and NDT are refiners — they need a starting pose in the basin of convergence. The global pass is the only method that works with no prior, but it is coarse and always followed by a local refinement. The practical pipeline is: global pass when the prior is bad, then ICP on dense structured scans or NDT on sparse ones.

Decision Criteria #

Criterion 1 — Is the initial pose inside the basin of convergence? #

A local method only works if the starting transform is close enough. Estimate the initial error from odometry or a pose prior; if the rotation or translation exceeds the convergence radius, a global pass is mandatory.

python
import numpy as np

def needs_global(init_T: np.ndarray, rot_limit_deg=15.0, trans_limit_m=2.0) -> bool:
    """True if the initial guess is likely outside the local basin."""
    R = init_T[:3, :3]
    angle = np.degrees(np.arccos(np.clip((np.trace(R) - 1) / 2, -1, 1)))
    trans = np.linalg.norm(init_T[:3, 3])
    return angle > rot_limit_deg or trans > trans_limit_m

Key parameters: rot_limit_deg and trans_limit_m bound the local basin; beyond them, seed with global registration using FPFH features and RANSAC.

Criterion 2 — Scan density and structure select the refiner #

Dense, planar scenes favour point-to-plane ICP; sparse or noisy scans favour NDT's distribution model. Estimate density from the average nearest-neighbour spacing.

python
from scipy.spatial import cKDTree

def choose_refiner(points: np.ndarray, spacing_thresh=0.3) -> str:
    d, _ = cKDTree(points).query(points[::50], k=2)
    mean_spacing = float(d[:, 1].mean())
    return "icp" if mean_spacing < spacing_thresh else "ndt"

Key parameter: spacing_thresh (0.3 m) splits dense from sparse; below it ICP has enough correspondences, above it NDT is more robust.

Criterion 3 — Compute budget #

ICP is cheapest per iteration but needs a good start; NDT costs a voxel grid build; the global pass is the most expensive. Run the global pass only when Criterion 1 demands it, and prefer ICP over NDT when density allows, to keep per-scan cost low at map scale.

Validation & QC Automation #

Every method's output is validated the same way, against the alignment budget:

  • Inlier RMSE ≤0.05 m on correspondences within the search radius.
  • Fitness ≥ threshold: the fraction of source points with a target correspondence must exceed a scene-dependent floor (e.g. ≥0.6 for overlapping scans).
  • Transform sanity: the recovered rotation and translation are within physically plausible bounds for the platform motion.
python
def validate_registration(result, rmse_budget=0.05, fitness_floor=0.6):
    assert result.inlier_rmse <= rmse_budget, f"RMSE {result.inlier_rmse:.3f} m too high"
    assert result.fitness >= fitness_floor, f"fitness {result.fitness:.2f} too low"

Edge Cases & Failure Patterns #

  • ICP on a bad prior. Converges confidently to a wrong local minimum. Gate on Criterion 1 and seed with a global pass when the prior is out of basin.
  • NDT voxel too coarse. A large voxel smooths away structure and under-constrains the fit. Size the voxel to the scene scale, typically 1–2 m for outdoor LiDAR.
  • Global pass with too few features. Low-texture scenes (open highway) yield few distinctive FPFH features, so RANSAC finds no consensus. Fall back to odometry-seeded NDT.
  • Degenerate geometry. A long featureless corridor is unconstrained along its axis; all methods slide. Detect low geometric conditioning and hold that degree of freedom from odometry.

Performance & Scale Notes #

Downsample before every method — a voxel grid at the scene scale cuts point counts by an order of magnitude with negligible accuracy loss, and is covered in accelerating ICP with a KD-tree and voxel downsampling. Cache the target's KD-tree (ICP) or voxel grid (NDT) across iterations. The global pass dominates cost, so run it only when Criterion 1 fires; at map scale, most scan pairs have a good odometry prior and skip straight to ICP. Registration parallelizes per scan pair with the async worker pattern from async data pipeline architecture.

FAQ #

When does ICP fail and NDT succeed? #

ICP matches individual point correspondences, so it needs dense, overlapping clouds and a decent initial pose; on sparse LiDAR returns or with a poor guess it locks onto wrong correspondences and converges to a local minimum. NDT instead models the target as a grid of normal distributions and aligns the source to that continuous field, which is more tolerant of sparsity and moderate initial error. On sparse or noisy scans NDT often converges where ICP stalls.

Why is a global registration pass sometimes mandatory? #

Both ICP and NDT are local methods — they refine a pose that is already roughly right. When there is no good initial guess, a local method has no basin of attraction to fall into and will diverge. A global pass using FPFH feature matching with RANSAC finds a coarse alignment from scratch, which then seeds the local refiner.

Is point-to-plane always better than point-to-point ICP? #

On structured scenes with planar surfaces — roads, walls, buildings — point-to-plane ICP converges faster and more accurately because it lets points slide along surfaces toward alignment. Point-to-point is simpler and can be more robust on unstructured geometry where reliable normals are hard to estimate. For AV scenes, which are dominated by planar structure, point-to-plane is the usual default.

Up one level: Sensor Fusion & Spatial Data Alignment — the parent domain whose registration stage this guide helps you configure.