### Author Topic: Cell phone Accelerometer g force vector representation maths  (Read 393 times)

0 Members and 1 Guest are viewing this topic.

#### Wilson__

• Regular Contributor
• Posts: 131
• Country:
##### Cell phone Accelerometer g force vector representation maths
« on: June 07, 2024, 11:23:26 pm »
For MEMS Accelerometer as used in cell phone, after reading out three individual g values from x, y and z axis of sensor, what is the maths formula to calculate the 'resultant' vector (direction and magnitude)?   How is the maths notation of 'direction' vector?   For aeroplane, traditionally it will be three values, pitch, yaw and roll?  Is there a 'single value' for the vector's direction (or may be something called euler angle)?

How to calculate the difference between 'TWO VECTORS'?  For example, if the sesnor is placed flat on table, x and y axis is zero.  Z is 9.81 ms-2 (g value).   Call this VECTOR_0 as base reference.   If I rotate the sesnor and the x,y,z resultant is VECTOR_1.   How to calculate the difference between VECTOR_0 (base reference) and VECTOR_1 (new value)?

Any standard c language library to do the maths?

Many thanks

#### jpanhalt

• Super Contributor
• Posts: 3725
• Country:
##### Re: Cell phone Accelerometer g force vector representation maths
« Reply #1 on: June 07, 2024, 11:53:03 pm »

The following users thanked this post: Wilson__

#### Nominal Animal

• Super Contributor
• Posts: 6766
• Country:
##### Re: Cell phone Accelerometer g force vector representation maths
« Reply #2 on: June 08, 2024, 12:48:17 am »
For MEMS Accelerometer as used in cell phone, after reading out three individual g values from x, y and z axis of sensor, what is the maths formula to calculate the 'resultant' vector (direction and magnitude)?
That is it: $\vec{v} = (x, y, z)$.  Its magnitude is $\lVert \vec{v} \rVert = \sqrt{x^2 + y^2 + z^2}$.  It is often useful to normalize the direction to an unit length vector.  In linear algebra form, I recommend column vectors, so that matrix-vector multiplication always has matrix on the left and vector on the right, and in general, operations have oldest or original rightmost, and advance leftwards.

In math terms:
$$\vec{v} = (x, y, z) = \left[ \begin{matrix} x \\ y \\ z \end{matrix} \right ]$$
Its length (or equivalently magnitude) is
$$n = \lVert\vec{v}\rVert = \sqrt{x^2 + y^2 + z^2}$$
and the unit direction vector is
$$\hat{v} = \left(\frac{x}{n}, \frac{y}{n}, \frac{z}{n}\right) = \left[ \begin{matrix} \frac{x}{\sqrt{x^2 + y^2 + z^2}} \\ \frac{y}{\sqrt{x^2 + y^2 + z^2}} \\ \frac{z}{\sqrt{x^2 + y^2 + z^2}} \end{matrix} \right ]$$
When a vector is normalized, it means the vector is scaled to unit length as above, by dividing each component by the magnitude of the original vector.

Do not use Euler or Tait-Bryan angles, or you will have gimbal lock.  If you need complex rotations, use versors AKA unit quaternions, or equivalently bivectors.

