3D maths to sutract gravity from accelerometer data

Hi,

I'm using an IMU9150 which outputs data for acceleration, rotation and magnetometer information in 3 dimensions (so 9 pieces of data)

I am using the RTImuLib (https://github.com/richards-tech/RTIMULib) which works to use the data to determine the orientation of the data in 3 axis of rotation (alpha, beta and theta) and this works fine

But I'd like to take the accelerometer data and work out which way the module is being moved, e.g. upwards (away from the ground), downwards (towards the ground), as well as horizontal direction.

I plan to use the accelerometers, and I know they are not accurate, but I think they are good enough to give a rough idea of which direction the module is being moved (assuming I can average out the noise)

Anyway, the problem is that the accelerometers show 1.0G downwards all the time due to the force of gravity.
I need to deduct the gravity force on the accelerometer data to just leave the motion forces.

But the gravity shown by the accelerometers is relative to the plane of the module in X,Y and Z dimensions

so if the module is laying on a flat surface the values are 0,0,1.0 but if its rotated they will be values like 0.56,0.62,0.57

ie the sum of the values still adds up to 1.0, its just distributed across all 3 axis

Anyway. So what I need to do is take the gravity usual gravity vector (0,0,1.0) and rotate it through the angles in alpha beta and theta that the module is rotated (I get this data from the RTImuLib) then subtract this rotated gravity vector from the accelerometer data

This is where I'm struggling.

I have sound a reference on how to do this here

and so far I've got this far with the code

float accel[3]={0,0,0};// data will come from the accelerometers
float gravity[3]={0,0,1.0};// always vertically downwards at g = 1.0
float rotatedGravity[3];
float motionAcceleration[3];

// Angle of rotation will come from RTImuLib
float alpha= 0.1;// some aribitar values for testing
float beta=  0.2;// some aribitar values for testing
float theta = 0.3;// some aribitar values for testing

float rotationMatrix[3][3] = 
{
  { cos(alpha)*cos(beta) , cos(alpha)*sin(beta)*sin(theta) - sin(alpha)*cos(theta) , cos(alpha)*sin(beta)*cos(theta) + sin(alpha)*sin(theta)},
  { sin(alpha)*cos(beta) , sin(alpha)*sin(beta)*sin(theta) + cos(alpha)*cos(theta) , sin(alpha)*sin(beta)*cos(theta) - cos(alpha)*sin(theta)},
  {     -1* sin(beta)    ,                  cos(beta) * sin(theta)                 ,               cos(beta) * cos(theta)                   }
};

rotatedGravity[0]= gravity[0]*rotationMatrix[0][0] + gravity[1]*rotationMatrix[0][1] + gravity[3]*rotationMatrix[0][2] ;
rotatedGravity[1]= gravity[1]*rotationMatrix[1][0] + gravity[1]*rotationMatrix[1][1] + gravity[3]*rotationMatrix[1][2] ;
rotatedGravity[2]= gravity[2]*rotationMatrix[2][0] + gravity[1]*rotationMatrix[2][1] + gravity[3]*rotationMatrix[2][2] ;

motionAcceleration[0]=accel[0]-rotatedGravity[0];
motionAcceleration[1]=accel[1]-rotatedGravity[1];
motionAcceleration[2]=accel[2]-rotatedGravity[2];
};

However I'm not sure if this is correct or whether the order of rotation makes any difference (I think is does but I'm not sure how)

I'd appreciate any help in letting me know if what I'm doing is correct

Thanks

Roger

You might want to consider this worst-case analysis of the errors involved in doing the subtraction, which is pretty discouraging. http://www.chrobotics.com/library/accel-position-velocity
Beware that there are numerical errors in the table -- column 1 (acceleration) is high by a factor of 100 and column 3 (position) is high by a factor of 2.

