This solution is only for normal mount of sensor package (see Fig 1)When we read accelerometer values, we get measurements with Earth gravity. How to remove gravity amount?
Gravity is the vector in direction to center of Earth. Accelerometer values (for Ox, Oy, Oz axis) contains gravity vector's projections (projection, because of tilt of sensor: sensor can have pitch and roll angles not equals to 0!). We need to remove gravity projections to get clear values of acceleration.
Fig 1 |
Fig 2 (Oy is "out from eyes") |
So,
Ok, let's define gravity component on Oy axis. See Fig 3:
Fig 3 (Ox is "out from eyes") |
So,
Ok, let's define gravity component on vertical, Oz axis.
Projection gz has some unknown angle γ between Oz and vector of gravity g. And how to define this angle γ ? It's easy: we know the theorem about orths:
And gz = g * cos γ. We need to find cos γ. From this theorem: cos2γ = 1 - (cos2p + cos2r).
We know that cos2x = 0.5 * (1 + cos2x) so, cos2γ = 1 - (0.5*(1 + cos2p) + 0.5*(1 + cos2r)) = -0.5 * (cos2r + cos2p).
And now:
So, we will use
with correction of sign (direction of gz) by pitch/roll amounts.
These formulas are in g units, not in m/sec2! We suppose |g| = 1. So, you need to multiply by g constant (9.8). But more correct may be to use |g| = sqrt(Accx2 + Accy2 + Accz2) instead of 1
Here is the example in C:
#define DEG2RAD(D) ((D)*0.01745329251994329576) typedef struct accv_t { double v[3]; // values of 3 axis of accelerometer } accv_t; accv_t corr_gravity(double ax, double ay, double az, double pitch, double roll) { /* XXX: for normal mount!!! Other not implemented */ double gx, gy, gz, tmp; gx = sin(DEG2RAD(pitch)); gy = sin(DEG2RAD(roll)); tmp = cos(DEG2RAD(2*pitch)) + cos(DEG2RAD(2*roll)); gz = 0.70710678118654752440 * sqrt(fabs(tmp)); ax += gx; ay += gy; if (fabs(pitch) > 90.0 || fabs(roll) > 90.0) { az -= gz; } else { az += gz; } return ((accv_t){ .v = {ax, ay, az}}); }NOTE: condition abs(pitch) > 90° || abs(roll) > 90° => invert gz.
On real accelerometer values I got:
sensor:
Ax = 0.287g
Ay = -0.094g
Az = -0.928g
corrected:
Ax = -0.006g
Ay = 0.006g
Az = 0.022g
See also How to convert accelerometer values to path/coordinates