Chapters

48 Complementary Filters: Sensor Trust

analytics-ml
data
fusion
complementary

48.1 Start With the Decision

A gyro reacts fast but drifts. An accelerometer holds a long-term reference but shakes during motion.

48.2 Route Overview

This is part 1 of 2. Continue with Complementary Filters: Tuning and Validity.

48.3 Part Objectives

  • Separate gyro drift from accelerometer motion noise.
  • Derive the trust roles in a complementary filter.

48.4 Chapter Roadmap

  • Start With the Story
  • Complementary Filter Trust
  • Phoebe’s Field Notes: Why the Complementary Filter Behaves Like a Physics Ledger
  • Tune Alpha by Motion and Rate

48.5 Start With the Story

Picture a small robot trying to stay upright. One sensor feels quick turns. Another senses which way gravity pulls. The first reacts fast but slowly wanders. The second is steady over time but shakes during motion. Neither gives a perfect answer alone.

An inertial measurement unit is a small set of motion sensors. Its short name is IMU. A complementary filter combines two imperfect views. It trusts the fast view for quick change. It trusts the steady view for slow correction. The two parts support each other.

Start with one angle. Read both sensors at the same moment. Use the quick-turn value to update the last angle. Use the gravity view to pull that result back toward a stable direction. Choose how strongly each part should count. Then compare the estimate with a known pose.

Timing matters. A missed or uneven update changes the result. Vibration can disturb the gravity view. A fixed error can make the quick view wander. Record the test motion, update time, and error. Do not tune on one easy movement.

This first view assumes gentle motion and one angle. Real devices turn in three dimensions and may speed up in any direction. The Practitioner layer builds the test and tuning record. Under the Hood derives the update rule, tracks uncertainty, and shows where this simple blend stops being enough.

Picture an IoT team using the ideas in Complementary Filters and IMU Fusion during a live operations review. A device has produced messy evidence, an analytic step is about to change an alert or control decision, and someone has to explain why the result should be trusted.

Read this page as that path from sensor evidence to accountable action. Start with what the system observes, keep the model or data treatment visible, and finish with the check that would convince an operator, maintainer, or auditor to act.

48.6 Complementary Filter Trust

A complementary filter is a lightweight IMU fusion method that combines gyroscope integration with an accelerometer gravity reference. The gyroscope is responsive over short intervals, but bias and noise accumulate into drift when angular rate is integrated. The accelerometer gives an absolute roll and pitch reference from gravity when the device is not accelerating hard, but it is noisy during vibration and linear motion.

The filter works because those errors are complementary. It trusts the gyroscope for fast changes and uses a small accelerometer correction to pull the estimate back toward the gravity reference over time. In signal terms, the gyroscope path behaves like a high-pass contribution and the accelerometer path behaves like a low-pass correction.

For three-dimensional orientation, name the axis convention before naming the filter. In the usual aircraft convention, roll is rotation about the forward x-axis, pitch is rotation about the lateral y-axis, and yaw is rotation about the vertical z-axis. Wearable systems also need the body-plane mapping: sagittal, coronal, and transverse planes must be tied to the sensor mounting frame. Store that transform with the data; otherwise a correct filter can publish inverted or swapped roll, pitch, and yaw.

Before touching any filter mathematics, pin the vocabulary to a body. Figure 48.1 puts a chest-worn IMU on a person and shows why two of the three angles get a free referee while the third does not.

A person with three anatomical planes marked: the sagittal plane divides left from right, the coronal plane divides front from back, and the transverse plane divides upper from lower, with an IMU on the sternum. Three cards map motions to angles: bowing forward in the sagittal plane is rotation about the left-right axis, called pitch, with gravity reference yes; side-bending in the coronal plane is rotation about the front-back axis, called roll, gravity reference yes; twisting in the transverse plane is rotation about the vertical axis, called yaw, gravity reference no, needing a heading reference.
Figure 48.1: Anatomy fixes the axis convention for a chest-worn IMU — and decides which angles gravity can referee.

Walk the three cards in Figure 48.1 downward. Bowing forward is motion in the SAGITTAL plane, so it rotates the trunk about the left–right axis — that is what the filter will call pitch, and the card marks Gravity reference: YES because the tilt swings gravity across the sensor axes. Side-bending does the same job for roll in the CORONAL plane. The TRANSVERSE plane card is the odd one out: twisting about the vertical never moves the gravity vector, so its chip reads Gravity reference: NO. That one amber card is the entire reason this chapter keeps insisting that yaw needs a magnetometer or another heading source — the accelerometer is blind to it by geometry, not by quality.

