Snap one point cloud onto another by matching then fitting, over and over. Match each source point to its nearest target point, solve the optimal rigid transform for those pairs in closed form, apply it, and repeat. The mean-square distance falls monotonically to a local minimum — this is how two scans become one map. Rendered, not quoted.
ICP alternates two steps until the pose stops moving:
1 · match — for every source point, find its nearest target point (Euclidean). This guesses the correspondences.
2 · solve — with those pairs held fixed, the optimal rigid transform (R,t) is the closed-form orthogonal Procrustes / SVD solution: center both sets, correlate them, take the rotation, then t = q̄ − R·p̄.
Each step can only lower the mean-square distance, so the metric decreases monotonically to a fixed point.
amber Point-to-point here; point-to-plane converges in fewer iterations but needs surface normals.
Besl & McKay 1992 turned nearest-neighbour matching plus the rigid Procrustes fit into an iteration — the standard way a fresh scan is registered against the last one.
Downstream neighbour: the pose-graph SLAM sphere (Smith & Cheeseman 1986) consumes these scan-to-scan rigid transforms as graph edges. ICP gives the relative pose; the back-end fuses the chain of poses into one consistent map. Rigidity is the contract the map depends on.
Live re-check of the rigidity guarantee on a dedicated anisotropic probe: the solver must return an orthonormal map (RᵀR = I, det = +1). It confirms green now, and flips red the instant window 6 swaps the rigid solve for an affine one.
A source cloud P and a target cloud Q. Here Q is a known rigid transform of a hexagonal token with one displaced marker vertex: rotation θ*=25.000°, translation t*=(1.30, −0.80). Initialization: identity.
From identity, correct correspondences are found (25° < 30° half-spacing), so ICP recovers the exact rigid pose and the SSE collapses to machine zero.
The adversary owns the initial pose and the overlap. Real ways ICP breaks:
• Local minima — a far or symmetric start locks onto the wrong basin (window 0's BAD INIT shows it).
• Outliers & partial overlap — nearest-neighbour pairs the wrong points and drags the fit off; needs rejection / trimming.
• Non-rigid deformation — a rigid model cannot fit it; loosening to affine over-fits it (window 6).
Planted void: replace the rigid Procrustes solve with a general affine least-squares solve (scale + shear allowed). On the witness's anisotropic probe the fit distorts the shape and the recovered map is no longer a rotation — the rigidity guarantee dies.
amber Honest subtlety: on perfectly rigid data (window 0's token) affine coincides with rigid, so the bug hides there — which is exactly why the witness runs its own non-rigid probe.