Use this file to discover all available pages before exploring further.
OpenVINS uses a 6-axis IMU as the backbone of its Extended Kalman Filter (EKF), propagating a 15-dimensional inertial state forward between camera frames. Each incoming IMU reading — a raw angular rate and a raw linear acceleration — is de-biased and integrated to evolve the orientation, position, velocity, and sensor biases in time. Two integration strategies are supported: a straightforward discrete model that is easy to understand and implement, and a full continuous-time analytical model that additionally accommodates IMU intrinsic calibration parameters such as scale factors, axis misalignments, and gyroscope gravity sensitivity.
A 6-axis MEMS IMU reports measurements of the local angular rate Iωm and local linear acceleration Iam in the IMU body frame {I}. Both channels are corrupted by an additive slowly-drifting bias and white Gaussian noise:Iωm(t)=Iω(t)+bg(t)+ng(t)Iam(t)=Ia(t)+GIR(t)Gg+ba(t)+na(t)where Iω and Ia are the true angular velocity and linear acceleration, bg and ba are the gyroscope and accelerometer biases, ng and na are zero-mean white Gaussian noise processes, Gg=[009.81]⊤ is gravity expressed in the global frame {G}, and GIR rotates vectors from the global frame into the IMU frame.For IMUs with significant scale/axis imperfections (MEMS models in particular), OpenVINS also supports an extended intrinsic model that introduces separate gyroscope and accelerometer sensor frames {w} and {a}:wωm(t)=TwIwRIω(t)+TgIa(t)+bg(t)+ng(t)aam(t)=TaIaR(Ia(t)+GIR(t)Gg)+ba(t)+na(t)Here Tw and Ta are invertible 3×3 scale/misalignment matrices, and Tg models the gravity sensitivity of the gyroscope (its response to linear acceleration due to inherent inertia).
Calibrating IMU intrinsics introduces many additional degrees of freedom and requires trajectories with sufficient excitation (e.g. dynamic handheld motion). Planar, single-axis, or constant-measurement trajectories can lead to degenerate calibrations. OpenVINS recommends performing intrinsic calibration offline unless your platform is guaranteed to have rich, multi-axis motion.
The inertial navigation state xI at time t is a 16-dimensional vector (parameterized as a 15-dimensional error state):xI(t)=GIqˉ(t)GpI(t)GvI(t)bg(t)ba(t)
Symbol
Dimension
Meaning
GIqˉ
4 (unit quaternion)
Rotation from global frame {G} to IMU frame {I} (JPL convention)
GpI
3
Position of IMU origin in the global frame
GvI
3
Velocity of IMU in the global frame
bg
3
Gyroscope bias
ba
3
Accelerometer bias
OpenVINS uses the JPL quaternion convention with a left multiplicative quaternion error:GIqˉ=δqˉ⊗GIqˉ^,δqˉ≃[21θ~1]where θ~∈R3 is the small-angle orientation error vector. All other states use standard additive error. This yields a 15-dimensional error state x~I despite the 16-element quaternion parameterization.
The continuous-time differential equations governing IMU state evolution are:GIqˉ˙(t)=21Ω(Iω(t))GItqˉGp˙I(t)=GvI(t)Gv˙I(t)=GItR⊤Ia(t)b˙g(t)=nwg(t),b˙a(t)=nwa(t)where Ω(ω)=[−⌊ω×⌋−ω⊤ω0] is the quaternion rate matrix, and the biases evolve as random walks driven by white Gaussian process noises nwg and nwa.
Given the kinematic equations above, the state mean must be numerically integrated between IMU timestamps. OpenVINS provides two integration approaches. Both compute the state transition matrix Φ(tk+1,tk) and noise Jacobian Gk, then propagate the covariance as:Pk+1∣k=Φ(tk+1,tk)Pk∣kΦ(tk+1,tk)⊤+GkQdGk⊤
Discrete Integration
Analytical Integration
The discrete model assumes each IMU measurement is constant over its sampling interval Δtk=tk+1−tk. This is a zero-order hold (ZOH) approximation.Quaternion propagation uses the matrix-exponential form of the constant-rate assumption:GIk+1qˉ^=exp(21Ω(ω^k)Δtk)GIkqˉ^where ω^k=ωm,k−b^g,k is the bias-corrected angular rate.Position and velocity are updated assuming constant acceleration in the current body frame:Gp^Ik+1=Gp^Ik+Gv^IkΔtk−21GgΔtk2+21GIkR^⊤a^kΔtk2Gv^k+1=Gv^Ik−GgΔtk+GIkR^⊤a^kΔtkBiases propagate as pure random walks:b^g,k+1=b^g,k,b^a,k+1=b^a,kThe discrete noise covariance is converted from the continuous-time noise spectral density:Qmeas=[Δtσgc2I300Δtσac2I3],Qbias=[Δtσwgc2I300Δtσwac2I3]The 15×15 state transition matrixΦ is constructed by perturbing each state variable and collecting first-order terms. It captures how orientation error propagates into position and velocity errors through the estimated acceleration.
The discrete model is simpler to implement and is the right starting point for understanding OpenVINS propagation. It does not include IMU intrinsic calibration parameters.
The analytical model performs continuous-time integration under the constant-measurement assumption and accommodates the full IMU intrinsic model (scale/axis corrections Dw, Da; inter-frame rotations wIR, aIR; and gravity sensitivity Tg).The continuous integration introduces four matrix integrals Ξ1…4 that are evaluated analytically using closed-form expressions involving SO(3) exponentials:Ξ1≜∫tktk+1IτIkRdτ,Ξ2≜∫tktk+1∫tksIτIkRdτdsThese allow the position and velocity increments to be written as:Δp^k=Ξ2⋅Ika^,Δv^k=Ξ1⋅Ika^Intrinsic calibration adds up to 27 extra parameters (6 gyroscope, 6 accelerometer, 3 inter-frame rotation, 9 gravity sensitivity) to the state, and the analytical Jacobians with respect to all of them are derived in closed form. Two IMU intrinsic models are supported:
KALIBR: Lower-triangular Dw6′/Da6′, calibrates wIR; compatible with the Kalibr toolbox output.
RPNG: Upper-triangular Dw6/Da6, calibrates aIR; follows the imu2 model analyzed in Yang et al. (TRO 2023).
Only one of wIR or aIR should be calibrated at a time. Calibrating both over-parameterizes the rotation between the IMU and camera, making that extrinsic unobservable.
A standard EKF linearizes about the current (post-update) state estimate at each step. Because a visual-inertial system has 4 unobservable degrees of freedom — absolute yaw and 3D global translation — linearizing about an ever-changing estimate causes the observability matrix to gain spurious rank along the yaw direction, leading to filter over-confidence (estimated uncertainty smaller than true uncertainty) and degraded accuracy.First-Estimate Jacobians (FEJ) resolve this by evaluating all Jacobians at a fixed, per-state linearization point:
Propagation: The state transition matrix Φ(tk+1,tk) is evaluated using the pre-update (predicted) state rather than the post-update state. This preserves the semi-group property Φ(tk+1,tk−1)=Φ(tk+1,tk)Φ(tk,tk−1).
Update: The measurement Jacobian Hk for a feature is computed at the feature’s initial triangulated estimate (not its current estimate) for all subsequent updates.
In the analytical model, applying FEJ means replacing the integrated increments with expressions computed from the current and previous state estimates:ΔR^k=GIk+1R^(GIkR^)⊤Δp^k=GIkR^(Gp^Ik+1−Gp^Ik−Gv^IkΔtk+21GgΔtk2)This guarantees the correct 4-dimensional unobservable nullspace and prevents the filter from falsely gaining information along the global yaw direction.
The Propagator class (ov_msckf/src/state/Propagator.h) implements the IMU propagation pipeline.Inputs:
A stream of ImuData messages (timestamp, angular rate ωm, linear acceleration am) fed via feed_imu().
A NoiseManager struct holding the continuous-time noise spectral densities (σg, σa, σwg, σab).
A gravity magnitude scalar (normally 9.81 m/s²).
Key methods:
Method
Description
feed_imu(message, oldest_time)
Appends a new IMU reading to the internal buffer and trims measurements older than oldest_time.
propagate_and_clone(state, timestamp)
Collects all IMU readings since the last state time, integrates the mean and covariance step-by-step, then clones the current IMU pose into the sliding window.
Propagates a copy of the IMU state to an arbitrary future timestamp without modifying the filter state — used to provide high-frequency pose outputs between camera updates.
select_imu_readings(...)
Static helper that extracts and (linearly) interpolates IMU readings in a given time window.
Propagator maintains a cache that is invalidated after each EKF update. Subsequent calls to fast_state_propagate re-use a cached propagated state when possible to minimize redundant computation.