The camera poses and 3D points that Structure from Motion and Visual-SLAM obtain via triangulation and PnP are, at best, rough initial values from linear approximations and sequential processing. Per-image noise, quantization error in correspondence points, and propagated error from sequential estimation all pile up, leaving a reconstruction that's internally inconsistent as it stands. Bundle Adjustment (BA) is the final polishing optimization that resolves this inconsistency by moving every camera parameter and every 3D point at once, minimizing the sum of reprojection error across all observed points. The name "bundle" comes from adjusting the bundle of light rays running from each 3D point to each camera, all at once, so they agree with the observed positions.

0. 30-Second Summary

1. What Does It Take as Input, and What Does It Solve For?

The input consists of the following three initial estimates, obtained as intermediate results from SfM or Visual-SLAM:

The output is camera poses and 3D points, all finely adjusted simultaneously, that are more internally consistent across every observation. The fact that Bundle Adjustment isn't a method for building a solution from scratch, but rather a finishing optimization that locally polishes an already "roughly correct" initial value, matters for the discussion of convergence below.

2. The Cost Function: Reprojection Error

The mismatch between where a 3D point \mathbf{X}_j projects into camera i and the actually observed image coordinate \mathbf{u}_{ij} is called the reprojection error. Writing camera i's pose as R_i, \mathbf{t}_i and the projection function as \pi(\cdot) (the nonlinear map converting homogeneous coordinates into pixel coordinates), the residual for one observation is

r_{ij} = \pi\big(K_i(R_i\mathbf{X}_j + \mathbf{t}_i)\big) - \mathbf{u}_{ij}

Bundle Adjustment minimizes the sum of squares of this residual over the entire set of observed pairs \mathcal{O}=\{(i,j)\}.

\min_{\{K_i,R_i,\mathbf{t}_i,\mathbf{X}_j\}}\sum_{(i,j)\in\mathcal{O}}\rho\left(\|r_{ij}\|^2\right)

\rho is a robust loss function such as the Huber loss, which prevents a single large outlier from a mismatch from distorting the entire optimization. This equation is exactly the same form already seen in the SfM Primer — Bundle Adjustment deals with the computational core of actually solving this minimization problem.

3. Solving as Nonlinear Least Squares: From Gauss-Newton to Levenberg-Marquardt

Collecting every unknown into a single vector \mathbf{x} (all camera poses and all 3D points laid out together), and writing the whole set of residuals as \mathbf{r}(\mathbf{x}), the minimization target is \|\mathbf{r}(\mathbf{x})\|^2. Since \mathbf{r} is nonlinear, we use a first-order Taylor expansion around the current estimate \mathbf{x}_k: \mathbf{r}(\mathbf{x}_k+\Delta\mathbf{x})\approx \mathbf{r}(\mathbf{x}_k)+J\Delta\mathbf{x}. J=\partial \mathbf{r}/\partial \mathbf{x} is the Jacobian. Substituting this in and solving for \Delta\mathbf{x} gives the Gauss-Newton method's normal equation:

(J^\mathsf{T}J)\,\Delta\mathbf{x} = -J^\mathsf{T}\mathbf{r}

H=J^\mathsf{T}J is the Hessian approximation (the Gauss-Newton approximation, ignoring second-order terms). Solving this equation for \Delta\mathbf{x}, updating \mathbf{x}_{k+1}=\mathbf{x}_k+\Delta\mathbf{x}, and repeating this operation until the residual converges is the whole procedure.

The Gauss-Newton method converges fast when the initial value is close to the solution, but tends to diverge with a poor initial value. Levenberg-Marquardt (LM), proposed independently by Levenberg (1944) and Marquardt (1963), eases this by adding a damping term to the normal equation.

(J^\mathsf{T}J + \lambda D)\,\Delta\mathbf{x} = -J^\mathsf{T}\mathbf{r}