I'm certain that you could do quite a better than this pessimistic estimate by averaging the incoming measurements, but at considerable cost to the sampling rate. On the other hand, accelerometers are confused by angular velocity effects (if the craft is rotating) so there is an additional source of error to take into account.

Thanks jremington

I should have said what I'm trying to build it for.

Its not for an aircraft, its for a audience participation device that will be a foam cube a bit like a giant rubic cube.

So I'm not too fussed if it drifts a lot. I just need a general idea of whether its moving up down left right.

I realise it may not work at all, but I won't really know until I try it.

I was going to assume steady state, i.e continuously use the normalised accelerometer output, to get an average, then subtract the change from the long term average.

So that if the device comes to rest, eventually the averaging will remove any continuous offset inputs, that would make the device think its moving

Unfortunately at the moment my code isnt working. I'm still getting over 1.0 for gravity all the time :frowning:

I suspect I'm doing something wrong with the rotation matrix for Gravity

OK.

For the code you posted, acceleration is zero. So no matter what orientation gravity, the vector resulting from the subtraction will still have magnitude 1. Is that all the code?

The only issue with order (and sign) of rotations is that your definition has to agree with the RTImuLib definition. The only way I know to test that is to inspect how the orientation matrix is constructed.

The following isn't much of a test of your posted code, but it works more or less as expected. All it does is define some acceleration in the Earth frame, and rotates both the acceleration and gravity vectors by the assumed body rotation.

Discouragingly, the error in the subtraction is about 3%, regardless of whether the variables are single or double precision (this was done on a PC, with CodeBlocks), and I don't yet know where that is coming from.

I took some liberty with your variable names, for speed of typing.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
double accel[3]={0.1,0,1.0};// data will come from the accelerometers
double gravity[3]={0,0,1.0};// always vertically downwards at g = 1.0
double rG[3],rA[3];
double mA[3];

// Angle of rotation will come from RTImuLib
double alpha= 0.1;// some aribitar values for testing
double beta=  0.2;// some aribitar values for testing
double theta = 0.3;// some aribitar values for testing

double R[3][3] =
{
  { cos(alpha)*cos(beta) , cos(alpha)*sin(beta)*sin(theta) - sin(alpha)*cos(theta) , cos(alpha)*sin(beta)*cos(theta) + sin(alpha)*sin(theta)},
  { sin(alpha)*cos(beta) , sin(alpha)*sin(beta)*sin(theta) + cos(alpha)*cos(theta) , sin(alpha)*sin(beta)*cos(theta) - cos(alpha)*sin(theta)},
  {     -1* sin(beta)    ,                  cos(beta) * sin(theta)                 ,               cos(beta) * cos(theta)                   }
};
double det = +R[0][0]*(R[1][1]*R[2][2]-R[1][2]*R[2][1])\
            -R[0][1]*(R[1][0]*R[2][2]-R[1][2]*R[2][0])\
            +R[0][2]*(R[1][0]*R[2][1]-R[1][1]*R[2][0]);

printf(" det= %f\r\n",det);  //for check, should be +1 exactly

rG[0]= gravity[0]*R[0][0] + gravity[1]*R[0][1] + gravity[3]*R[0][2] ;
rG[1]= gravity[1]*R[1][0] + gravity[1]*R[1][1] + gravity[3]*R[1][2] ;
rG[2]= gravity[2]*R[2][0] + gravity[1]*R[2][1] + gravity[3]*R[2][2] ;

rA[0]= accel[0]*R[0][0] + accel[1]*R[0][1] + accel[3]*R[0][2] ;
rA[1]= accel[1]*R[1][0] + accel[1]*R[1][1] + accel[3]*R[1][2] ;
rA[2]= accel[2]*R[2][0] + accel[1]*R[2][1] + accel[3]*R[2][2] ;

mA[0]=rA[0]-rG[0];
mA[1]=rA[1]-rG[1];
mA[2]=rA[2]-rG[2];

