Part X: Sensor Fusion, World Models, and Spatial AI
Chapter 52: SLAM and Spatial AI

Classical SLAM (ORB-SLAM3, DROID-SLAM)

"I drove a perfect loop of the warehouse and came back forty centimeters to the left of where I started. The floor had not moved. My belief had."

A Loop-Closing AI Agent

Prerequisites

This section assumes you understand visual-inertial odometry from Section 52.1: how tracking a camera and IMU frame to frame yields an incremental pose estimate that drifts. It leans on the sparse keypoint detectors and descriptors of Chapter 8, on the nonlinear least-squares and pose-graph machinery of Chapter 11, and on the stereo and RGB-D depth geometry of Chapter 40. You need comfort with rigid-body transforms in \(SE(3)\) and with reading a residual as something an optimizer drives to zero.

Odometry remembers the last second; SLAM remembers the whole room

Visual-inertial odometry answers "how did I move since the last frame?" and its errors compound: every small mis-estimate is welded onto the running total, so a long trajectory bends away from the truth. SLAM adds the second letter, mapping, and with it a new power: recognizing a place you have already seen. When the agent re-enters a previously mapped corridor, a loop closure ties the present pose to the past one, and a global optimization redistributes the accumulated drift across the entire trajectory at once. That single idea, turning a drifting chain into a globally consistent graph, is what separates a system that can localize inside a building for an hour from one that is lost after a hallway. This section covers the two reference designs that define the field: ORB-SLAM3, the mature geometric feature-based system, and DROID-SLAM, the learned dense alternative that trades hand-crafted features for a trained update operator.

Every SLAM system juggles the same four jobs: track the camera against the current map, map new geometry as keyframes and 3D points, close loops by recognizing revisited places, and optimize the whole estimate for global consistency. ORB-SLAM3 and DROID-SLAM answer these jobs with opposite philosophies, and understanding the contrast teaches you when to reach for each.

Feature-based SLAM: the ORB-SLAM3 design

What ORB-SLAM3 does is track a sparse set of a few hundred to a few thousand ORB keypoints per frame, the oriented FAST corners with rotated BRIEF descriptors from Chapter 8, chosen because they are fast to detect, cheap to match by Hamming distance, and invariant to rotation and modest scale change. Why sparse features win here is efficiency: representing the world by landmarks rather than pixels lets the whole system run in real time on a CPU while carrying an explicit, reusable map. The system keeps a subset of frames as keyframes and links them in a covisibility graph: two keyframes are connected when they observe the same landmarks, and that graph is the backbone for both local mapping and loop search.

How it stays accurate is bundle adjustment: the joint refinement of camera poses \(T_i \in SE(3)\) and 3D points \(\mathbf{p}_j\) so that the reprojection of every point lands on the pixel where it was actually seen. Formally it minimizes

$$\min_{\{T_i\},\{\mathbf{p}_j\}} \sum_{(i,j)} \rho\!\left( \big\lVert \mathbf{u}_{ij} - \pi(T_i, \mathbf{p}_j) \big\rVert^2_{\Sigma_{ij}} \right),$$

where \(\pi\) is the camera projection, \(\mathbf{u}_{ij}\) the observed pixel, \(\Sigma_{ij}\) the measurement covariance, and \(\rho\) a robust (Huber) kernel that stops a few bad matches from dominating. ORB-SLAM3 runs this in two scopes: local bundle adjustment over a sliding window of covisible keyframes for real-time refinement, and full bundle adjustment after a loop closure for global consistency, exactly the sparse nonlinear least-squares problem of Chapter 11.

Three features make version 3 the reference rather than a research toy. First, it is tightly coupled visual-inertial: the IMU preintegration factors sit in the same optimization as the visual factors, so scale (unobservable from a single monocular camera) becomes observable and tracking survives brief visual blackouts. Second, it supports monocular, stereo, and RGB-D inputs through a shared pipeline, so the same code localizes a phone, a robot with a stereo rig, or a depth camera. Third, its Atlas system maintains multiple disconnected sub-maps: when tracking is lost, it starts a fresh map and later merges it if a place is recognized, which is what makes it robust to the kidnapped-robot problem.

Loop closure and relocalization: recognizing a place