Use a complementary filter when you need a simple, reviewable roll/pitch estimator on constrained hardware. Do not treat it as a full state estimator: a 6-DOF accelerometer-plus-gyroscope IMU does not observe yaw drift without another reference such as a magnetometer, visual landmark, wheel odometry, or external heading source.

The mathematical gist. The chapter’s 10 ms update first integrates the gyro from 8.00° to 8.12°, then blends 98% of that prediction with 2% of the accelerometer’s 6.00° tilt to obtain 8.0776°. That small correction corresponds to a 0.495 s time constant and leaves 1.82° of an initial 5° drift after 50 equal updates.

Math Bridge · guided foundationsHow does 0.98 turn gyro motion into a stable angle?Let Data Dora integrate one step, blend two sensors, and price the remaining drift.

The fusion diagram in Figure 48.2 turns the worked roll update into a complete evidence path and exposes the separate requirement for yaw.

IMU fusion architecture: a 3-axis gyroscope, 3-axis accelerometer, and 3-axis magnetometer feed a calibration unit. The gyroscope and accelerometer feed a fusion filter for roll and pitch; the accelerometer also supports pitch and roll calculation; the magnetometer supports tilt-compensated yaw. The lower panel labels gyroscope evidence as fast but drifting, accelerometer evidence as a gravity reference for tilt, and magnetometer evidence as a yaw and heading reference.
Figure 48.2: For complementary IMU fusion, the gyro-plus-accelerometer path estimates roll and pitch; yaw must be backed by magnetometer or external heading evidence, or labeled as drifting.

Read Figure 48.2 from calibrated gyroscope and accelerometer inputs into the roll-and-pitch filter, then inspect the magnetometer branch that supplies heading evidence for yaw. The lower comparison explains the blend: the gyro is responsive but drifts, while gravity supplies a slower tilt reference when linear acceleration is controlled. This connects the worked alpha calculation to the running physics ledger: every output axis must name its reference, calibration, sample period, and conditions of observability.

Gyroscope

Measures angular rate. Integration gives smooth short-term attitude changes but accumulates bias drift.

Accelerometer

Measures gravity plus linear acceleration. It can correct roll and pitch when gravity is the dominant acceleration.

Alpha

The blend coefficient. Higher alpha trusts gyro prediction longer; lower alpha applies faster accelerometer correction.

Evidence

Outputs should carry sample period, axis convention, alpha, calibration state, and degraded labels when gravity is unreliable.

Input
Useful Evidence
Weak Assumption
Control
Gyroscope
Bias estimate, temperature range, saturation flags, and angular-rate units.
Assuming integration drift stays small over long periods.
Calibrate bias, track elapsed integration time, and reset or correct with references.
Accelerometer
Gravity magnitude check, vibration level, clipping flags, and mounting orientation.
Treating all acceleration as gravity.
Gate correction during strong linear acceleration or high vibration.
Clock
Actual sample interval, missed samples, timestamp source, and filter update rate.
Using a nominal dt when the loop is jittery.
Use measured dt and publish stale or skipped updates.

Overview Knowledge Check

48.7 Tune Alpha by Motion and Rate

The common one-axis complementary update predicts attitude from the gyroscope, then blends that prediction with the accelerometer-derived attitude. The same idea can be applied to roll and pitch separately, or implemented in quaternion form for a full orientation pipeline.

The alpha value is not a universal constant. It should be chosen from the update period, expected vibration, allowed drift, and how often the accelerometer is a valid gravity reference. A higher alpha makes the output smoother during vibration but slower to correct gyro drift. A lower alpha corrects drift faster but can inject acceleration and vibration into the attitude estimate.

Keep raw and calibrated IMU traces separate during review. A stationary calibrated gyroscope should sit near zero angular rate, while the calibrated accelerometer should show two axes near 0 g and the gravity-facing axis near +1 g or -1 g depending on mounting. Magnetometer channels should be stable in the local field but still need hard-iron and soft-iron checks before they are trusted for heading.

What does “raw” actually look like before anyone applies units? Figure 48.3 shows thirty motionless samples exactly as the driver delivers them — as integer codes.