printf("A-G %8.5f %8.5f %8.5f\r\n",mA[0],mA[1],mA[2]);
    return 0;
}

}

Output:

det= 1.000000
A-G 0.09752 0.00000 0.00000

Process returned 0 (0x0) execution time : 0.000 s

rogerClark:
Anyway, the problem is that the accelerometers show 1.0G downwards all the time due to the force of gravity.

A common mistake. An object sat on the surface of the earth experiences a 9.8m/s^2
upwards acceleration. After all its being pushed from the underside by the earth's
surface. Remember the accelerometer is measuring the locally felt acceleration, not
our outsiders' view.

The fact it doesn't appear to move due to this acceleration is because we are accelerating
with it. The fact that we stay the same distance from the centre of the earth is because
space is curved.

An object in free-fall has zero acceleration and is an inertial frame (ignoring tidal
forces).

Hi @MarkT

No worries.

I know why the accelerometers are reading 1.0g when its in steady state, i.e if they were in free fall they would indicate 0,0,0

Never the less, I need to remove the gravity component of the acceleration to get the acceleration imparted by other external forces e.g people moving the sensor :wink:

@jremington

I took some liberty with your variable names, for speed of typing.

No worries. I'd normally use short names, but its harder for other people to understand if I post cryptic code :wink:

Discouragingly, the error in the subtraction is about 3%

I'm not quite sure what your code does (the maths is beyond me.
I think you are saying, that if you take the output of the rotation matrix and then work out the magnitude that there is a 3% error due to the precision of the maths i.e for sin and cos ?

As the gravity vector is actually only in one dimension, a lot of the calculations in the rotation matrix are zero

Does this improve the accuracy?

Surely rotation of a 3D point is performed by all sorts of programs, there must be a way to do it without getting an error as large as 3% ?

Thanks

Roger

BTW. I forgot to say..

I think one issue is definately the matrix order, or basically which values from RTImuLib are alpha beta and theta

The way I've currently got it coded is obviously not correct the rotated gravity vector is not 0,0,-1 but the accelerometers are reading 0,0,1

Edit

Notice a bug / typo's in my code

I think this is correct now.

rotatedGravity[0]= gravity[0]*rotationMatrix[0][0] + gravity[1]*rotationMatrix[0][1] + gravity[2]*rotationMatrix[0][2] ;
rotatedGravity[1]= gravity[0]*rotationMatrix[1][0] + gravity[1]*rotationMatrix[1][1] + gravity[2]*rotationMatrix[1][2] ;
rotatedGravity[2]= gravity[0]*rotationMatrix[2][0] + gravity[1]*rotationMatrix[2][1] + gravity[2]*rotationMatrix[2][2] ;

I still have an axis version, but at least the magniture of the gravity vector seems to be coming out at 1.00

e.g.
rotated gravity

-0.02 0.56 0.83

=1.0029

The error in this case is that I'm only seeing the vectors to 2 DP when I use Serial.Print Shame there isnt a way to set the DP display on floats

You are certainly on the right track! Edit: our posts crossed.

I found the mistake. You had some array indexing errors in the original rotation matrix multiplication, which I overlooked at first. Here is the original snippet:

rotatedGravity[0]= gravity[0]*rotationMatrix[0][0] + gravity[1]*rotationMatrix[0][1] + gravity[3]*rotationMatrix[0][2] ;
rotatedGravity[1]= gravity[1]*rotationMatrix[1][0] + gravity[1]*rotationMatrix[1][1] + gravity[3]*rotationMatrix[1][2] ;
rotatedGravity[2]= gravity[2]*rotationMatrix[2][0] + gravity[1]*rotationMatrix[2][1] + gravity[3]*rotationMatrix[2][2] ;

which should be:

