Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

IMU

factors::imu — inertial preintegration. Two factors per group and nothing else, so a choice here is two questions rather than a catalogue.

Preintegration

Integrating raw IMU samples between keyframes would re-integrate the whole interval every time the state changes. Preintegration instead accumulates the measurements into a relative quantity that does not depend on the states — only on the bias linearization point — so a keyframe pair can be re-evaluated in constant time.

ImuPreintegration::new(measurements, params, t0, t1, &bias_ref) accumulates the delta , its covariance, and the bias-correction Jacobians . Everything it produces is gravity-free; the factors reinstate gravity when they build the gravity-corrected state.

Two axes

Which group? se23 models a keyframe as ; sgal3 adds a time coordinate, , making the inter-keyframe interval an estimated quantity — pick it for time-offset or rolling-shutter calibration, se23 otherwise.

Combined or not? This is the split GTSAM draws between ImuFactor and CombinedImuFactor, and it decides the residual dimension.

ImuFactorCombinedImuFactor
se239D, (SE23, SE23, bias)15D, (SE23, bias, SE23, bias)
sgal310D, (SGal3, SGal3, bias)16D, (SGal3, bias, SGal3, bias)

ImuFactor shares one bias variable across the interval and leaves its evolution to a separate edge; CombinedImuFactor takes a bias per keyframe and embeds the random walk in six extra residual rows. Doing both counts that uncertainty twice.

Weighting follows the same split: the shared-bias form uses a information built from measurement noise alone, the combined form the full including the random walk.

A keyframe is a single variable on the group, not separate pose and velocity blocks — the optimizer’s update is then a group right-plus, and the pose/velocity coupling inertial integration produces is the group’s job. The practical consequence is that aiding measurements attach to that state: an SE(3)-only factor cannot connect to an SE23 variable, while PriorFactor<SE23> and MarginalPriorFactor are generic and do.

Error

Folding gravity into the state rather than the residual is what makes the comparison a plain group right-minus. The bias correction is the first-order update of the preintegrated delta for a bias away from its linearization point,

The combined form appends (6 rows).

Jacobian

All four factors are thin wrappers over one evaluate, which returns the residual and three tangent-space blocks. Write for the two Jacobians right_minus reports and for the tangent Jacobian of right_plus. Then

The comes from differentiating with respect to the left argument: .

The bias block expands to

in the tangent order.

The lift from to the gravity-corrected state is a constant matrix, independent of the linearization point, because shares ’s rotation and shifts the rest by gravity terms only:

The combined form appends the bias-walk rows, whose Jacobian is constant:

Every above is reported by the group’s own right_plus, right_minus and adjoint; none of it is hand-derived.

Bias evolution

The non-combined factors need a companion edge, which factors::imu::bias builds as a BetweenFactor<Rn> with zero measurement:

#![allow(unused)]
fn main() {
use apex_solver::factors::imu::{se23, bias_random_walk, bias_random_walk_noise};

problem.add_residual_block(
    &[state_i, state_j, bias],
    Box::new(se23::ImuFactor::new(preintegration)),
    None,
);
problem.add_residual_block_with_noise(
    &[bias, bias_next],
    Box::new(bias_random_walk()),
    None,
    bias_random_walk_noise(&params, dt)?,
);
}

An initial bias prior (an EuclideanPriorFactor on ) is required for observability in every configuration.

SGal(3) and the time row

SGal(3)’s tangent carries a time coordinate, so the residual gains a row , weighted by (with_time_sigma, default 100 µs). That row is the reason to choose SGal(3): it makes the interval a quantity the optimizer can move.

Known limitation. SGal(3)’s group law is — the left operand’s time couples the right operand’s velocity into translation. The residual composes , so it depends on the absolute , while the preintegrated delta corresponds to . A single interval with is correct; chaining these factors across keyframes on a common absolute clock is not. Prefer the se23 factors for multi-keyframe chains until the residual is re-derived in terms of .