Three stacked charts of thirty raw samples from a motionless IMU. Gyroscope x, y, and z hover near zero LSB with small distinct bias offsets inside a plus or minus 50 LSB band. Accelerometer x and y sit together near zero while z pins near minus 16384 LSB, the code for minus one g at 16384 LSB per g. Magnetometer axes hold stable different levels around plus 152, minus 78, and minus 158 counts. Cards state each sensor’s range and scale factor.
Figure 48.3: A motionless IMU still speaks in integer codes: bias offsets, one pinned gravity axis, and a steady magnetic field.

None of the numbers in Figure 48.3 is a physical unit yet. The gyroscope panel wobbles inside a ±50 LSB band, and its card gives the decoder ring: 131 LSB per °/s on a ±250 °/s range. The accelerometer’s most important teaching is the z trace pinned near −16,384 LSB — that is not a fault, it is gravity expressed at 16,384 LSB per g, and it will still be there in every “stationary” recording you ever review. The magnetometer’s three levels differ from each other because the local field plus hard-iron bias set a private offset per axis. Flat and boring is the healthy signature here; the next two figures show what turns these codes into checkable physics.

Alpha tuning is meaningless until the inputs have a healthy stationary baseline. Inspect the three charts in Figure 48.4 to establish that baseline before comparing drift under motion.

Gyroscope x, y, and z axes sit near zero angular rate with small noise. Accelerometer x and y axes sit near zero g while z sits near minus one g from gravity. Compass axes sit at stable but different offsets. None of the three traces drift while the device is not moving.
Figure 48.4: Three stationary calibrated IMU traces for gyroscope, accelerometer, and compass

The top chart in Figure 48.4 shows Gyroscope — near-zero angular rate, with x, y, and z close to zero. In Accelerometer — gravity on one axis only, z holds about -1g while x and y remain near 0g. The Compass — stable local field, no drift panel keeps three separate offsets without a trend. These are calibration signatures, not interchangeable zero targets; the later complementary filter can be reviewed only after each sensor matches its own physical reference.

The step between those two figures — raw codes in, calibrated traces out — deserves its own arithmetic. Figure 48.5 walks one sample per sensor through both corrections so the calibrated traces stop being magic.

Three pipelines, one per sensor. A gyroscope sample of minus 13 LSB divided by 131 LSB per degree per second, minus a rest-average bias, leaves minus 0.02 degrees per second against a target of white noise around zero. An accelerometer sample of minus 16650 LSB divided by 16384 LSB per g, minus a small offset, leaves exactly minus one g against a target of gravity on z only. A magnetometer sample of 152 counts times 0.6 microtesla per LSB, minus a 59.2 microtesla hard-iron offset, leaves 32 microtesla of steady local field.
Figure 48.5: Scale first, bias second: one stationary sample per sensor walked from integer code to checkable physical target.

Read one row of Figure 48.5 end to end. The accelerometer’s −16,650 LSB becomes −1.016 g at step 1 · APPLY SCALE, and only the second step, 2 · REMOVE BIAS, brings it to the clean −1.000 g the calibrated chart displayed. The order matters for review: scale converts codes to units, bias centres the units on the physics, and the STATIONARY TARGET column — 0 °/s, −1 g, steady field — is what a reviewer can actually check. If a “calibrated” trace misses its target at rest, one of these two numbers was wrong, and no amount of filter tuning downstream will repair it.

Gyroscope angle is obtained by integrating angular rate, commonly with a rectangle or trapezoidal numerical rule. That integration also accumulates bias and white noise: a class trace can show tens of degrees of apparent angle drift over about 30 seconds even though the gyroscope itself is unaffected by earth gravity. Accelerometer tilt estimates avoid long-term drift but are noisy and sluggish when filtered, so they are best treated as roll and pitch correction evidence rather than a complete attitude solution.

“Integrating angular rate” sounds abstract until you see that each 10 ms interval simply contributes one slice of area under the rate curve. Figure 48.6 zooms into a single slice below and prices the difference between the two common rules.

A rising gyro rate curve with samples every 10 milliseconds. Between the samples reading 10.0 and 12.0 degrees per second, the area under the curve is shaded as a trapezoid worth 0.11 degrees of angle. A dashed rectangle at the newer sample’s height overshoots by a red triangular sliver worth 0.01 degrees. A card works the trapezoid formula, compares the 0.12 degree rectangle result, and notes that no integration rule removes bias.
Figure 48.6: One angle step is one trapezoid of area under the gyro rate curve — and the rectangle rule overpays by a visible sliver.