rotatedGravity[0]= gravity[0]*rotationMatrix[0][0] + gravity[1]*rotationMatrix[0][1] + gravity[2]*rotationMatrix[0][2] ;
rotatedGravity[1]= gravity[0]*rotationMatrix[1][0] + gravity[1]*rotationMatrix[1][1] + gravity[2]*rotationMatrix[1][2] ;
rotatedGravity[2]= gravity[0]*rotationMatrix[2][0] + gravity[1]*rotationMatrix[2][1] + gravity[2]*rotationMatrix[2][2] ;

My corrected program now assumes some acceleration (and the gravity vector) defined in the Earth frame, rotates both into the body frame of the object, does the subtraction and rotates the result back into the Earth frame. It gets the correct result even in single precision. Additionally, I calculate the determinant of the rotation matrix, which should be 1.0 if it is correctly defined (always useful as a check).

All this does is just verify that matrix math works (as it certainly should), but perhaps that can be helpful in thinking about the problem.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
float accel[3]={0.1,0,1.0};// data will come from the accelerometers
float gravity[3]={0,0,1.0};// always vertically downwards at g = 1.0
float rG[3],rA[3];
float mA[3];

// Angle of rotation will come from RTImuLib
float alpha= 0.1;// some aribitar values for testing
float beta=  0.2;// some aribitar values for testing
float theta = 0.3;// some aribitar values for testing

float R[3][3] =
{
  { cos(alpha)*cos(beta) , cos(alpha)*sin(beta)*sin(theta) - sin(alpha)*cos(theta) , cos(alpha)*sin(beta)*cos(theta) + sin(alpha)*sin(theta)},
  { sin(alpha)*cos(beta) , sin(alpha)*sin(beta)*sin(theta) + cos(alpha)*cos(theta) , sin(alpha)*sin(beta)*cos(theta) - cos(alpha)*sin(theta)},
  {     -1* sin(beta)    ,                  cos(beta) * sin(theta)                 ,               cos(beta) * cos(theta)                   }
};
float det =  R[0][0]*(R[1][1]*R[2][2]-R[1][2]*R[2][1])\
             -R[0][1]*(R[1][0]*R[2][2]-R[1][2]*R[2][0])\
             +R[0][2]*(R[1][0]*R[2][1]-R[1][1]*R[2][0]);

printf(" det= %f\r\n",det);  //for check, should be +1 exactly

rG[0]= gravity[0]*R[0][0] + gravity[1]*R[0][1] + gravity[2]*R[0][2] ;
rG[1]= gravity[0]*R[1][0] + gravity[1]*R[1][1] + gravity[2]*R[1][2] ;
rG[2]= gravity[0]*R[2][0] + gravity[1]*R[2][1] + gravity[2]*R[2][2] ;

rA[0]= accel[0]*R[0][0] + accel[1]*R[0][1] + accel[2]*R[0][2] ;
rA[1]= accel[0]*R[1][0] + accel[1]*R[1][1] + accel[2]*R[1][2] ;
rA[2]= accel[0]*R[2][0] + accel[1]*R[2][1] + accel[2]*R[2][2] ;

mA[0]=rA[0]-rG[0];
mA[1]=rA[1]-rG[1];
mA[2]=rA[2]-rG[2];

printf("A %8.5f %8.5f %8.5f\r\n",accel[0],accel[1],accel[2]);
printf("G %8.5f %8.5f %8.5f\r\n",gravity[0],gravity[1],gravity[2]);
printf("rA %8.5f %8.5f %8.5f\r\n",rA[0],rA[1],rA[2]);
printf("rG %8.5f %8.5f %8.5f\r\n",rG[0],rG[1],rG[2]);
printf("A-G %8.5f %8.5f %8.5f\r\n",mA[0],mA[1],mA[2]);

//rotate modified acceleration back into the Earth frame (use transpose of R)

rA[0]= mA[0]*R[0][0] + mA[1]*R[1][0] + mA[2]*R[2][0] ;
rA[1]= mA[0]*R[0][1] + mA[1]*R[1][1] + mA[2]*R[2][1] ;
rA[2]= mA[0]*R[0][2] + mA[1]*R[1][2] + mA[2]*R[2][2] ;

