IMU preintegration

An IMU produces measurements at 100–1000 Hz, while cameras deliver keyframes at 10–30 Hz. A naive VIO formulation would insert every IMU reading into the estimator, exploding the number of state variables. Worse, naive integration is done in the world frame: the integrated result depends on the absolute pose at the start of the interval, so every time the optimizer adjusts that pose, all raw IMU data would need to be re-integrated.

Preintegration (introduced by Lupton and Sukkarieh, 2012) solves both problems. IMU measurements between two keyframe times ii and jj are integrated in the local frame of keyframe ii, producing a compact relative-motion summary:

(ΔRij,  Δvij,  Δpij)\left(\Delta\mathbf{R}_{ij},\; \Delta\mathbf{v}_{ij},\; \Delta\mathbf{p}_{ij}\right)

— a relative rotation, velocity change, and position change. Crucially, these quantities depend only on the IMU measurements and the bias estimates, not on the absolute poses. They are computed once, stored, and act as a single “IMU factor” connecting the states at ii and jj in the factor graph. When the optimizer moves the poses, nothing needs re-integration.

The math

Starting from the measurement model ω~t=ωt+bg+ηg\tilde{\boldsymbol{\omega}}_t = \boldsymbol{\omega}_t + \mathbf{b}^g + \boldsymbol{\eta}^g,   a~t=Rt(atg)+ba+ηa\;\tilde{\mathbf{a}}_t = \mathbf{R}_t^\top(\mathbf{a}_t - \mathbf{g}) + \mathbf{b}^a + \boldsymbol{\eta}^a, the preintegrated terms accumulate over the IMU samples in [i,j)[i, j):

ΔRij=t=ij1Exp ⁣((ω~tbig)δt)\Delta\mathbf{R}_{ij} = \prod_{t=i}^{j-1} \mathrm{Exp}\!\big((\tilde{\boldsymbol{\omega}}_t - \mathbf{b}^g_i)\,\delta t\big)

Δvij=t=ij1ΔRit(a~tbia)δt,Δpij=t=ij1[Δvitδt+12ΔRit(a~tbia)δt2]\Delta\mathbf{v}_{ij} = \sum_{t=i}^{j-1} \Delta\mathbf{R}_{it}\,(\tilde{\mathbf{a}}_t - \mathbf{b}^a_i)\,\delta t, \qquad \Delta\mathbf{p}_{ij} = \sum_{t=i}^{j-1}\Big[\Delta\mathbf{v}_{it}\,\delta t + \tfrac{1}{2}\Delta\mathbf{R}_{it}\,(\tilde{\mathbf{a}}_t - \mathbf{b}^a_i)\,\delta t^2\Big]

Note that gravity does not appear here — it re-enters only in the residual below, where absolute orientation is available. In pseudo-code, the accumulation is a simple loop run once per keyframe interval:

ΔR, Δv, Δp ← I, 0, 0
for each IMU sample (ω̃, ã, δt) in [i, j):
    Δp ← Δp + Δv·δt + ½·ΔR·(ã − bᵃ)·δt²
    Δv ← Δv + ΔR·(ã − bᵃ)·δt
    ΔR ← ΔR · Exp((ω̃ − bᵍ)·δt)
    (propagate covariance and bias Jacobians alongside)

The IMU residual

The resulting factor compares the predicted relative motion (from the current pose/velocity/bias estimates and gravity) against the stored preintegrated measurement, exactly parallel to how a reprojection residual compares a predicted and observed pixel:

rΔR=Log(ΔRijRiRj),rΔv=Ri(vjvigΔtij)Δvij\mathbf{r}_{\Delta R} = \mathrm{Log}\big(\Delta\mathbf{R}_{ij}^\top\,\mathbf{R}_i^\top\mathbf{R}_j\big), \qquad \mathbf{r}_{\Delta v} = \mathbf{R}_i^\top\big(\mathbf{v}_j - \mathbf{v}_i - \mathbf{g}\,\Delta t_{ij}\big) - \Delta\mathbf{v}_{ij}

rΔp=Ri(pjpiviΔtij12gΔtij2)Δpij\mathbf{r}_{\Delta p} = \mathbf{R}_i^\top\big(\mathbf{p}_j - \mathbf{p}_i - \mathbf{v}_i\,\Delta t_{ij} - \tfrac{1}{2}\mathbf{g}\,\Delta t_{ij}^2\big) - \Delta\mathbf{p}_{ij}

weighted by the covariance propagated during the accumulation loop (which is where the IMU noise model parameters enter).

Two refinements that make it practical

Common pitfalls

Why it matters for SLAM

Preintegration is the single idea that made optimization-based VIO real-time: it compresses hundreds of high-rate measurements into one factor per keyframe pair while remaining exactly re-linearizable. Every modern tightly-coupled VIO system builds on it, and understanding how ΔRij\Delta\mathbf{R}_{ij} is formed and bias-corrected is the fastest route to understanding any VIO codebase.