Accelerometer Calibration
| This documentation was generated with the assistance of AI. Please report any inaccuracies. |
The com.irurueta.navigation.inertial.calibration.accelerometer package (79 classes) estimates
accelerometer bias and the scale-factor/cross-coupling matrix
from the model introduced in the sensor error model:
Every calibrator needs several measurements of at different, sufficiently varied orientations, together with the corresponding (or enough information to derive it). The 79 classes reduce to 6 distinct algorithms, differing only in how is known and whether the bias is already known:
| Family | How is obtained | Solves for | Min. measurements |
|---|---|---|---|
|
Directly: the full position/orientation/velocity frame at each measurement is known, so gravity rotated into body axes gives exactly. |
+ |
4 (linear) / 10 (non-linear, or 13 without common z-axis) |
|
Same as above |
Only (bias given) |
3 (linear) / 7 (non-linear) |
|
Indirectly: device held static at several unknown orientations; only the magnitude is assumed known (e.g. local standard gravity). |
+ |
10 (13 without common z-axis) |
|
Same as above |
Only |
7 (10 without common z-axis) |
|
Indirectly: device static at several unknown orientations, but at a known geodetic position — gravity
magnitude is derived via |
+ |
10 (13 without common z-axis) |
|
Same as above |
Only |
7 (10 without common z-axis) |
Usage examples
| Javadoc and source links for every class used in the examples below are collected in the Class Reference table at the end of this page. |
The snippets below are simplified illustrations (not full copies of the test suite) showing how to
construct each family’s plain calibrator, run calibrate(), and read back the results. Measurement
collection is elided with // … since in practice it comes from several real orientations/positions
of the device.
KnownFrame
KnownFrameAccelerometerLinearLeastSquaresCalibrator takes a collection of FrameBodyKinematics
(measured specific force plus the known frame it was taken at) and solves for both bias and
:
List<FrameBodyKinematics> measurements = new ArrayList<>();
// ... add FrameBodyKinematics(bodyKinematics, ecefFrame, previousEcefFrame) for each measurement
var calibrator = new KnownFrameAccelerometerLinearLeastSquaresCalibrator(measurements);
calibrator.calibrate();
double[] estimatedBiases = calibrator.getEstimatedBiases();
Matrix estimatedMa = calibrator.getEstimatedMa();
KnownBiasAndFrame
Same measurements, but the bias is already known and passed to the constructor, so only is solved for:
List<FrameBodyKinematics> measurements = new ArrayList<>();
// ... add FrameBodyKinematics measurements as above
double biasX = 0.01, biasY = 0.02, biasZ = 0.03; // known bias, in m/s^2
var calibrator = new KnownBiasAndFrameAccelerometerLinearLeastSquaresCalibrator(
measurements, biasX, biasY, biasZ);
calibrator.calibrate();
Matrix estimatedMa = calibrator.getEstimatedMa();
KnownGravityNorm
The device is held static at several unknown orientations; each StandardDeviationBodyKinematics
measurement only needs the measured kinematics plus its noise standard deviations, and the known
gravity-norm magnitude is passed once to the calibrator:
List<StandardDeviationBodyKinematics> measurements = new ArrayList<>();
// ... add StandardDeviationBodyKinematics(bodyKinematics, specificForceStd, angularRateStd)
// for each static orientation
double groundTruthGravityNorm = 9.81; // m/s^2, e.g. local standard gravity
var calibrator = new KnownGravityNormAccelerometerCalibrator(groundTruthGravityNorm, measurements);
calibrator.calibrate();
double[] estimatedBiases = calibrator.getEstimatedBiases();
Matrix estimatedMa = calibrator.getEstimatedMa();
KnownBiasAndGravityNorm
Same idea, but with a known bias supplied up front so only is estimated:
List<StandardDeviationBodyKinematics> measurements = new ArrayList<>();
// ... add StandardDeviationBodyKinematics measurements as above
double groundTruthGravityNorm = 9.81; // m/s^2
double biasX = 0.01, biasY = 0.02, biasZ = 0.03; // known bias, in m/s^2
var calibrator = new KnownBiasAndGravityNormAccelerometerCalibrator(
groundTruthGravityNorm, measurements, biasX, biasY, biasZ);
calibrator.calibrate();
Matrix estimatedMa = calibrator.getEstimatedMa();
KnownPosition
Instead of an assumed gravity-norm magnitude, the device’s known geodetic position is used to derive
gravity via NEDGravityEstimator internally:
List<StandardDeviationBodyKinematics> measurements = new ArrayList<>();
// ... add StandardDeviationBodyKinematics measurements as above, all taken at the same position
NEDPosition position = new NEDPosition(latitude, longitude, height);
var calibrator = new KnownPositionAccelerometerCalibrator(position, measurements);
calibrator.calibrate();
double[] estimatedBiases = calibrator.getEstimatedBiases();
Matrix estimatedMa = calibrator.getEstimatedMa();
KnownBiasAndPosition
Same as KnownPosition, but with the bias already known:
List<StandardDeviationBodyKinematics> measurements = new ArrayList<>();
// ... add StandardDeviationBodyKinematics measurements as above
NEDPosition position = new NEDPosition(latitude, longitude, height);
double[] bias = new double[]{0.01, 0.02, 0.03}; // known bias, in m/s^2
var calibrator = new KnownBiasAndPositionAccelerometerCalibrator(position, measurements, bias);
calibrator.calibrate();
Matrix estimatedMa = calibrator.getEstimatedMa();
Robust wrapper: RANSACRobustKnownFrameAccelerometerCalibrator
Robust variants of KnownFrame need each measurement’s standard deviation (a
List<StandardDeviationFrameBodyKinematics> instead of a plain FrameBodyKinematics collection) so
that residuals can be weighed, and RANSAC additionally exposes a threshold controlling how large a
residual is still considered an inlier:
List<StandardDeviationFrameBodyKinematics> measurements = new ArrayList<>();
// ... add StandardDeviationFrameBodyKinematics(bodyKinematics, ecefFrame, specificForceStd, angularRateStd)
// for each measurement, including a few outliers
var calibrator = new RANSACRobustKnownFrameAccelerometerCalibrator(measurements);
calibrator.setThreshold(0.1); // m/s^2, default is RANSACRobustKnownFrameAccelerometerCalibrator.DEFAULT_THRESHOLD
calibrator.calibrate();
double[] estimatedBiases = calibrator.getEstimatedBiases();
Matrix estimatedMa = calibrator.getEstimatedMa();
KnownGravityNorm/KnownBiasAndGravityNorm is the accelerometer half of the same idea as
the Tedaldi et al. "Easy" gyroscope calibrator: hold the device
static at several orientations and rely only on the (approximately known, ~9.81 m/s²) magnitude of
gravity — no turntable or precisely known frame needed. In this codebase, the two ideas are implemented
as siblings rather than a single combined class.
|
Linear vs. non-linear solvers
The KnownFrame and KnownBiasAndFrame families additionally offer a linear least-squares variant
(…LinearLeastSquaresCalibrator) alongside the default Levenberg-Marquardt non-linear least-squares
one (…NonLinearLeastSquaresCalibrator). Because is exactly known for
these two families, the model can be rearranged into a linear system solved in closed form (fast, no
initial guess needed); the non-linear form is typically used to refine that solution or when a linear
solution is not accurate enough. The gravity-norm and position families only expose a non-linear solver,
since being known (but not its direction) makes the problem
inherently non-linear.
The robust-estimator wrapper
As described in IMU Calibration, each of the 6 families above has a plain (non-robust) form
plus 5 Robust* outlier-rejection wrappers (RANSACRobust*, MSACRobust*, LMedSRobust*,
PROSACRobust*, PROMedSRobust*), all extending a shared abstract Robust*AccelerometerCalibrator
base. QualityScoredAccelerometerCalibrator is the interface robust variants that use measurement
quality scores (PROSAC, PROMedS) require their input to implement.
| Class group | Purpose |
|---|---|
|
Root marker interfaces implemented by every calibrator (all / non-linear-only, respectively). |
|
Enum distinguishing which measurement container a given calibrator instance expects. |
|
Mixin interfaces exposing estimated bias getters, implemented by the "unknown bias" half of each family. |
|
Interfaces for calibrators that need an ordered measurement list (used by RANSAC/PROSAC-style robust variants). |
|
Interfaces for calibrators taking a plain, unordered measurement collection (the non-robust calibrators). |
Class Reference
Javadoc and source links for the classes used in the examples above:
| Class | Javadoc | Source |
|---|---|---|
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
Where to go next
-
Gyroscope Calibration — the Tedaldi et al. "Easy" calibrator and turntable-based gyroscope calibration.
-
Magnetometer Calibration — the same known-frame / known-norm / known-position structure, applied to hard-iron/soft-iron.
-
Static/Dynamic Interval Detection and Measurement Generation — how static-interval measurements like the ones
KnownGravityNormneeds are actually produced from a raw sensor stream. -
reference.adoc#bibliography — bibliography.