printf("A-G in Earth frame %8.5f %8.5f %8.5f\r\n",rA[0],rA[1],rA[2]);

    return 0;
}

Program output:

det= 1.000000
A 0.10000 0.00000 1.00000
G 0.00000 0.00000 1.00000
rA 0.31587 -0.26531 0.91643
rG 0.21835 -0.27510 0.93629
A-G 0.09752 0.00978 -0.01987
A-G in Earth frame 0.10000 -0.00000 -0.00000

Process returned 0 (0x0) execution time : 0.016 s

You shouldn't need to use Euler angles at all in simple coordinate transforms - these
are performed on the DCM with matrix multiplication. Remember matrix multiplication
is not commutative (neither are rotations in 3D) so you have to use the right matrix
in the right position to effect the wanted transformation. Due to rotations being nice
and well behaved mathematically the inverse matrix is simply the transpose so its
trivial to calculate.

Pass some simple test vectors into the code to confirm its rotating the right
way?

@MarkT:

An object sat on the surface of the earth experiences a 9.8m/s^2
upwards acceleration.

True, but it also experiences a 9.8m/s^2 acceleration downwards due to gravity. The two balance out and so the object doesn't move.

The fact it doesn't appear to move due to this acceleration is because we are accelerating
with it.

No. We aren't accelerating and neither is the object. If we were accelerating we'd be moving.

There are two opposing forces on the object. The earth's gravity trying to pull it towards the centre of the earth and the force of the ground pushing it up by exactly the opposite amount. If the two forces aren't balanced, the object will be moving.

The fact that we stay the same distance from the centre of the earth is because
space is curved.

No. The curvature of space around earth is caused by the earth's mass and the result of the curvature is what we perceive as gravity.

An object in free-fall has zero acceleration

That is a contradiction. An object in free fall is, by definition, accelerating.

Pete

An object in free-fall has zero acceleration

That is a contradiction. An object in free fall is, by definition, accelerating.

This confused me at first, too. An accelerometer actually measures the difference in forces applied to the accelerometer housing to those applied to the sensing element, which can be thought of in 1D as a mass suspended by a spring.

In free fall the difference is zero. When the accelerometer is sitting still on a table, the table is pressing up on the package with 1 g, while gravity is pulling down on both the element and the package with 1 g. The difference is +1 g, which is reported.

@jremington

Thanks for your code.

I'll need to download and install codeblocks and give it a whirl.

Actually I have MS Visual Studio installed (for work purposes) so I guess I could use that, but I'm not sure if its got c++ installed or whether its just c#

I may as well install codeblocks and keep my work an hobby stuff separate :wink:

Now that I fixed the error in the code the vector is being rotated OK, but there is a still a problem with the axis i.e which one is which

So I'm swapping them around (trial and error) However I'm not sure this will ultimately work, and it could be the order of multiplication of the 3 rotation matrixes thats the issue :frowning:

I'll keep the forum posted in case I make any progress, as I think I"m not the only one interested in this

@Roger:

There is no doubt that this topic is of great interest!

I glanced through the RTIMULib code, and it appears that the author has abandoned rotation matrices defined by Euler angles completely, in favor of quaternions. There are good arguments for doing this (avoidance of the "gimbal lock" problem, ease of normalization of the rotation operator, etc.) but it makes it rather difficult to figure out which rotation matrix would agree with the internal definitions of the order and signs of applied rotations.

One way out of this is to generate quaternions from the Euler angles rather than rotation matrices, and use those to perform coordinate system rotations, but fewer people are familiar with those operations.

If you wish to stick with rotation matrices, a starting point would be the following two routines found In RTMath.cpp, which convert a set of Euler angles to a quaternion and vice versa. It appears that m_data[] is the quaternion that defines the current body orientation with respect to the Earth frame of reference.

