Acceleration vector based on accelerometer, gyro and magnetometer?

Asked by alan rorie on 2011-11-16


In some of your older code (the 6DOF project you have a function getInclination that incorporated the gyro data into the accelerometer to get a beter estimate of the real world acceleration vector. (I think this is a Kalman filter?).

I'm wondering if there are any functions in the FreeIMU lib that does the same and incorporates the magnetometer?

I need the best estimate of acceleration possible using these three sensors.


Question information

English Edit question
FreeIMU Edit question
No assignee Edit question
Last query:
Last reply:

This question was reopened

The getQ() function will return a quaternion which represents the orientation of the FreeIMU board with respect to the World computed using the fusion between accelerometer, gyroscope and magnetometer.

If you are not experienced with quaternions you can just use the getYawPitchRoll() function which will returns the Yaw, pitch and roll angles as computed from the sensor fusion.

alan rorie (alan-kec) said : #2

Thanks so much.

Excuse my potential misunderstanding here but those are returning the orientation not the acceleration, right?

If the board is rotated onto its side but not moving I'll still have a reading from either of those functions.

I need to extract velocity and position information, I know the that the double integration causes errors, but I only need position for a short period and distance. I'm hopping it will work.

Ah.. ok. I misunderstand your question. So, you wanna know the dynamic acceleration. I explained this in a blog post, see Once you have the dynamic acceleration, by numerically integrating that with time once you'll get speed and displacement when integrating another time.

alan rorie (alan-kec) said : #4

Thanks, I'll try implementing that in processing, looks like it should be easy to do.

Will this dynamic acceleration be effected by rotation?

Or will I still need to subtract out the acceleration component related to rotation?

The output of the function I linked above will return the dynamic acceleration relative to the sensor frame, so if you integrate that it will be speed or displacement relative to the sensor frame. In order to compute them in the world frame you'll have to rotate that vector using the sensor fusion orientation. You can read about quaternion multiplications with vectors with this document

alan rorie (alan-kec) said : #6

Hello Fabio --

I implements your code above in porcessing:

void getDynamicAcc() {

 float[] g= {
  0.0, 0.0, 0.0

  g[0] = 2 * (q[1] * q[3] - q[0] * q[2]);
  g[1] = 2 * (q[0] * q[1] + q[2] * q[3]);
  g[2] = q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3];

  float[] dynAcc= {
    rawAcc[0] - g[0], rawAcc[1] - g[1], rawAcc[2] - g[2]


 and I'm wondering if you would be kind enough to verify my calculations:

[0] 0.045540933
[1] 0.58828443
[2] 0.80633926
[3] -0.040799923

[0] -244.0
[1] 0.0
[2] 0.0

dynamic acceleration=
[0] -243.87856
[1] 0.012215115
[2] 0.99252295

Also, while I understand, in theory, the matrix calculations in the paper you refereed to me are, the implementation is honestly, beyond my ability.

I'm wondering if you might have a code snippet that can preform this calculation?

I've learned so much working with your code.

Thanks so much for all you awesome help.

The code I linked says: "@param acc the readings coming from an accelerometer expressed in g" .. you are not passing raw accelerometer data in g. Check the datasheet of your accelerometer to understand how to convert raw readings to g. Look for "LSB/g". (LSB = Least significant bits).

alan rorie (alan-kec) said : #8

Hello Fabio -

Thanks for your continued guidance.

The accelerometer I'm using is the ADXL345. I read up on the specs as you recommended and discovered that the scale factor I needed to use to convert the raw acc data in g depended on the sensitivity.

So I went poking through FreeIMU.h and FreeIMU.cpp and implemented the setRangeSetting function. Using that I sent the sensitivity to +-4g at 10bits of resolution. So based on some further reading I determined that the scale is found by dividing the total range (8g) by the max number represented in 10bits, that is 8/1024=0.0078.

So I updated getDynamicAcc to scale the incoming acc data:

void getDynamicAcc() {
  float S=0.0078;//scale factor to convert from raw acc data to g

  float[] g= {
    0.0, 0.0, 0.0

  g[0] = 2 * (q[1] * q[3] - q[0] * q[2]);
  g[1] = 2 * (q[0] * q[1] + q[2] * q[3]);
  g[2] = q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3];

  float[] dynAcc= {
    rawAcc[0] - g[0], rawAcc[1] - g[1], rawAcc[2] - g[2]

Now that values I'm getting are:

[0] 0.048809517
[1] -0.4581384
[2] 0.8866772
[3] 0.03911991

rawAccleration (now in g I hope);
[0] -0.1248
[1] 0.038999997
[2] -0.9906

dynamic acceleration=
[0] -0.0023987591
[1] 0.014349561
[2] 0.0015745759

These values were taken while the IMU was stationary, and seem to make more sense to me.
The rawAcc for X slight (the chip is on a slight tilt), negligible for Y and close to -1 for Z, while the dynamic acc is close to 0 for all three axis.

Do these numbers look more reasonable for you as well?

Again, thank you so very much for your continued support, I'm learning so much with your help and slowly moving this project along.

> Do these numbers look more reasonable for you as well?

Yes, much better. ;-)

Calibrating your accelerometer will give you even better results.

Google for the following documentations:
AN3182: Tilt measuring using a low-g 3-axis accelerometer.
AN3192: Using LSM303DLH for a tilt compensated electronic compass.
both by ST.

Good luck,


tusshar saigal (tusshar-s) said : #11

Fabio in your Free IMU library u have set the range to ? ie +-2g/+-4g/etc..

Can you help with this problem?

Provide an answer of your own, or ask alan rorie for more information if necessary.

To post a message you must log in.