# When Accelerometer Roll Estimation Fails: The Pitch Singularity

> As pitch approaches 90 degrees the accelerometer roll estimate becomes unstable while the sensor barely moves. Why the information disappears, what a regularization coefficient buys, what it costs, and the measured tradeoff across five values of the coefficient.

![A GY-521 MPU-6050 module standing on its pin-header edge so the sensor X axis points straight up and gravity straight down along the same line, in front of the measured plot from the experiment where the roll estimate swings through more than 150 degrees while pitch is held at almost minus 90 degrees](https://embed-studio.com/assets/hero.BTxwEVWr.jpg)

- Thread: MPU-6050 Journey (Experiment #007)
- Published: 2026-09-02
- Tags: Embedded, IMU, MPU6050, STM32, Accelerometer, Attitude, EmbedStudio
- Canonical page: https://embed-studio.com/experiments/mpu6050/experiment-007-mpu6050-roll-regularization

In the previous experiment, we demonstrated how the MPU6050 accelerometer can be
used to estimate sensor attitude from the direction of the gravity vector. The
obtained results were surprisingly good and showed that a low-cost MEMS
accelerometer can provide accurate inclination measurements without long-term
drift.

The mathematical framework used in these experiments follows the approach
described in NXP Application Note
[AN3461, _Tilt Sensing Using a Three-Axis Accelerometer_](https://www.nxp.com/docs/en/application-note/AN3461.pdf).

While exploring the full range of sensor orientations, however, an interesting
problem became apparent. Under certain conditions, the calculated roll angle
becomes unstable despite the sensor remaining almost perfectly stationary.

In this experiment, we investigate this failure mode, explain its cause, and
evaluate a practical modification that can improve the stability of the roll
estimate.

## When Roll Estimation Fails

The roll angle derived from the accelerometer is calculated as:

```c
roll = atan2f(ay, az);
```

where:

- `ax` is the acceleration measured along the X axis,
- `ay` is the acceleration measured along the Y axis,
- `az` is the acceleration measured along the Z axis.

To investigate the behavior of this equation, the sensor was slowly rotated
around its pitch axis while recording accelerometer measurements and calculated
attitude.

The acquisition configuration was unchanged from the previous experiments:

- Sampling rate: 1 kHz
- Digital low-pass filter: approximately 22 Hz

EmbedStudio read the firmware's own variables over SWD for thirty-five seconds,
at about 280 samples per second.

![An EmbedStudio plot of calculated pitch and roll through a slow rotation about the pitch axis. Pitch falls smoothly from zero to minus 89 degrees and comes back. Roll sits near zero for the first thirteen seconds, then breaks up into a large noisy excursion that climbs past 170 degrees and collapses again as pitch returns, with the unstable stretch shaded.](https://embed-studio.com/assets/mpu6050-007-01-roll-instability.CxahotEG.png)
*Figure 1 — One slow sweep about the pitch axis. Pitch (green) moves smoothly to −89.4° and back; roll (red) is quiet until pitch passes about −84°, then swings across the whole ±180° range. The vertical lines near 18 s are the ±180° wrap of [experiment #006](https://embed-studio.com/experiments/mpu6050/experiment-006-mpu6050-accelerometer-inclination.md), reached here by noise rather than by movement.*

For most of the rotation range, the roll estimate behaves as expected. However,
as the pitch angle approaches ±90°, the roll signal becomes increasingly
unstable.

The surprising part is that the sensor itself is not undergoing significant roll
motion. Nevertheless, the calculated roll angle starts exhibiting large
fluctuations.

At first sight, this behavior may appear to be a sensor accuracy problem. In
reality, the cause is much more fundamental.

## Why Does It Happen?

Consider what happens when the sensor approaches a pitch angle of −90°.

The gravity vector becomes almost aligned with the sensor X axis:

```text
ax ≈ 1 g
ay ≈ 0 g
az ≈ 0 g
```

The roll calculation therefore approaches:

```c
roll = atan2f(0, 0);
```

In practice, accelerometer measurements are never exactly zero. Even a stationary
sensor contains measurement noise.

Instead of:

```text
ay = 0
az = 0
```

the sweep above measured, averaged over a second near the worst orientation:

```text
ay = 0.019 g
az = 0.018 g
```

These errors are tiny compared to the 1 g gravity signal, but they are now
comparable to the quantities used to calculate roll.

Consequently, very small variations in the measured acceleration can produce
surprisingly large changes in the estimated angle.

This effect is not specific to the MPU6050. It is a consequence of the geometry
of the measurement itself.

As discussed in AN3461, accelerometer-based attitude estimation relies entirely
on the direction of the gravity vector. The roll equation uses the projection of
this vector onto the YZ plane. As the gravity vector approaches the X axis, this
projection becomes increasingly small, making its direction highly sensitive to
measurement errors.

![Two sensor coordinate frames with the YZ plane drawn as a shaded panel. In the first the acceleration vector points into the octant and its projection onto the YZ plane is a long arrow whose direction is the roll. In the second the vector lies along the X axis and its projection is a single dot at the origin, drawn to the same scale.](https://embed-studio.com/assets/mpu6050-007-02-gravity-projection.By-DUOXQ.svg)
*Figure 2 — Roll is the direction of the acceleration vector's projection onto the YZ plane. Away from the singular orientation that projection is nearly a full g long. At the orientation measured in figure 1 it is 0.026 g — the dot at the origin, drawn to the same scale — and its components carry about 0.008 g of noise.*

At exactly ±90° pitch, the projection disappears completely.

The accelerometer therefore contains no information that can be used to
determine roll in this configuration.

## Can We Improve the Situation?

Although the missing information cannot be recovered, we can modify the
calculation to reduce its sensitivity to noise.

The idea is simple: prevent the second argument of `atan2f()` from becoming
arbitrarily small.

A modified roll calculation can be written as:

$$
\phi_\mu = \operatorname{atan2}\left( a_y,\ \sqrt{a_z^2 + \mu\,a_x^2} \right)
$$

where $\mu$ is a regularization coefficient.

When $\mu = 0$ the equation reduces to the original roll calculation.

As the sensor approaches ±90° pitch, $a_x$ approaches ±1 g while $a_z$
approaches zero. The additional term therefore prevents the denominator from
collapsing completely.

There is one detail the written form hides. A square root is never negative, so
a denominator built out of one would confine the result to −90°…+90° and the
estimator could never report a board tipped past vertical. The sign of $a_z$ has
to be carried explicitly, which is why the firmware spells it:

```c
void ahrs_estimate_regularized_attitude(const vector_3f_t* const acceleration,
        ahrs_attitude_t* const attitude, const float mu)
{
    attitude->roll = atan2(acceleration->y,
            copysignf(1.0f, acceleration->z) *
            sqrtf(mu * acceleration->x * acceleration->x +
                  acceleration->z * acceleration->z));
    attitude->pitch = atan2(-acceleration->x,
            sqrtf(acceleration->y * acceleration->y +
                  acceleration->z * acceleration->z));
}
```

The pitch calculation is untouched. Its own square root is a length, and pitch is
correctly restricted to −90°…+90° by it.

The price is that we deliberately modify the ideal attitude equation.

This introduces an engineering tradeoff:

```text
smaller μ
    better accuracy
    weaker stabilization

larger μ
    stronger stabilization
    larger estimation error
```

Before performing measurements, we can estimate this error analytically.

## Analytical Error Estimation

Assuming the accelerometer measures only gravity, the normalized acceleration
components for roll $\phi$ and pitch $\theta$ are:

$$
a_x = -\sin\theta
$$

$$
a_y = \sin\phi\cos\theta
$$

$$
a_z = \cos\phi\cos\theta
$$

Substituting these values into the regularized roll equation gives:

$$
\phi_\mu = \operatorname{atan2} \left( \sin\phi\cos\theta,\ \sqrt{ \cos^2\phi\cos^2\theta + \mu\sin^2\theta } \right)
$$

which can be rewritten as:

$$
\phi_\mu = \arctan \left( \frac{\tan\phi} {\sqrt{ 1+\mu\dfrac{\tan^2\theta}{\cos^2\phi} }} \right)
$$

The resulting estimation error is:

$$
E_\phi = \phi_\mu - \phi
$$

This equation allows us to predict the maximum error introduced by a given value
of $\mu$.

## Maximum Error Within Typical Operating Ranges

The table below shows the theoretical worst-case roll error for several
symmetric operating ranges.

The percentage indicates the error relative to the maximum true roll angle
within the specified range.

| Range | μ = 0.1 | μ = 0.01 | μ = 0.001 | μ = 0.0001 |
| --- | --: | --: | --: | --: |
| ±30° | 0.536° · 1.79 % | 0.055° · 0.18 % | 0.0055° · 0.018 % | 0.00055° · 0.0018 % |
| ±45° | 2.608° · 5.80 % | 0.284° · 0.63 % | 0.0286° · 0.064 % | 0.00286° · 0.0064 % |
| ±60° | 10.575° · 17.63 % | 1.425° · 2.38 % | 0.148° · 0.247 % | 0.0149° · 0.025 % |
| ±85° | 69.595° · 81.88 % | 44.008° · 51.77 % | 15.467° · 18.20 % | 3.210° · 3.78 % |

*Table 1 — Worst-case roll error introduced by the regularization term, over a symmetric range of roll and pitch. Theory only; no measurement is involved.*

Several observations can immediately be made.

For applications limited to moderate angles, such as ±30° or ±45°, even
relatively large values of $\mu$ introduce only a small error.

As the operating range expands towards the singular orientation, the cost of
regularization increases dramatically.

This is an important indication that regularization improves numerical stability
but does not solve the underlying observability problem.

## Error Distribution

To better visualize the effect of regularization, figures 3 and 4 show the
theoretical roll error as a function of both roll and pitch.

**Both surfaces are drawn on the same vertical scale**, because the whole point
of the pair is that one is far taller than the other.

![A three-dimensional surface of the absolute roll error against roll and pitch for a regularization coefficient of 0.01. The surface is almost flat over the middle of the square and rises steeply into four corner peaks reaching 44 degrees, with contour lines drawn on the floor and the origin marked.](https://embed-studio.com/assets/mpu6050-007-03-error-surface-mu-0p01.DhqfC0Sc.png)
*Figure 3 — Theoretical roll estimation error introduced by regularization coefficient μ = 0.01. The error is under a tenth of a degree over most of the useful range and reaches 44.0° in the corners, where both angles approach 85°.*

![The same surface for a regularization coefficient of 0.1, drawn on the same vertical scale. It rises much earlier and its corner peaks reach 70 degrees.](https://embed-studio.com/assets/mpu6050-007-04-error-surface-mu-0p1.luYOtvuW.png)
*Figure 4 — The same, for μ = 0.1, on the same axes. Ten times the coefficient is roughly ten times the error while the error is small, but the corner peak only grows from 44.0° to 69.6° — the estimator is already saturated there.*

The error is smallest near the origin, where the original roll equation is
already well conditioned.

As the sensor approaches the problematic orientations, the error increases
rapidly.

Larger values of $\mu$ produce substantially stronger distortion of the estimated
attitude.

## Experimental Verification

To verify the analytical predictions, several regularized estimators were
evaluated simultaneously using the same accelerometer samples.

The following coefficients were tested:

```c
enum {
    N_REG_VALS = 5,
};

float mu[N_REG_VALS] = {
    0.0f,
    0.1f,
    0.01f,
    0.001f,
    0.0001f,
};
```

The corresponding attitude estimates were stored in arrays:

```c
ahrs_attitude_t attitude_reg[N_REG_VALS];
ahrs_attitude_t attitude_reg_deg[N_REG_VALS];
```

After each accelerometer update, all estimators were evaluated:

```c
for (uint8_t i = 0; i < N_REG_VALS; ++i) {

    ahrs_estimate_regularized_attitude(
        &accel_g,
        &attitude_reg[i],
        mu[i]
    );

    attitude_reg_deg[i].roll =
        rad_to_deg(attitude_reg[i].roll);

    attitude_reg_deg[i].pitch =
        rad_to_deg(attitude_reg[i].pitch);
}
```

This guarantees that every estimator receives exactly the same accelerometer
measurement. The only difference between the outputs is the value of $\mu$.

Nothing had to be rebuilt to look at them. The five arrays are ordinary firmware
variables, so EmbedStudio read all five roll estimates and the pitch out of the
running target and plotted them together.

The sensor was then slowly rotated through the problematic region while all five
roll estimates were recorded.

## Experimental Results

![Two stacked EmbedStudio plots over the same five seconds. The upper one shows pitch falling from minus 79 to minus 89 degrees. The lower one shows five roll estimates that start together near three degrees and fan apart as pitch approaches ninety, the unmodified one climbing past eighty degrees while the most strongly regularized one stays near four.](https://embed-studio.com/assets/mpu6050-007-05-roll-comparison.CNjOnqu9.png)
*Figure 5 — The approach to the singular orientation, 11.5 s to 16.25 s of the same sweep. Pitch (top) goes from −78° to −89°. The five roll estimates start together and fan apart in order of μ. The window stops at 16.25 s, just before a_z changes sign; past that point every estimator correctly reports a board that has gone past vertical, which is a real change of orientation rather than the noise this figure is about.*

The measurements confirm the analytical predictions.

The original estimator ($\mu = 0$) becomes increasingly unstable as the pitch
angle approaches the singular orientation.

Increasing $\mu$ progressively reduces the observed fluctuations.

At the same time, the estimates begin to deviate from the original attitude
calculation.

The larger the value of $\mu$, the earlier this deviation becomes visible.

To put numbers on it, the Analysis panel was pointed at the last 1.25 s of that
window, where the board is nearly still — pitch moves by 1.38° over the whole
stretch.

![An EmbedStudio plot of the five roll estimates over 1.25 seconds near the singular orientation, with the Analysis panel underneath reporting the count, mean, standard deviation, minimum, maximum and peak-to-peak of each one.](https://embed-studio.com/assets/mpu6050-007-06-analysis-singular.D8xCjeCL.png)
*Figure 6 — The same five estimates over 1.25 s at a pitch of −88.4°, measured by the Analysis panel. Standard deviation runs from 14.76° at μ = 0 down to 0.61° at μ = 0.1; peak-to-peak from 59.3° to 3.1°.*

| μ | Mean | Std. dev. | Peak-to-peak |
| --: | --: | --: | --: |
| 0 | 47.94° | 14.76° | 59.28° |
| 0.0001 | 42.83° | 11.00° | 43.99° |
| 0.001 | 27.29° | 4.89° | 22.33° |
| 0.01 | 10.68° | 1.84° | 8.95° |
| 0.1 | 3.48° | 0.61° | 3.06° |

*Table 2 — The five estimates over the same 1.25 s, as EmbedStudio measured them. The board's pitch moved by 1.38° over the whole window.*

Two things are worth reading off that table.

The wobble falls by a factor of 24 between the unmodified estimator and the
strongest one tested. The pitch, meanwhile, moved by less than a degree and a
half. **A 59° swing in roll came out of an orientation that barely changed.**

And the means differ as much as the spreads do — 47.9° against 3.5°. All five
numbers describe the same physical orientation. That is the clearest statement of
the problem there is: when a quantity is not observable, five estimators can all
be reasonable and all disagree.

## What It Costs at Ordinary Angles

The other half of the tradeoff is easier to miss, because there is nothing to
see. A second recording swept the board through arbitrary inclinations well away
from the singular orientation, reaching ±45° of roll and −38° to +20° of pitch.

![Two stacked EmbedStudio plots over twelve and a half seconds. The upper one shows pitch moving between minus 38 and plus 20 degrees. The lower one shows five roll estimates swinging between minus 37 and plus 45 degrees, drawn on top of one another so only the last one plotted is visible.](https://embed-studio.com/assets/mpu6050-007-07-arbitrary-inclinations.BhMv02rw.png)
*Figure 7 — All five estimates over an ordinary ±45° workout. Every curve is drawn; they coincide to within the line width. The legend is the only way to tell there are five of them.*

The differences are there, and they follow the coefficient exactly:

| μ | Median difference from μ = 0 |
| --: | --: |
| 0.0001 | 0.0001° |
| 0.001 | 0.0008° |
| 0.01 | 0.0052° |
| 0.1 | 0.0298° |

*Table 3 — Typical deviation from the unmodified roll estimate over the ±45° recording. A factor of ten per decade of μ, as Table 1's worst cases predict.*

The worst case matters less here than it looks. The largest single deviation over
that recording is about 2.7°, and it is the same 2.7° for μ = 0.0001 as for
μ = 0.01 — which is proof that it is not the coefficient. It is the acquisition:
EmbedStudio reads each variable in its own SWD transaction, so during a fast
movement two channels can come from firmware iterations a millisecond apart. That
skew is larger than the effect being measured, so **this recording confirms that
the cost is small without being able to resolve how small.** The median, where
the skew averages out, is what carries the ladder.

## What Did We Actually Fix?

It is tempting to view the regularized equation as a solution to the problem.

In reality, it is not.

The regularization improves the numerical behavior of the estimator, but it does
not provide any additional information.

When gravity aligns with the sensor X axis, the accelerometer still cannot
determine rotation around that axis.

The modified equation simply constrains the behavior of the estimator when the
available information becomes insufficient.

In other words:

> We have made the estimator more stable, but we have not made the accelerometer
> more informative.

This distinction is important when designing a complete attitude estimation
system.

## Conclusions

The classical accelerometer roll calculation becomes increasingly sensitive to
noise as the gravity vector approaches the sensor X axis.

This occurs because the projection of gravity used for roll estimation becomes
very small and eventually disappears completely. At −88.4° of pitch that
projection measured 0.026 g against about 0.008 g of noise, and the calculated
roll wandered over 59° while the board's pitch moved by 1.4°.

A regularized roll equation can significantly improve stability by preventing the
denominator of the calculation from approaching zero. Over that same window the
spread fell by a factor of 24, from 14.76° to 0.61°.

The improvement comes at the cost of systematic error.

The coefficient $\mu$ therefore directly controls the tradeoff between stability
and accuracy.

For moderate operating ranges, values around $\mu = 0.001$ introduce negligible
error while providing noticeable stabilization — a worst case of 0.029° within
±45°, and a measured typical deviation of 0.0008° over a real recording. Larger
values produce stronger stabilization but increasingly distort the estimated
attitude.

Most importantly, the experiment demonstrates that the limitation is fundamental.
Regularization can improve the behavior of the estimator, but it cannot recover
information that is absent from the accelerometer measurement.

This naturally leads to the next question:

**Can another sensor provide the missing information?**

The answer comes from the second sensing element inside the MPU6050: the
gyroscope.

## Experiment data

The raw datasets used in this experiment are publicly available in the
[EmbedStudio Experiments repository](https://github.com/Embed-Studio/embedstudio-experiments/tree/main/007-mpu6050-roll-regularization).

The dataset contains:

- the sweep through the singular orientation, in which pitch reaches −89.4° and
  the unregularized roll estimate loses its input;
- the hand-held capture within ±45° used to measure what regularization costs at
  ordinary angles.

Both captures record all five roll estimates side by side. The subscript in
`attitude_reg_deg[i]` is an index into the firmware's coefficient table rather
than a value, and the order is not monotone — the repository's manifest lists
which index carries which value of $\mu$.

All datasets are provided as HDF5 files and can be downloaded and opened with
EmbedStudio or another compatible HDF5 tool.

## Frequently Asked Questions

### Why does accelerometer roll become unstable near 90 degrees of pitch?

Because roll is the direction of the acceleration vector's projection onto the sensor's YZ plane, and that projection shrinks to nothing as gravity lines up with the X axis. On the board measured here, at a pitch of minus 88.4 degrees the projection was 0.026 g, about one thirty-eighth of the vector it came from, while the noise on it was around 0.008 g. The direction of a vector that short is barely determined, so the calculated roll swung across 59 degrees while the pitch moved by 1.4 degrees. It is a property of the geometry, not a fault in the sensor.

### Can regularization fix the accelerometer roll singularity?

No. It makes the estimator better behaved but adds no information. Replacing the roll denominator with the square root of a_z squared plus mu times a_x squared stops it collapsing to zero, which cuts the fluctuation, but when gravity lines up with the X axis the accelerometer still cannot see rotation about that axis. The measured standard deviation near the singular orientation fell from 14.8 degrees at mu equals zero to 0.61 degrees at mu equals 0.1, a factor of 24, and every one of those five answers described the same orientation.

### What value of the regularization coefficient should I use?

It depends on the operating range, and the worst-case error is a closed-form number you can read off before measuring anything. Within plus or minus 45 degrees of roll and pitch, mu equals 0.001 costs at most 0.029 degrees and mu equals 0.01 costs at most 0.28 degrees. Within plus or minus 85 degrees the same two coefficients cost 15.5 and 44 degrees. A value around 0.001 is a reasonable default for moderate ranges, because it is a negligible error where the equation already works and still visibly steadies it where it does not.

### Does the regularization term change the roll calculation at small angles?

Almost not at all. Over a twelve and a half second recording covering plus or minus 45 degrees of roll and pitch, the median difference from the unmodified estimate was 0.0001 degrees at mu equals 0.0001, 0.0008 degrees at mu equals 0.001, 0.005 degrees at mu equals 0.01 and 0.030 degrees at mu equals 0.1. The differences track the coefficient by a factor of ten per decade, exactly as the closed-form error predicts.

### Why does the regularized roll equation need the sign of a_z?

Because a square root is never negative, so a denominator without the sign would confine roll to minus 90 to plus 90 degrees and the estimator could never report a board tipped past vertical. Multiplying the square root by the sign of a_z puts the result back in the correct quadrant and keeps the full minus 180 to plus 180 degree range that the original two-argument arctangent has. Dropping it is a silent halving of the output range.

### Is the accelerometer roll singularity the same thing as gimbal lock?

It is the same kind of problem, arising from the same place. Roll and pitch are a two-angle description of a direction, and at pitch equal to plus or minus 90 degrees that description has a coordinate singularity where roll stops being defined. What is specific to the accelerometer is that the measurement itself carries no information about rotation around gravity, so no change of parameterisation recovers it. A second sensor does.

### What fixes the problem properly?

Another sensor. The accelerometer measures the direction of one vector, and rotation about that vector leaves the measurement unchanged, so the information is genuinely absent rather than merely badly conditioned. A gyroscope measures rotation rate directly and is not blind at that orientation, which is why the next step is combining the two.

## Source Code

The firmware and supporting files for this experiment: https://github.com/Embed-Studio/MPU-6050/releases/tag/experiment_007

- Previous: [MPU6050 Roll and Pitch: Estimating Attitude from the Gravity Vector](https://embed-studio.com/experiments/mpu6050/experiment-006-mpu6050-accelerometer-inclination.md)
- Next: [Experiment #008 — Can a Gyroscope Be Used as an Attitude Sensor?](https://embed-studio.com/experiments/mpu6050/experiment-008-mpu6050-gyroscope-inclination.md)