void RTQuaternion::toEuler(RTVector3& vec)
{
    vec.setX(atan2(2.0 * (m_data[2] * m_data[3] + m_data[0] * m_data[1]),
            1 - 2.0 * (m_data[1] * m_data[1] + m_data[2] * m_data[2])));

    vec.setY(asin(2.0 * (m_data[0] * m_data[2] - m_data[1] * m_data[3])));

    vec.setZ(atan2(2.0 * (m_data[1] * m_data[2] + m_data[0] * m_data[3]),
            1 - 2.0 * (m_data[2] * m_data[2] + m_data[3] * m_data[3])));
}

void RTQuaternion::fromEuler(RTVector3& vec)
{
    RTFLOAT cosX2 = cos(vec.x() / 2.0f);
    RTFLOAT sinX2 = sin(vec.x() / 2.0f);
    RTFLOAT cosY2 = cos(vec.y() / 2.0f);
    RTFLOAT sinY2 = sin(vec.y() / 2.0f);
    RTFLOAT cosZ2 = cos(vec.z() / 2.0f);
    RTFLOAT sinZ2 = sin(vec.z() / 2.0f);

    m_data[0] = cosX2 * cosY2 * cosZ2 + sinX2 * sinY2 * sinZ2;
    m_data[1] = sinX2 * cosY2 * cosZ2 - cosX2 * sinY2 * sinZ2;
    m_data[2] = cosX2 * sinY2 * cosZ2 + sinX2 * cosY2 * sinZ2;
    m_data[3] = cosX2 * cosY2 * sinZ2 - sinX2 * sinY2 * cosZ2;
    normalize();
}

Hi jremington

I've actually already posted my code to Richard, but he's not mentioned quaternions

I did notice that the RTMath does stuff by quaternions, but it a branch of maths that I have no idea about, and was hoping to achieve it using stuff I already vaguely understood

But I'm happy to learn !

Just trying to change the X Y and Z axis data into alpha beta and theta in my code isn't working. i.e I can get it to nullify gravity for two planes but if I rotate it in the 3rd plane the gravity doesnt end up getting removed

So I presume that perhaps its a the order in which the rotation matrix's have has originally been compiled, e.g. from

where they state that the order does matter (which I expected to be the case)

Looking at the code in RTMath, he uses m_data for both quarternions and vectors (its just an array)

I could call the RTImuLib function to convert the Euler angle to quarternion for both the rotation of the module and gravity, but I'm not sure what to do after that, I presume somehow multiply the two together and then convert back to euler ?

Sorry, I didnt do this sort of maths (even at Uni). :frowning:

I've have another look at this , but not got a solution yet

However, I case anyone else wants to mess around with some real data here is some :wink:
See attached file (as it was too big to post in the message)

Its generated by this code

     RTVector3 pose =fusion.getFusionPose();
     dtostrf(pose.x(),12, 7, printBuf); Serial.print(printBuf);    Serial.print(","); 
     dtostrf(pose.y(),12, 7, printBuf); Serial.print(printBuf);    Serial.print(","); 
     dtostrf(pose.z(),12, 7, printBuf); Serial.print(printBuf);    Serial.print(","); 
     
     pose = imu->getAccel();
     dtostrf(pose.x(),12, 7, printBuf); Serial.print(printBuf);    Serial.print(","); 
     dtostrf(pose.y(),12, 7, printBuf); Serial.print(printBuf);    Serial.print(","); 
     dtostrf(pose.z(),12, 7, printBuf); Serial.println(printBuf);

So the columns are

