Skip to the content
FixTheRobot Explore Robotics / UAV / Module 4 / M4-T7

UAV Systems Engineering · Module 4

M4-T7: LOAM and A-LOAM

LOAM’s insight was to split the problem by rate: fast and rough scan-to-scan odometry, slow and precise scan-to-map mapping, with sharp edges and flat surfaces as features.

  • Lesson 7 of 15
  • SLAM and Autonomous Localization
  • Research-level
  • About 5 minutes to read

LOAM (Zhang and Singh, RSS 2014) set the pattern for feature-based LiDAR SLAM and A-LOAM is a widely used open implementation. Its core is a simple local-geometry measure: the smoothness (curvature) of points along a scan line.

Learning objectives

After this lesson, you should be able to:

  • Compute the LOAM smoothness measure and classify edge and planar points.
  • Describe the two-rate structure: odometry and mapping.
  • Explain point-to-edge and point-to-plane residuals.
  • State what A-LOAM is and its dependence on the LiDAR scan pattern.

Conceptual explanation

Along each scan line of a spinning LiDAR, LOAM computes a local curvature cc for each point from its neighbours. Points with large cc are edge features (corners), points with small cc are planar features (flat surfaces). Registration minimises distances from edge points to edge lines and from planar points to planar patches in the previous scan (odometry, ~10 Hz) and then in an accumulated map (mapping, ~1 Hz, more precise). The original LOAM uses a constant-velocity assumption within a scan for distortion; A-LOAM (an “advanced” re-implementation by Qin and Cao) uses Ceres and Eigen, dropping the IMU.

LOAM two-rate structureEach scan is split into edge and planar features by curvature. Odometry registers the features to the previous scan at the sensor rate. Mapping registers them to the accumulated map at a lower rate for accuracy. The two poses are combined to give an output at the high rate.Scanpoint cloudFeaturescurvature: edge / planeOdometryscan-to-scan, fastMappingscan-to-map, slowPosehigh-rate outputrough and fast refined by precise and slow
LOAM’s two-rate pipeline.
Animation of LOAM feature extraction on a two-dimensional scan of a room with a box. A window slides along the scan; for each point a smoothness value is computed from the sum of the differences to its neighbours. Points with high curvature, at the corners of the room and the box, become edge features drawn in orange; points with very low curvature, along the straight walls, become planar features drawn in green; the others are ignored.
LOAM smoothness c=∥Σc=\Vert \Sigma (ppⱼ − ppᵢ)∥\Vert / (|SS| ‖ppᵢ∥\Vert ) over the 10 neighbours of a point: large cc = edge, small cc = planar surface. Edges are matched to lines and planar points to planes in the next scan or map. Computed on a ray-cast scan with 1 cm range noise. (Looping, about 6 seconds; drawn and computed for this course with illustrative values.)

Engineering intuition

An edge is where a surface turns sharply: a point there differs strongly from the average of its neighbours; a plane has neighbours that average back onto the point. Both features constrain the pose differently: planes constrain along their normal (lesson M2-T13), edges constrain across the line. Using both gives constraints in more directions than planes alone. The split into odometry and mapping uses the fact that a good initial guess (from the previous scan) makes the expensive scan-to-map step converge quickly at a low rate.

Mathematical formulation

For point ii on a scan line with the set SS of neighbouring points on each side (typically five on each side) and range vectors XX, the smoothness is:

LOAM smoothness
ci=1∣S∣ ∥Xi∥∥∑j∈S, j≠i(Xi−Xj)∥c_i = \frac{1}{\lvert S\rvert\,\lVert\mathbf X_i\rVert}\left\lVert\sum_{j\in S,\ j\ne i}(\mathbf X_i - \mathbf X_j)\right\rVert
edge: ci>cthr,planar: ci<cthr\text{edge: } c_i > c_{\text{thr}}, \qquad \text{planar: } c_i < c_{\text{thr}}

Selection rules in the paper also exclude points near occlusion boundaries and nearly parallel to the beam. Residuals: for an edge point pp and the line through two map edge points a and bb, de=∥(p−a)×(p−b)∥/∥a−b∥d_{e}=\Vert (p-a)\times (p-b)\Vert /\Vert a-b\Vert ; for a planar point and a plane through three points, dp=∣(p−a)⋅((a−b)×(a−c))∣/∥(a−b)×(a−c)∥d_{p}=|(p-a)\cdot ((a-b)\times (a-c))|/\Vert (a-b)\times (a-c)\Vert . The pose is found by Levenberg–Marquardt on the sum of squared distances (lesson M2-T14 for the ICP analogue).

SS
neighbourhood on the same scan line.
cthrc_{\text{thr}}
threshold, a tuning parameter for each LiDAR.
a, bb, cc
map points defining the edge line or the plane.

Architecture and data flow

