"I know precisely how fast I am spinning. I am simply no longer certain which way is down, where north lies, or whether I have moved at all."
An Inertially Confident AI Agent
Prerequisites
This section assumes the general measurement model (true value plus bias plus zero-mean noise) from Chapter 2, the sampling and noise-density vocabulary from Chapter 3, and the notion of a random walk from Chapter 4. Everything vector-and-rotation stays deferred: coordinate frames arrive in Section 23.2, gravity separation in Section 23.3, and calibration of the error terms named here in Section 23.4. Basic Python and NumPy are enough for the code.
The Big Picture
A modern inertial measurement unit is three separate sensors sharing one silicon package, and the single most useful thing you can know about them is what each one actually measures. An accelerometer does not measure acceleration; it measures specific force. A gyroscope does not measure orientation; it measures angular rate. A magnetometer does not measure heading; it measures a magnetic field vector that includes the Earth and every ferrous object nearby. Get those three sentences into your bones and the rest of Part VI, orientation estimation, dead reckoning, activity recognition, stops being magic and becomes bookkeeping over three noisy, complementary streams.
Three sensors, three physical quantities
The triad is usually sold as a "9-axis IMU" (three axes each), and treating it as one device hides the physics that determines how you must process it. Each sensor answers a different question about the same rigid body, and each is silent about what the others report.
The accelerometer measures specific force: the non-gravitational force per unit mass acting on the sensor case, expressed in the sensor's own axes. This is the point every newcomer trips on. A phone lying flat and still on a table reads roughly \(9.81\ \mathrm{m/s^2}\) upward, not zero, because the table pushes up on it and gravity is not a force the device can feel; in free fall the same device reads zero. The clean statement is \[ \tilde{\mathbf a} = \mathbf a_{\text{lin}} - \mathbf g + \mathbf b_a + \mathbf n_a, \] where \(\mathbf a_{\text{lin}}\) is true linear acceleration, \(\mathbf g\) is the local gravity vector, \(\mathbf b_a\) is a slowly varying bias, and \(\mathbf n_a\) is white noise. Because gravity is always in the reading, an accelerometer at rest is a superb tilt sensor: the direction of the measured vector points along "down." Under motion, gravity and linear acceleration are tangled, and untangling them is the whole job of Section 23.3.
The gyroscope measures angular rate \(\boldsymbol\omega\), the rotational velocity of the case about its three axes, in radians or degrees per second: \[ \tilde{\boldsymbol\omega} = \boldsymbol\omega + \mathbf b_g(t) + \mathbf n_g. \] It knows nothing about position or absolute orientation. To get an angle you must integrate rate over time, and integration is where a gyroscope's small, drifting bias \(\mathbf b_g(t)\) becomes ruinous: a constant \(0.01^\circ/\mathrm{s}\) bias, tiny on any single sample, accumulates to \(36^\circ\) of heading error in one hour. That single fact drives almost every design choice in Chapter 24.
The magnetometer measures the local magnetic flux density \(\mathbf m\), a vector combining the Earth's field (about 25 to 65 microtesla, tilted by the local inclination angle) with fields from nearby motors, speakers, steel beams, and the device's own currents: \[ \tilde{\mathbf m} = \mathbf m_{\text{earth}} + \mathbf m_{\text{disturb}} + \mathbf b_h + \mathbf n_h. \] On a clean day the horizontal component points toward magnetic north, which is why the magnetometer is the only member of the triad with an absolute, non-drifting heading reference. It pays for that with vulnerability to disturbance: walk past a refrigerator and your "north" swings.
Common Misconception: magnetic north is not true north
A calibrated magnetometer heading is not a compass-perfect geographic bearing: magnetic north and true north differ by the local declination angle, from near zero to over 20 degrees depending on location, and that angle drifts slowly as Earth's field shifts. A system that skips declination correction, typically a lookup against a field model such as the World Magnetic Model, is wrong by a fixed offset even after hard-iron and soft-iron calibration (Section 23.4) has removed every local distortion. The error hides during bench testing near the equator's low-declination band and becomes glaring once the same code ships to Alaska or northern Canada, where it can exceed 15 degrees.
Key Insight
The three sensors fail in complementary ways, which is exactly why they are packaged together. The gyroscope is smooth and trustworthy over seconds but drifts over minutes. The accelerometer and magnetometer are noisy and easily perturbed instant to instant but have no long-term drift because gravity and the Earth's field do not wander. Fusion (Chapter 24) is the art of borrowing the gyro's short-term stability and the accelerometer and magnetometer's long-term anchoring, so each covers the other's weakness.
Inside the MEMS: where the numbers come from
Understanding the transduction explains the error terms rather than leaving them as mysterious datasheet lines. Consumer accelerometers and gyroscopes are MEMS devices, microscopic mechanical structures etched into silicon, and their imperfections follow directly from being tiny springs and masses.
A MEMS accelerometer is a proof mass on silicon springs forming a differential capacitor: specific force displaces the mass, changing the capacitance, which readout electronics convert to a number. Spring stiffness drifts with temperature and the mass is measured in femtofarads, so the zero point wanders; that wander is your bias, which is why datasheets quote it over a temperature range. A MEMS gyroscope exploits the Coriolis effect instead: a mass is driven into continuous vibration, and when the case rotates, the Coriolis force \(\mathbf F_c = -2m\,\boldsymbol\omega \times \mathbf v\) pushes the mass sideways in proportion to angular rate, in a deflection read the same capacitive way. Coriolis forces are minuscule, so gyroscopes run noisier and more bias-prone than accelerometers, and sensitive to vibration that mimics the drive motion. Magnetometers use a different physics entirely, usually the Hall effect or anisotropic magnetoresistance (AMR), where a magnetic field bends charge carriers or changes a thin film's resistance; being non-mechanical, they skip that vibration sensitivity but not a hard operating range. A Hall sensor's output grows linearly with field strength only until carrier deflection maxes out, and an AMR film's resistance swing flattens once its magnetization fully aligns with the field, so past roughly a few hundred microtesla the reading clips instead of tracking the true field. That matters near any strong local source, a magnetic phone case, a motor, a speaker magnet, because the sensor then reports a wrong-but-plausible number rather than failing obviously, which is why calibration flags out-of-range samples instead of trusting every reading equally.
In Practice: the ESC that felt a pothole as a spin
An automotive electronic stability control (ESC) unit uses a yaw-rate gyroscope to decide whether the car is rotating more than the driver's steering commands, then brakes individual wheels to correct a skid. On one early integration the gyroscope was bolted rigidly near the transmission tunnel; sharp road vibration coupled into the MEMS drive mode and appeared as phantom yaw rate, so on rough pavement the controller occasionally braked a wheel for a skid that was not happening. The fix was not a smarter algorithm first: it was a compliant mechanical mount plus a matched low-pass filter tuned to the vehicle's vibration band, from Chapter 6. The lesson recurs across Part VI: an inertial pipeline that ignores how its transducer physically responds to its mounting will chase ghosts.
The measurement model you will actually code against
For processing, collapse each sensor to bias plus white noise (scale and axis misalignment are real too, but belong to Section 23.4). Two numbers characterize the random part, both straight from the datasheet. Noise density \(\rho\) is the white-noise level per root hertz of bandwidth: an accelerometer at \(150\ \mu g/\sqrt{\mathrm{Hz}}\) has a per-sample standard deviation of \(\sigma = \rho\sqrt{\mathrm{BW}}\), so wider bandwidth buys more noise, which is why you sample only as fast as you need and filter to the band that carries your signal. Bias instability is the floor of the Allan-deviation curve: the slowest, irreducible wander of the zero point that no averaging removes and that dead reckoning integrates into unbounded error. The bias itself is well modeled as a random walk, \(\mathbf b_{k+1} = \mathbf b_k + \mathbf w_k\), the process-noise structure a Kalman filter in Chapter 9 is built to track.
The code below takes a recording from a stationary IMU and recovers these constants: the mean is the bias, the standard deviation over a fixed bandwidth gives the noise density, and watching how the average of ever-longer windows behaves reveals the bias-instability floor. Run it on your own phone logs and the numbers should land within a factor of two of the datasheet.
import numpy as np
def characterize_axis(x, fs):
"""Estimate bias, white-noise density, and a crude bias-instability
floor from a stationary single-axis IMU recording x sampled at fs Hz."""
x = np.asarray(x, dtype=float)
bias = x.mean() # zero-point offset
resid = x - bias
sigma = resid.std() # per-sample white noise
noise_density = sigma / np.sqrt(fs / 2.0) # units per sqrt(Hz)
# Overlapping-average stability: std of block means vs block length.
# The curve stops falling near the bias-instability floor.
floors = []
for m in (10, 50, 200, 1000):
if len(resid) < 2 * m:
break
k = len(resid) // m
block_means = resid[:k * m].reshape(k, m).mean(axis=1)
floors.append((m / fs, block_means.std()))
return bias, noise_density, floors
fs = 200.0 # Hz
gyro_z = np.random.normal(0.02, 0.05, size=60 * int(fs)) # 60 s at rest
bias, nd, floors = characterize_axis(gyro_z, fs)
print(f"bias = {bias:.4f} deg/s")
print(f"noise dens. = {nd*1000:.2f} mdps/sqrt(Hz)")
for tau, dev in floors:
print(f" tau={tau:5.2f}s stability={dev*1000:.2f} mdps")
Right Tool: skip the hand-rolled Allan sweep
The block-mean estimator above is deliberately naive. Production characterization uses a proper overlapping Allan deviation, and the allantools library computes it, with correct confidence intervals and the standard \(\tau\) grid, in essentially one call: allantools.oadev(x, rate=fs, data_type="freq"). That replaces roughly 30 lines of careful windowing and error-bar bookkeeping with three, and it handles the log-spaced averaging times and edge effects that a hand-rolled loop gets subtly wrong. Reach for it whenever you need to quote a real bias-instability number rather than a rough floor.
Research Frontier: learning the error model instead of measuring it
The bias-plus-white-noise model here is decades old and still the production default, but active work asks whether a network can learn a device's error signature directly from raw motion instead of a bench rig, using the self-supervised objectives of Chapter 17 or wearable foundation models pretrained across thousands of devices (Chapter 20). Early results suggest a learned denoiser can suppress correlated, motion-dependent errors that a stationary Allan-deviation sweep never sees, since real bias instability shifts with temperature and orientation in ways a 60-second bench recording cannot capture. Whether such models generalize across manufacturing batches, let alone across vendors, is still open.
Why one sensor is never enough
Put the error signatures side by side and the case for the triad is immediate. The accelerometer alone answers orientation perfectly at rest but lies once the device accelerates, unable to tell a push from a change in "down." The gyroscope alone tracks fast rotations beautifully for a few seconds, then its integrated bias slowly rotates the whole estimate away from truth. The magnetometer alone holds an absolute heading reference indefinitely, until someone opens a laptop nearby. No single stream tells the truth all the time, but together they always do. That structural complementarity, not marketing, is why phones, drones, watches, and cars all carry the same nine axes, and why the models of Chapter 26 train on all three streams at once rather than any one alone.
Exercise
Log 60 seconds of your phone's accelerometer, gyroscope, and magnetometer while it lies flat and still (any sensor-logging app exports CSV). (1) Confirm the accelerometer magnitude sits near \(9.81\ \mathrm{m/s^2}\) and identify which axis carries gravity. (2) Run characterize_axis on each gyroscope axis and compare the recovered noise density to your phone's IMU datasheet. (3) Now slowly wave a steel object near the phone and plot the magnetometer magnitude: quantify how many microtesla of disturbance a common object injects, and relate that to the Earth-field magnitude you measured at rest.
Self-Check
1. A quadcopter hovers perfectly still. What does its accelerometer read, and why is it not zero? 2. Why does a constant gyroscope bias cause bounded orientation error over one second but unbounded error over an hour, whereas a constant accelerometer bias behaves differently for tilt? 3. You halve an IMU's sampling rate and keep the same anti-alias bandwidth. What happens to the per-sample white-noise standard deviation, and what does not change?
What's Next
In Section 23.2, we make the "in the sensor's own axes" caveat precise. Every quantity in this section, specific force, angular rate, magnetic field, was reported in the moving body frame, and to reason about the world we must relate that frame to a fixed one. Coordinate frames and orientation representations are the machinery that turns three axis-locked streams into a statement about how a device is posed in space.