First 3 are X Y and Z rotation returned by the getFusionPose (angles in radians)
The last 3 X Y Z acceleration (in G's)

It wasn't worth printing out more than 7 decimal places as it didnt give any more precision, I have a feeling the RTImuLib may be defaulting to using float, but I've not double checked

The data is with me trying to slowly rotate the module though various orientations.
It will be a bit shakey as its on a breadboard attached to a uni by short wires and its hard to work

Looking at the data graphed in excel, I dont think I rotated it completely around in all 3 dimensions

I'll carry on tomorrow if I get chance, probably processing the data on the PC, as its quicker to compile and test in CodeBlocks than to keep compiling and uploading to the Arduino

data2.csv (20.8 KB)

It wasn't worth printing out more than 7 decimal places as it didnt give any more precision, I have a feeling the RTImuLib may be defaulting to using float, but I've not double checked

On the Arduino? Of course it is. A double is just another name for float.

el_supremo:
@MarkT:

An object sat on the surface of the earth experiences a 9.8m/s^2
upwards acceleration.

True, but it also experiences a 9.8m/s^2 acceleration downwards due to gravity. The two balance out and so the object doesn't move.

Lets be clear here, the accelerometer, in its own frame of reference, experiences
an acceleration upwards - that's all it knows (apart from the tidal forces, but they
are much much smaller).

In our frame of reference we also experience an acceleration upwards - we are in
the same frame, to a first approximation, so see the accelerometer as stationary.

Nothing is or appears to be accelerating downwards from this frame. The force from
the floor is not cancelled out by anything, its a true upwards acceleration we feel
from our feet.

This is the key insight behind general relativity, that inertial and gravitational mass
are identical and apparent forces due to gravity are inertial forces.

The fact it doesn't appear to move due to this acceleration is because we are accelerating
with it.

No. We aren't accelerating and neither is the object. If we were accelerating we'd be moving.

see answer above.

There are two opposing forces on the object. The earth's gravity trying to pull it towards the centre of the earth and the force of the ground pushing it up by exactly the opposite amount. If the two forces aren't balanced, the object will be moving.

There is no force due to gravity, there is only curved space, described by the
gravitational tensor.

The fact that we stay the same distance from the centre of the earth is because
space is curved.

No. The curvature of space around earth is caused by the earth's mass and the result of the curvature is what we perceive as gravity.

Yes the curvature is caused by the mass, and YES that's why we don't appear to move
relative to the earth's centre. We perceive the force from the floor, which is due to
the earth being an elastic body, resisting the deformation that the curvature gives it.

An object in free-fall has zero acceleration

That is a contradiction. An object in free fall is, by definition, accelerating.

An object in free fall is free of all forces, and therefore subject to zero acceleration
in its own frame - this makes it an inertial frame (apart from those pesky tidal forces,
themselves the signature that space is curved).

Pete
[/quote]
I recommend a course on general relativity. Its been validated by several elegant
experiments since Einstein proposed it. Without it you cannot explain why atomic clocks run
apparently faster at altitude - with it you realise you have clocks in different accelerating
frames hence the difference

Hi, Roger:

I was going to suggest just the following:

I could call the RTImuLib function to convert the Euler angle to quarternion for both the rotation of the module and gravity, but I'm not sure what to do after that, I presume somehow multiply the two together and then convert back to euler ?

All the functions you need are already in RTMath.cpp, including definitions for some useful quaternion operators.

For a clear introduction to use of quaternions in IMU maths, I suggest starting with this summary https://www.chrobotics.com/docs/AN-1006-UnderstandingQuaternions.pdf I find the maths quite a bit more unwieldy than rotation matrices.

To do the operation you've already started (with rotation matrices), you need to rotate the gravity vector into the "cube" frame using the appropriate quaternion operation, subtract it from the measured acceleration vector and rotate the result back to the Earth frame. All this can be done in a dozen or so lines of code, provided you get the quaternion from RTIMUlib. Obviously, the accelerometer must be properly calibrated.

I'll take a look at the data you posted and see if I can make sense out of them.

Could you briefly elaborate on what sort of motions you expect from the foam cube? Will the audience toss it around?