Cell phone Accelerometer g force vector representation maths - Page 1
Forum section: electronics / projects

author: Wilson__
author_rank: Frequent Contributor
timestamp: June 07, 2024, 11:23:26 pm
content: 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

author: jpanhalt
author_rank: Super Contributor
timestamp: June 07, 2024, 11:53:03 pm
content: Does this help:https://www.analog.com/media/en/technical-documentation/application-notes/AN-1057.pdfI am sure there are later explanations.

author: Nominal Animal
author_rank: Super Contributor
timestamp: June 08, 2024, 12:48:17 am
content: Quote from: Wilson__ on June 07, 2024, 11:23:26 pmThat 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 tonormalizethe 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.Quote from: Wilson__ on June 07, 2024, 11:23:26 pmYou 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.Quote from: Wilson__ on June 07, 2024, 11:23:26 pmDon't need one, really.Code:#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 viaCode:vec3f v0, v1;float n0 = vec3f_length(v0);float n1 = vec3f_length(v1);if (n0 <= EPS) {// 0 was in free fall, abort} elseif (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.} elseif (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 givesaas the rotation axis vector, andvarphias the rotation angle around that vector in radians. Multiplyvarphiby 360/(2π) ≃ 57.29578f to get the result in degrees.If you need rotations, then orientation and rotation are best described using versor/bivectorCode: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 };elsereturn (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:typedef struct {vec3f x; // Unit x axis vector after rotationvec3f y; // Unit y axis vector after rotationvec3f z; // Unit z axis vector after rotationvec3f 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.

author: Wilson__
author_rank: Frequent Contributor
timestamp: June 08, 2024, 01:39:04 am
content: 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

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 08, 2024, 04:57:56 am
content: 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

author: Wilson__
author_rank: Frequent Contributor
timestamp: June 08, 2024, 11:33:08 am
content: 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