Read the shaded slice in Figure 48.6: it sits between two real samples, ω[k−1] = 10.0 °/s and ω[k] = 12.0 °/s, over one Δt = 0.01 s interval. The trapezoid averages the two rates and books 0.11° of angle; the dashed rectangle at the newer sample’s height would book 0.12°, overpaying by the red sliver — which is exactly why the chapter’s quick 8.00 → 8.12 update is the rectangle answer while a trapezoidal integrator lands on 8.11. Note what the side card refuses to promise: a finer Δt shrinks that geometric sliver, but any rule faithfully integrates whatever bias hides in ω. Sharper integration buys motion accuracy, never drift immunity.

So how bad can that integrated bias get? Figure 48.7 runs the classic classroom experiment: rock a board back and forth between 0° and 90° for half a minute and watch the integrated angle in the lower panel walk away.

Two charts share a 30-second time axis. The gyroscope rate oscillates symmetrically around what looks like zero, with a dashed marker revealing the true mean at minus 1.7 degrees per second. Below, the true rocking angle repeats between 0 and 90 degrees while the gyro-integrated estimate rides the same motion but slides steadily downward, ending about 51 degrees low. A card computes error equals bias times time and contrasts the square-root-of-time noise random walk with the linear bias ramp.
Figure 48.7: A bias invisible in the rate chart compounds into fifty-one degrees of angle error in thirty seconds of integration.

The top panel of Figure 48.7 looks perfectly healthy — the rocking is symmetric and no single sample is suspicious — yet the dashed line marks its mean = −1.7 °/s, not 0. The integral sign between the panels is doing the damage: every biased sample is added and never forgotten, so the red card’s bill, error = bias × time, reaches −1.7 °/s × 30 s ≈ −51° by the right edge. The card also separates the two failure currencies: noise integrates into a slow random walk that grows like √t, while bias buys a straight ramp that grows like t. Calibration shrinks the ramp’s slope; only an external reference — gravity, in this chapter — can keep paying it off.

The blend factor only makes sense after seeing what each IMU channel gets wrong over the same motion. The paired chart in Figure 48.8 holds the time window constant so the tuning discussion can separate accumulated bias from sample-by-sample noise.

Two charts over the same 30-second window: gyro-integrated angle drifting about 50 degrees, and accelerometer-derived angle staying noisy but driftless.
Figure 48.8: Same window, same motion, opposite failure modes – exactly why a complementary filter blends the two instead of trusting either alone.

Compare the two traces in the chart Figure 48.8 at 0s and 30s. The Gyro-integrated angle accumulates small angular-rate errors until the annotation marks roughly 50 deg drift by t = 30s. The Accelerometer-derived angle remains noisy on each sample, yet gravity resets its reference so it has no matching long-term drift. A larger alpha trusts the fast gyro branch for short motion; the complementary term must still pull the estimate toward the driftless gravity reference. The chosen alpha and sample interval therefore belong in the review record because motion spectrum and update rate set how these two labelled failure modes trade off.

Common accelerometer tilt estimates
pitch = atan2(-ax, sqrt(ay^2 + az^2))
roll  = atan2( ay, az )

Axis signs vary by board and mounting. Record the coordinate frame,
unit conversion, and body transform before comparing values across devices.

Those two atan2 lines have a picture behind them, and it is worth seeing once properly. Figure 48.9 draws the 20°-rolled device and shows where the numbers inside atan2 come from.

A device outline rolled 20 degrees from the true vertical with gravity drawn straight down at one g. Construction lines project gravity onto the body axes: 0.34 g on the lateral y axis and 0.94 g on the device’s vertical z axis. A card computes roll equals atan2 of 0.34 and 0.94 equals 20 degrees and gives the pitch formula. A caution card checks that the total magnitude equals 1.00 g and warns that braking, lifts, and vibration break the assumption.
Figure 48.9: Tilt is recovered from gravity’s projections: two shadows on the body axes, one atan2 call, no integration anywhere.

