Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Fast CPU bundle adjustment: Full and Schur

Created by Codex.

This tutorial solves one bundle-adjustment problem twice with the CPU SfmLevenbergMarquardtOptimizer: first with the fastest measured Full-system configuration, then with explicit Schur elimination. The example includes a calibration shared by every camera, so it also demonstrates that CPU Schur elimination removes Point3 landmarks while keeping poses and calibration in the reduced system.

Open In Colab

1. Build a bundle-adjustment graph

Four camera poses observe eight landmarks. Every projection factor refers to the same calibration variable k0; calibration is therefore optimized globally rather than stored separately in each camera. Priors on the first pose and landmark fix the coordinate frame and scale, while a loose calibration prior regularizes self-calibration.

35 factors, 4 poses, 8 points

2. Create one initial estimate

Both optimizations start from exactly the same deterministic perturbation. This makes their final objectives directly comparable.

Initial error: 9805.400745

3. Calculate the ordering once

reduced_ordering contains only the four poses and shared calibration. schur_ordering is the complete point-first ordering: naturally ordered landmarks followed by that METIS reduced ordering. The fastest measured CPU path uses this complete ordering with Full mode and MULTIFRONTAL_SOLVER.

Reduced ordering: 5 variables
Complete Schur ordering: 13 variables

4. Fastest measured CPU path: Full + multifrontal

Full mode passes the entire linearized graph to the ordinary nonlinear-optimizer solver. Supplying schur_ordering makes MultifrontalSolver eliminate all landmarks first and then factor the camera-and-calibration Schur complement in the same Bayes tree—there is no separately materialized reduced graph or second solver call.

Full final error: 0.000172184

5. Explicit Schur mode

Schur-mode parameters accept the reduced ordering, not the complete one. With MULTIFRONTAL_SOLVER, the optimizer completes it internally and performs the same landmark-first elimination in one multifrontal factorization. Other solver choices would instead receive an explicitly materialized reduced graph.

Schur final error: 0.000172184

6. Verify both paths

The two modes may take slightly different floating-point paths, but they should converge to the same objective and nearly identical shared calibration. These assertions also make the notebook a useful end-to-end smoke test of the Python wrappers.

Full and Schur agree.
Recovered calibration: [ 4.99680801e+01  4.66069104e+01 -2.45373588e-07  5.00012934e+01
  4.83109424e+01]

7. Inspect the reconstruction

The recovered landmarks should overlay the ground truth. Hover over either point cloud to inspect coordinates.

Loading...