How to calculate the difference between 'TWO VECTORS'?  For example, if the sensor is placed flat on table, x and y axis is zero.  Z is 9.81 ms-2 (g value).   Call this $\vec{v}_0$. If I rotate the sesnor and the x,y,z resultant is $\vec{v}_1$. How to calculate the difference?
You have $\vec{v}_0 = ( x_0, y_0, z_0 )$ and $\vec{v}_1 = ( x_1, y_1, z_1 )$.  First, calculate their lengths/magnitudes/Euclidean norms:
\begin{aligned} n_0 &= \left\lVert \vec{v}_0 \right\rVert &= \sqrt{x_0^2 + y_0^2 + z_0^2} \\ n_1 &= \left\lVert \vec{v}_1 \right\rVert &= \sqrt{x_1^2 + y_1^2 + z_1^2} \\ \end{aligned}
Note that the magnitudes are acceleration in meters per second per second, m·s⁻².  Next, calculate the corresponding unit vectors:
\begin{aligned} \hat{v}_0 &= \left( \frac{x_0}{n_0}, \frac{y_0}{n_0}, \frac{z_0}{n_0} \right) \\ \hat{v}_1 &= \left( \frac{x_1}{n_1}, \frac{y_1}{n_1}, \frac{z_1}{n_1} \right) \\ \end{aligned}
The second direction corresponds to the first direction rotated by angle $\varphi$ around unit axis vector $\hat{a}$:
\begin{aligned} \cos \varphi &= \hat{v}_0 \cdot \hat{v}_1 \\ \vec{a} &= \hat{v}_0 \times \hat{v}_1 \\ \sin \varphi &= \left\lVert \vec{a} \right\rVert \\ \hat{a} &= \frac{\vec{a}}{\left\lVert \vec{a} \right\rVert} \\ \end{aligned}
Note that $-1 \le \hat{v}_0 \cdot \hat{v}_1 \le +1$.  If $\hat{v}_0 \cdot \hat{v}_1 = 1$, the two directions are the same, and $\varphi = 0°$.  If $\hat{v}_0 \cdot \hat{v}_1 = -1$, the two directions are opposite.  In both these cases $\vec{a}$ and thus $\hat{a}$ are undefined.