The mechanism that turns odometry into SLAM is place recognition. ORB-SLAM3 uses a bag-of-visual-words index (DBoW2): each keyframe's ORB descriptors are quantized against a pre-trained vocabulary tree into a compact histogram, and finding loop candidates becomes a fast lookup for keyframes with similar histograms rather than an all-pairs image comparison. A candidate is only accepted after a geometric check, matching features and verifying a consistent rigid transform, so a lookalike wall does not trigger a false closure.

A loop closure is a single constraint that pays off globally

One recognized place adds exactly one edge to the pose graph, connecting the current keyframe to an old one with a measured relative transform. Yet that lone edge is worth more than thousands of odometry edges, because it is the only constraint that contradicts accumulated drift. Optimizing the graph then spreads the correction backward across every intermediate pose, snapping the trajectory into global agreement. This is why SLAM engineers obsess over recall of place recognition: a missed loop leaves drift uncorrected, while a single good closure can rescue an entire session. It is also why a false closure is catastrophic, welding two genuinely different places together, and why the geometric verification step is never optional.

The code below strips loop closure to its essence: a one-dimensional robot that drifts around a loop and returns to its start. A pose-graph optimization treats the known return-to-origin as a constraint and redistributes the error.

import numpy as np

# A robot makes N steps around a loop; each odometry step should be +1.0 but drifts.
N = 20
true_step = 1.0
rng = np.random.default_rng(0)
odom = true_step + rng.normal(0.0, 0.05, N)      # noisy relative measurements
poses = np.concatenate([[0.0], np.cumsum(odom)]) # dead-reckoned positions

# Loop closure: we recognize that pose N is the SAME place as pose 0 (relative = 0).
# Build a linear pose graph: odometry edges + one loop edge, solve least squares.
rows, b = [], []
for i in range(N):                               # odometry constraints x_{i+1}-x_i = odom_i
    r = np.zeros(N + 1); r[i], r[i+1] = -1, 1
    rows.append(r); b.append(odom[i])
r = np.zeros(N + 1); r[0], r[N] = -1, 1          # loop constraint x_N - x_0 = 0
rows.append(r); b.append(0.0)
r = np.zeros(N + 1); r[0] = 1                     # anchor x_0 = 0 (gauge freedom)
rows.append(r); b.append(0.0)

A = np.array(rows)
x_opt = np.linalg.lstsq(A, np.array(b), rcond=None)[0]
print(f"drift before closure : {poses[N]-poses[0]:+.3f} m")
print(f"drift after  closure : {x_opt[N]-x_opt[0]:+.3f} m")
print(f"max pose correction  : {np.abs(x_opt-poses).max():.3f} m")
A minimal pose-graph loop closure. The dead-reckoned path ends tens of centimeters from its start; adding one loop constraint (pose \(N\) equals pose \(0\)) and solving the linear least-squares graph drives the closing error to zero and spreads the correction smoothly over all intermediate poses, exactly what full bundle adjustment does in three dimensions.

Real ORB-SLAM3 solves the nonlinear \(SE(3)\) version of this graph over keyframes and landmarks, but the arithmetic in the snippet is the whole idea: drift measured at the loop is a residual, and the optimizer apologizes for it everywhere.

DROID-SLAM: learned dense bundle adjustment

DROID-SLAM answers the same four jobs with a trained network instead of hand-crafted features. What it computes is dense per-pixel correspondence between frames using a recurrent update operator borrowed from optical-flow research (the RAFT-style GRU), which iteratively revises a flow field and a per-pixel confidence. Why this helps is robustness: learned dense matching tolerates low-texture walls, motion blur, and repetitive patterns that starve a corner detector, and the confidence weights let the system downweight unreliable pixels automatically rather than through a hand-tuned threshold. How it stays geometrically honest is a differentiable dense bundle adjustment layer: after each network update, a Gauss-Newton step (a dense BA layer) jointly refines all camera poses and a per-pixel depth map over a frame graph so that the geometry is consistent with the predicted correspondences. Training end to end through that geometric layer is what makes the learned flow serve accurate poses rather than pretty pictures.

When DROID-SLAM is the right call is when you have a GPU and a hard visual environment; when it is the wrong call is a CPU-only or power-constrained target, because dense correlation volumes and iterative BA are heavy. ORB-SLAM3 runs comfortably on a laptop CPU; DROID-SLAM expects a capable GPU and more memory. The two systems bracket the design space: sparse-geometric-cheap versus dense-learned-robust.

Where the state of the art sits