D is usually the diagonal of J^\mathsf{T}J (or an equivalent scaling matrix), and \lambda is the damping coefficient. When \lambda is small, this behaves close to Gauss-Newton and converges fast; when \lambda is large, it takes small, safe steps closer to steepest descent. Through an adaptive control scheme — shrink \lambda to accelerate whenever the cost decreases each iteration, and grow \lambda to reject and shorten the step whenever the cost increases — LM bridges Gauss-Newton's speed with steepest descent's stability. Nearly every practical implementation of Bundle Adjustment (Ceres Solver, g2o, SBA, and others, discussed below) adopts LM or a closely related trust-region method.

4. Why Is the Jacobian Sparse?

Bundle Adjustment's unknowns are camera pose (6 degrees of freedom — 3 rotation plus 3 translation, if intrinsic parameters are fixed) × m cameras, and 3D point (3 degrees of freedom) × n points, adding up to as many as 6m+3n dimensions. In real SfM problems with tens of thousands of observations or more, naively treating this J^\mathsf{T}J as a dense matrix costs O((6m+3n)^3) — not solvable in realistic time.

What comes to the rescue here is the structure that the reprojection error r_{ij} "depends only on camera i's parameters and point j's parameters." The partial derivatives with respect to any other camera k\neq i or point l\neq j are identically zero.

\frac{\partial r_{ij}}{\partial \mathbf{x}_{\text{camera }k}} = 0 \ (k\neq i), \qquad \frac{\partial r_{ij}}{\partial \mathbf{X}_l} = 0 \ (l\neq j)

In other words, the row of the Jacobian generated by a single observation has nonzero entries only in the block for the corresponding camera and the block for the corresponding point. The number of rows grows in proportion to the number of observations, but the number of nonzero entries per row stays constant (camera 6 + point 3, or a bit more if intrinsic parameters are included). This sparsity shows up, when you look at J^\mathsf{T}J, as the following block structure.

J^\mathsf{T}J = \begin{pmatrix} B & E \\ E^\mathsf{T} & C \end{pmatrix}

5. The Basic Pipeline

The basic Bundle Adjustment pipeline A diagram showing the flow that starts from an initial pose and 3D points, computes the reprojection-error Jacobian, eliminates points with the Schur complement to solve the reduced camera system, updates iteratively via Levenberg-Marquardt, and converges. Initial pose/3D points(rough estimate from SfM/SLAM) Reprojection errorcompute residual r_{ij} Sparse Jacobiancamera × pointblock structure Eliminate points viaSchur complement,reduced camera system Adjust \lambda viaLM method,update \Delta\mathbf{x} Checkconvergence

Every iteration recomputes the reprojection error, assembles the sparse Jacobian, solves the camera-only reduced system via the Schur complement, and updates via LM's step control. This repeats until the change in cost drops below a threshold, or until a maximum number of iterations is reached.

6. The Schur Complement Trick: Turning Sparsity Into Reduced Computation

Using the block structure from the previous section, we can write the normal equation (J^\mathsf{T}J+\lambda D)\Delta\mathbf{x}=-J^\mathsf{T}\mathbf{r} split into the camera update \Delta\mathbf{c} and the point update \Delta\mathbf{p} as

\begin{pmatrix} B' & E \\ E^\mathsf{T} & C' \end{pmatrix} \begin{pmatrix} \Delta\mathbf{c} \\ \Delta\mathbf{p} \end{pmatrix} = \begin{pmatrix} v \\ w \end{pmatrix}

(where B', C' are the blocks after adding the damping term). Since C' is a block-diagonal matrix, independent per 3D point, each 3×3 block can be inverted individually, at a cost roughly proportional to the number of points n. Using this C'^{-1} to eliminate \Delta\mathbf{p} leaves the reduced camera system, involving cameras only:

\left(B' - E C'^{-1}E^\mathsf{T}\right)\Delta\mathbf{c} = v - E C'^{-1}w

The left-hand side's B'-EC'^{-1}E^\mathsf{T} is called the Schur complement. This matrix has size 6m\times 6m (depending only on the number of cameras, not on the number of points n), and once \Delta\mathbf{c} has been solved, each point's update can be cheaply recovered with