A-LOAM expects a spinning multi-line LiDAR point cloud with a known number of scan lines (the feature extraction uses the ring structure) and publishes odometry and a map; it does not use an IMU, so it will distort under fast motion where an IMU-aided method will not (lesson M3-T10). Solid-state LiDARs with irregular scan patterns need different feature handling (this is why FAST-LIO’s direct approach is popular on them). Check the README of the repository for the topics and parameters (scan_line, mapping_line_resolution, mapping_plane_resolution).

Real-world UAV applications

  • Baseline LiDAR odometry and mapping with a spinning LiDAR.
  • Teaching feature-based registration.
  • Comparing against FAST-LIO2 on the same data.
  • Feature extraction as the front-end of LeGO-LOAM and LIO-SAM.

Implementation example

This runs as shown: LOAM smoothness on a synthetic scan line crossing a wall corner: the corner point is detected as an edge and points on the flat walls as planar.

import numpy as np

def smoothness(X, half=5):
    n = len(X); c = np.full(n, np.nan)
    for i in range(half, n - half):
        nb = [j for j in range(i - half, i + half + 1) if j != i]
        c[i] = np.linalg.norm(np.sum(X[i] - X[nb], axis=0)) / (2 * half * np.linalg.norm(X[i]))
    return c

# one scan line in the horizontal plane: the sensor at the origin sees two walls meeting at a corner (x = 6 and y = 4)
angles = np.radians(np.linspace(-20, 55, 150)); pts = []
for a in angles:
    d = np.array([np.cos(a), np.sin(a)]); r_x = 6.0 / d[0]; r_y = 4.0 / d[1] if d[1] > 1e-6 else 1e9
    pts.append(min(r_x, r_y) * d)
X = np.array(pts) + 0.002 * np.random.default_rng(0).standard_normal((150, 2))
c = smoothness(X)
corner = int(np.nanargmax(c)); thr = 0.01
edges = np.where(c > thr)[0]; planar = np.where(c < 0.002)[0]
corner_true = int(np.argmin(np.abs(np.arctan2(4.0, 6.0) - angles)))
print(f"corner at index {corner_true}; max curvature at {corner} (c = {c[corner]:.3f}); {len(edges)} edge-candidate and {len(planar)} planar points")
assert abs(corner - corner_true) <= 2 and c[corner] > 0.015
assert len(planar) > 80 and len(edges) < 15 and np.all(np.abs(edges - corner_true) <= 7)
LOAM curvature: corners are edge features and walls are planar features.

Common engineering mistakes

Using A-LOAM on a solid-state LiDAR without adapting the feature extraction

It assumes ring structure.

No IMU on a fast UAV

Scan distortion degrades the result (lesson M3-T10).

Thresholds copied between sensors

Curvature scale depends on resolution and range noise.

Evaluating on a flat scene

Few edge features: the pose is poorly constrained.

Expecting loop closure from LOAM itself

It is odometry and mapping; add a loop-closure back-end.

Failure modes

Failure modes, symptoms and causes
Failure modeHow it shows upLikely cause
Drift in corridorsAlong-axis driftPlanes only constrain across the corridor
Smeared map on fast turnsGhost surfacesNo IMU for deskewing
Feature starvationOdometry jumps in featureless areasToo few edges or planes
High latencySlow mapping threadMap resolution too fine for the CPU

Debugging approach

  1. Visualise the extracted edge and planar points on a scan.
  2. Check scan-line count and ring ordering of your driver.
  3. Evaluate with evo and compare with a LIO method on the same bag.
  4. Profile the mapping thread.

Practical exercises

  1. Tune the threshold on a synthetic scan line with sharper and shallower corners.
  2. Derive the point-to-line distance and its Jacobian.
  3. Run A-LOAM on a public dataset and report drift as a percentage of distance.
  4. Explain why the mapping step runs at a lower rate than the odometry step.

Interview questions

Write an answer in your own words, then reveal the model answer. Nothing is sent anywhere.

Question 1

How does LOAM decide edge and planar points?

Model answer

By the smoothness (curvature) of points along a scan line computed from neighbouring points: high curvature is an edge, low is planar.

Question 2

Why does LOAM have two rates?

Model answer

Scan-to-scan odometry is fast and approximate; scan-to-map mapping is slower but more accurate, and benefits from the odometry initial guess.

Question 3

What is A-LOAM?

Model answer

An open-source “advanced” implementation of LOAM using Ceres and Eigen without an IMU, popular as a baseline.

References and further reading

Primary papers, official documentation and standards. Each claim above that is specific to a tool or version points here.

What’s next

Mark this lesson

Saved in this browser and synced to your account when you are signed in.

Next lesson

M4-T8: FAST-LIO2

Explain the iterated Kalman filter and the ikd-Tree in FAST-LIO2.