ORB-SLAM3 (Campos et al., 2021) remains the accuracy and robustness benchmark for real-time feature-based visual-inertial SLAM and is still the baseline nearly every new paper reports against. DROID-SLAM (Teed and Deng, 2021) set the bar for learned dense SLAM and generalizes across monocular, stereo, and RGB-D without retraining. The frontier has since split two ways: DPVO (2023) brought DROID's learned matching to a sparse, far cheaper patch-based formulation, and end-to-end pointmap systems such as DUSt3R and MASt3R-SLAM (2024 to 2025) drop explicit feature matching and camera calibration entirely, regressing dense 3D directly. The differentiable-BA idea keeps reappearing because it fuses learned front ends with the geometric back end that guarantees consistency, the same fusion that Chapter 51 pushes toward photorealistic maps.

A warehouse AMR that stopped getting lost at the loading dock

An autonomous mobile robot ferrying totes across a distribution center ran stereo ORB-SLAM3. It localized beautifully among the shelving, where painted floor markings and rack edges gave dense corners, but repeatedly lost tracking at the loading dock: a wide, glossy, near-textureless concrete apron under changing daylight from the roller doors. Feature detection collapsed, the map fragmented into Atlas sub-maps, and the robot occasionally re-initialized with a scale jump. The team ran the same recorded sessions through DROID-SLAM offline and found the learned dense front end held correspondence across the blank apron where corners had vanished, because it could exploit faint gradients and lighting structure a detector discards. The shipped fix was pragmatic: keep ORB-SLAM3 on the CPU for the feature-rich aisles for battery life, and hand off to a GPU-backed dense tracker only in the geometrically starved dock zone, with loop closures from the aisle map re-anchoring the pose on return. Robustness came from matching the SLAM front end to the texture the environment actually offered.

Right tool: a full SLAM stack instead of a semester of geometry

Implementing tracking, keyframe selection, DBoW2 place recognition, and windowed bundle adjustment from scratch is several thousand lines of careful C++ and linear algebra. The reference systems ship it: cloning and building ORB-SLAM3 gives you a real-time visual-inertial SLAM binary you feed a calibrated camera and IMU stream, and pip install-able wrappers plus the authors' DROID-SLAM repo run a learned dense pipeline in a dozen lines of Python. That is on the order of 5000 lines of SLAM internals reduced to a config file and a call: the library owns the covisibility graph, the robust solver, and the loop-closure verification, leaving you to own calibration and evaluation. Build from scratch to learn the residuals; deploy the reference stack to ship.

Choosing between them, and their shared blind spot

Pick ORB-SLAM3 when compute is scarce, when you want an explicit reusable landmark map, or when an IMU is available for scale and blackout robustness. Pick a learned dense approach when the scene is low-texture, motion-blurred, or repetitive and a GPU is on board. Both, however, share a deep assumption: the world is static. A person walking through frame, a forklift crossing the aisle, or a swaying curtain injects correspondences that are geometrically consistent yet belong to a moving object, corrupting both the pose and the map. Handling that is the subject of Chapter 51's dynamic scenes and of Section 52.6. For now, remember that classical SLAM's global consistency is bought with a static-world promise the real world does not always keep.

Exercise: measure the value of a loop closure

Extend the pose-graph snippet to two dimensions: simulate a square loop of 40 noisy odometry steps returning near the origin. (a) Plot the dead-reckoned path and measure the closing error. (b) Add the loop constraint and re-solve; report how the maximum per-pose correction depends on where in the loop each pose sits. (c) Now inject one false loop closure between two poses that are physically far apart and re-solve. Describe how the false constraint corrupts the whole trajectory, and explain why ORB-SLAM3's geometric verification exists precisely to prevent this.

Self-check

  1. Why does adding a single loop-closure edge improve the entire trajectory rather than only the two poses it connects?
  2. ORB-SLAM3 represents the world with a few hundred landmarks per frame while DROID-SLAM reasons over every pixel. State one concrete advantage each choice buys and one cost it pays.
  3. What does the differentiable dense bundle adjustment layer contribute during DROID-SLAM's training that a network predicting flow alone would miss?

What's Next

In Section 52.3, we replace the sparse landmark cloud and the explicit point map with a learned neural representation of the scene. Neural SLAM systems such as NICE-SLAM store geometry and appearance in a continuous, differentiable field and optimize the camera pose by rendering against it, blurring the line between mapping and the neural-field reconstruction you will meet as a first-class citizen later in the chapter.