\Delta\mathbf{p} = C'^{-1}\left(w - E^\mathsf{T}\Delta\mathbf{c}\right)

In a typical SfM problem, the number of points n can be dozens of times the number of cameras m, so instead of naively solving a system with 6m+3n dimensions, you only need to handle the Schur complement, of dimension 6m. This is the core idea that makes Bundle Adjustment practically solvable even at the scale of tens of thousands of points. It was theoretically organized by Triggs et al.'s "Bundle Adjustment — A Modern Synthesis" (2000), and it's the standard internal implementation in current libraries like Ceres Solver and g2o.

Ceres Solver offers multiple options just for how to solve this reduced system: DENSE_SCHUR, which solves it as a dense matrix (up to a few hundred cameras); SPARSE_SCHUR, which exploits sparsity via reordering (thousands of cameras); and ITERATIVE_SCHUR, which applies conjugate gradient to the Schur complement (for even larger-scale problems). Choosing among these based on the scale of the problem is a practical rule of thumb.

7. Gauge Freedom: the Directions Along Which the Solution Isn't Uniquely Determined

Bundle Adjustment retains a degree of freedom that can move the whole set of parameters without changing the value of the cost function. Moving every camera and every 3D point together by the same rotation, translation, and scale leaves the reprojection error completely unchanged (for a monocular-only case, absolute scale is likewise indeterminate). This degree of freedom is called gauge freedom. Left unaddressed, it makes J^\mathsf{T}J singular (rank-deficient), which either makes the normal equation unsolvable, or numerically unstable.

In practice, this is worked around by fixing the pose of the first two cameras or one baseline length, or by relying on the fact that LM's own damping term \lambda D implicitly regularizes this singular direction. When absolute-scale or absolute-pose information is available — from GPS or an IMU, say — it's natural to use that as an additional constraint to fix the gauge.

8. The Difference From Pose Graph Optimization

Pose Graph optimization, covered in the Loop Closure Primer, also belongs to the same mathematical framework as Bundle Adjustment in the sense that it minimizes, with a robust loss, a nonlinear least-squares residual built with the \mathrm{Log} map. The difference lies in what the unknowns actually are.

Aspect Bundle Adjustment Pose Graph Optimization
Unknowns Every camera pose + every 3D-point coordinate Every camera's (node's) pose only
Residual 3D-point reprojection error (image space) Difference from relative-pose observations (SE(3) space)
Source of sparsity Which camera saw which point Which node pairs are linked by a constraint
Computational cost High with many points, tamed via the Schur complement Inherently smaller, scaling with the number of nodes (keyframes)
Primary use Final polish of SfM, refining local/global maps Global drift correction in SLAM (after loop closure)

In actual Visual-SLAM systems, it's common to see a division of labor: local bundle adjustment (local BA), including 3D points, refines the area around keyframes on a per-frame basis, while lightweight Pose Graph optimization without explicit 3D points quickly corrects the global trajectory whenever a loop closure is detected. Full bundle adjustment including 3D points (global BA) is more accurate but computationally costly, so it can't be run frequently in situations that demand real-time performance.

9. Representative Implementations

10. Difficult Conditions and Common Failure Cases

11. Practical Choices

12. Summary

Bundle Adjustment is a nonlinear least-squares problem that simultaneously minimizes reprojection error across every camera and every 3D point, solved iteratively via the Levenberg-Marquardt method. The Schur complement trick, which exploits the sparsity of the camera-point observation relationship, is what makes this optimization solvable in realistic time even at the scale of tens of thousands of points. While it shares a mathematical framework with Pose Graph optimization, the choice between the two comes down to whether 3D points are explicitly held, and it's a shared foundational technology that ultimately underpins the accuracy of both SfM and SLAM.

References

#Bundle Adjustment #Nonlinear Least Squares #Levenberg-Marquardt #Schur Complement #Structure from Motion