Any standard c language library to do the maths?
Don't need one, really.
Code: [Select]
#include <math.h>#define  EPS  0.00000001f  // Largest positive value considered zero or neglibletypedef struct {    float x;    float y;    float z;} vec3f;vec3f Vec3f(float x, float y, float z) {    return (vec3f){ .x=x, .y=y, .z=z };}float vec3f_length(vec3f v) {    return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);}float vec3f_dot(vec3f a, vec3f b) {    return a.x*b.x + a.y*b.y + a.z*b.z;}vec3f vec3f_cross(vec3f a, vec3f b) {    return (vec3f){ .x = a.y*b.z-a.z*b.y, .y = a.z*b.x-a.x*b.z, .z = a.x*b.y-a.y*b.x };}vec3f vec3f_unit(vec3f a) {    const float  n = vec3f_length(a);    if (a <= EPS) {        return (vec3f){ .x = 0.0f, .y = 0.0f, .z = 0.0f };    } else {        return (vec3f){ .x = a.x/n, .y = a.y/n, .z = a.z/n };    }}vec3f vec3f_mul(vec3f a, float c) {    return (vec3f){ .x = c*a.x, .y = c*a.y, .z = c*a.z };}vec3f vec3f_div(vec3f a, float d) {    return (vec3f){ .x = a.x/d, .y = a.y/d, .z = a.z/d };}with which the abovementioned problem is solved via
Code: [Select]
    vec3f  v0, v1;    float  n0 = vec3f_length(v0);    float  n1 = vec3f_length(v1);    if (n0 <= EPS) {        // 0 was in free fall, abort    } else    if (n1 <= EPS) {        // 1 was in free fall, abort    }    vec3f  u0 = vec3f_div(v0, n0);    vec3f  u1 = vec3f_div(v1, n0);    float  c = vec3f_dot(u0, u1);    if (c >= 1.0f - EPS) {        // The two orientations are the same; abort.    } else    if (c <= EPS - 1.0f) {        // The two orientations are opposite; abort.    }    vec3f  a = vec3f_cross(u0, u1);    float  s = vec3f_length(a);    if (s >= -EPS && s <= EPS) {        // neglible rotation, so use zero vector.        a = (vec3f){ .x = 0.0f, .y = 0.0f, .z = 0.0f };    } else {        a = vec3f_div(s);    }    float  varphi = atan2f(s, c);  // Better precision than asinf(s) or acosf(c).which gives a as the rotation axis vector, and varphi as the rotation angle around that vector in radians.  Multiply varphi by 360/(2π) ≃ 57.29578f to get the result in degrees.

If you need rotations, then orientation and rotation are best described using versor/bivector
Code: [Select]
typedef struct {    float  x;    float  y;    float  z;    float  r;  // Often listed first; I like to put last for shenanigans} rot3f;rot3f Rot3f(float q, float i, float j, float k) {    float n = sqrtf(q*q + i*i + j*j + k*k);    if (n > EPS)        return (rot3f){ .x = i/n, .y = j/n, .z = k/n, .r = q/n };    else        return (rot3f){ .x = 0.0f, .y = 0.0f, .z = 0.0f, .r = 1.0f };}rot3f rot3f_around(vecf axis, float angle) {    float n = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);    if (n > EPS) {        float c = cosf(angle * 0.5f);        float s = sinf(angle * 0.5f) / n;        return (rot3f){ .r = c, .x = s*axis.x, .y = s*axis.y, .z = s*axis.z };    } else {        return (rot3f){ .r = 1.0f, .x = 0.0f, .y = 0.0f, .z = 0.0f };    }}and vectors are rotated using a 3-column, 4-vector matrix,
Code: [Select]
typedef struct {    vec3f x;  // Unit x axis vector after rotation    vec3f y;  // Unit y axis vector after rotation    vec3f z;  // Unit z axis vector after rotation    vec3f t;  // Translation after rotation} trans3f;void  trans3f_apply(const trans3f *t, const vec3f *v, size_t n) {    while (n-->0) {        float  x = v->x * t->x.x + v->y * t->y.x + v->z * t->z.x + t->t.x;        float  y = v->x * t->x.y + v->y * t->y.y + v->z * t->z.y + t->t.y;        float  z = v->x * t->x.z + v->y * t->y.z + v->z * t->z.z + t->t.z;        v->x = x;        v->y = y;        v->z = z;        v++;    }}I omitted the function how to rotate an orientation or rotation by another (Hamilton product, orientation right, applied rotation left side), and how to turn an orientation into a matrix (this), because I don't remember them out of hand.
« Last Edit: June 08, 2024, 12:50:14 am by Nominal Animal »

The following users thanked this post: Wilson__

#### Wilson__

• Regular Contributor
• Posts: 131
• Country:
##### Re: Cell phone Accelerometer g force vector representation maths
« Reply #3 on: June 08, 2024, 01:39:04 am »
Many thanks.  Any idea of a visulization software (may be the software platform named processing and associated application code?) that can take x,y,z acceleration values and display an "aeroplane object" on screen showing the roll, pitch and yaw.

If I enter x0, y0 and z0 as base reference.  Then enter x1, y1 and z1 and it will show/say that the new values is xxx degrees changes in roll, pitch and yaw, respectively.

May be able to show animation video based on a time series of x,y,z values.

Many thanks

#### SiliconWizard

• Super Contributor
• Posts: 15168
• Country:
##### Re: Cell phone Accelerometer g force vector representation maths
« Reply #4 on: June 08, 2024, 04:57:56 am »
If you'd like to stream sensor data from a phone to a computer, there is the HyperIMU app that works fine for that, I've used it. Available on Android, maybe also on iOS, not sure.
The app streams data via UDP, it's very easy to handle on the PC side. There is a Python library already written: https://github.com/ianovir/HIMUServer

The following users thanked this post: pardo-bsso, Wilson__

#### Wilson__

• Regular Contributor
• Posts: 131
• Country:
##### Re: Cell phone Accelerometer g force vector representation maths
« Reply #5 on: June 08, 2024, 11:33:08 am »
Many thanks.  My data source is Arduino reading accelerometer and outputing on serial port.

I am searching for a Windows PC side software (may be processing) that can read the x,y,z acceleration data, display an aeroplane showing roll, yaw, pitch.    May be doing animation over a time series of data.  Many thanks

Smf