Skip to content
AI360Xpert
Beta

Visual Odometry from Frame Motion

Watch the ground slide past frame by frame and add up the steps. Visual odometry turns pixel motion between consecutive frames into a running camera path.

Tracked features step the camera forward frame by frame while small errors accumulate
Tracked features step the camera forward frame by frame while small errors accumulate

Why Does This Exist?

GPS dies indoors and wheels slip, so a camera must dead-reckon from what it sees. Visual odometry exists for that incremental job: estimate rotation RR and translation tt between consecutive frames and chain them into a path. It is the front end inside visual SLAM; SLAM adds the map reuse and loop closure that odometry lacks.

This page covers frame-to-frame motion only. Pixel motion basics live in optical flow; global correction lives in pose graph optimization.

Think of It Like This

Counting steps by watching floor tiles

Walk with eyes on the floor tiles and count how each tile slides past. Big fast slides mean long strides; slow slides mean shuffling. After a hundred steps your count is close but off, because each step estimate carried a small error.

Tiles are tracked corners and strides are RR and tt steps. The analogy stops at scale: tile size is known while a single camera never learns meters without a baseline or known object.

How It Actually Works

Each step detects corners, tracks them into the next frame, and solves for the motion that best explains the 2D shifts. Calibrated stereo triangulates points at true scale and solves perspective-n-point for [R∣t][R|t]; monocular setups estimate the essential matrix and recover motion up to an unknown scale factor. Keyframes anchor the chain: new frames track against the last keyframe, and a new keyframe spawns when parallax or feature loss passes a threshold. Chaining composes poses as T0:k=T0:k−1Tk−1:kT_{0:k} = T_{0:k-1} T_{k-1:k}, so per-step errors of 11 percent compound into percent-level drift per hundred meters.

Worked numbers

At 1010 Hz with 0.50.5 m per step, 200200 frames cover 100100 m. A 11 percent scale bias per step adds 0.0050.005 m extra each time, totaling about 1.01.0 m after 200200 steps, plus roughly 1.01.0 m of random walk from 0.070.07 m per-step noise. The path ends about 22 m from truth with no loop to pin it, the textbook odometry drift curve.

Code

def chain_poses(steps: list[float]) -> float:    total = 0.0    for s in steps:        total += s  # 1D chaining stands in for SE(3) composition    return total

print(chain_poses([0.505] * 200))  # -> 100.9999999999998

Watch Out For

Trusting monocular scale over distance

Monocular odometry recovers direction but not meters, so scale drifts silently with scene depth. The symptom is a path with the right shape at the wrong size. Fix scale from stereo, an IMU, or a known-height object, and never report meters from one camera alone.

Tracking through pure rotation

Distant scenes under rotation give tiny parallax, so translation estimates swing wildly while rotation looks clean. Gate keyframes on translation parallax and translation magnitude, and freeze the position update when the baseline collapses.

The Quick Version

  • Visual odometry chains frame-to-frame RR and tt into a running path.
  • Stereo gives metric scale; monocular recovers motion only up to scale.
  • Keyframes bound cost by tracking against sparse anchors.
  • Per-step errors near 11 percent compound into meters over hundreds of meters.
  • Odometry drifts by design; loop closure is what removes the drift.
  • Pure rotation and textureless frames are the standard tracking traps.