In Figure 48.9 the device’s blue z — device up axis leans 20° away from the dashed true vertical, and gravity — which never moves — casts two shadows onto the body frame: ay = 0.34 g on the lateral axis and az = 0.94 g along the device’s vertical. atan2 of those two shadows returns exactly the roll = 20° the geometry started with, and because the answer is a ratio, the strength of gravity cancels out — nothing is integrated, so nothing can drift. The amber card carries the licence condition the formulas hide: the magnitude check √(0.34² + 0.94²) = 1.00 g is what certifies the shadows as gravity’s. When that magnitude leaves 1 g, the same trigonometry runs happily on the wrong force — which is precisely the failure the validity-gate section below is built to catch.

Worked example: one roll update at 100 Hz
previous roll estimate: 8.00 deg
gyro roll rate: 12.0 deg/s
sample interval dt: 0.01 s
accelerometer roll estimate: 6.00 deg
alpha: 0.98

gyro prediction:
roll_gyro = 8.00 + 12.0 * 0.01 = 8.12 deg

complementary update:
roll_new = alpha * roll_gyro + (1 - alpha) * roll_accel
roll_new = 0.98 * 8.12 + 0.02 * 6.00
roll_new = 7.9576 + 0.1200
roll_new = 8.0776 deg

Interpretation:
The estimate follows the gyro's fast motion but is nudged 0.0424 deg toward
the accelerometer gravity estimate during this 10 ms update.

The arithmetic above is correct but linear text hides the architecture. Figure 48.10 lays the same update out as the signal loop it really is, with every intermediate value on the wire.

Signal-flow diagram of one complementary filter update. The fast path takes the 12.0 degree per second gyro rate, multiplies by the 0.01 second interval, adds the previous 8.00 degree estimate to form the 8.12 degree prediction, and scales it by alpha 0.98 to 7.9576 degrees. The slow path converts accelerometer readings through atan2 to 6.00 degrees and scales by 0.02 to 0.1200 degrees. A summing node outputs the new 8.08 degree estimate, which feeds back as the next cycle’s previous estimate. Chips give the 0.50 second time constant, the 0.32 hertz crossover, and note that yaw never enters the loop.
Figure 48.10: The worked roll update as a living loop: a fast gyro path weighted 0.98, a slow gravity correction weighted 0.02, and a feedback edge that never rests.

Two bands in Figure 48.10 carry the whole philosophy. The FAST PATH does almost all the work — its prediction arrives at the Σ node carrying 7.9576° of the answer — while the SLOW CORRECTION contributes a humble 0.1200°. The part the worked example cannot show is the feedback edge across the top: the fresh 8.08° becomes next cycle’s “previous θ”, so the 0.02 correction is applied again 100 times every second. That repetition is what the left chip prices as τ = Δt/(1−α) = 0.50 s, and the middle chip translates into a crossover near 0.32 Hz — below it the gravity reference wins, above it the gyro does. The amber chip repeats this chapter’s standing warning at the exact place designers forget it: yaw never enters this loop, so publish its drift label with the output.

Condition
Alpha Direction
Reason
Validation Check
High vibration
Increase alpha or gate correction.
Accelerometer samples include vibration and may not represent only gravity.
Compare attitude noise during motor-on and motor-off tests.
Visible drift
Decrease alpha after checking gyro bias.
The gravity correction is too slow for the observed bias and update rate.
Run stationary drift tests over the expected operating temperature range.
Loop jitter
Use measured dt before retuning alpha.
A wrong sample interval corrupts the gyro prediction term.
Log dt distribution and skipped samples under CPU load.
Fast linear motion
Hold or reduce accelerometer correction temporarily.
The accelerometer includes non-gravity acceleration during maneuvers.
Gate correction when acceleration magnitude is far from 1 g.
Correction time-scale example
sample interval dt: 0.01 s
alpha: 0.98

approximate time constant:
tau = dt / (1 - alpha)
tau = 0.01 / 0.02 = 0.50 s

If gyro integration starts 5.0 deg away from the gravity reference:
after 0.50 s, remaining error is about 5.0 * exp(-1) = 1.84 deg
after 1.00 s, remaining error is about 5.0 * exp(-2) = 0.68 deg
after 2.50 s, remaining error is about 5.0 * exp(-5) = 0.03 deg

Interpretation:
At 100 Hz and alpha 0.98, drift correction is visible within seconds,
but each individual update still heavily favors the gyro prediction.

Practitioner Knowledge Check

48.8 Continue to the Next Part

Carry this evidence into Complementary Filters: Tuning and Validity, which begins with Kalman state-space bridge.