How to compensate for gravity using 9DOF


I intend to purchase the MinIMU-9 v3 Gyro, Accelerometer, and Compass (L3GD20H and LSM303D Carrier) board. But first i need to know how i can compensate for gravity in my accelerometer readings using the other 6 degrees of freedom (3D magnetometer and 3D gyro). Can anyone help me with the algorithm and the math involved in this?

Thanks a lot

In subtracting acceleration due to gravity, is it your intention to integrate the remaining acceleration to derive velocity and position? If so, it is unlikely to work, because the orientation is usually too poorly known.

Here is the clearest explanation of the problem I’ve yet to find, along with some practical estimates for the conditions under which this approach can work: … n-velocity

For an excellent overview of inertial sensors, coordinate systems and orientation estimation, see the other entries on this page:

Jim is right, it doesn’t work. However for the sake of learning, this is how it can be done

I’ll assume you know your orientation and it’s represented by a quaternion. First you must measure specific force (from accelerometers) with reference to your IMU. You must then change the frame of reference to the real world frame. This can be done by rotating the acceleration vector by the conjugate of the orientation quaternion.

So now that your measured acceleration vector is referenced to the real world, you may simply subtract 1g from the vertical axis and voilà, you have proper acceleration.
If you go ahead and integrate that acceleration to find velocity, and then integrate that speed to find position, you will find that you end up with inaccuracies of hundreds of meters within seconds.

Here are some good links … plication/


Thanks for the replies. Actually I want to know how i can represent the orientation by a quaternion. I read up about it a little and I don’t see how I can use the readings from acc, gyro and mag to get that. I will get to reading finish all the links u sent after this reply.

Anyway my intention is actually to measure hand tremor using accelerometer readings. I have already implemented a FFT algorithm that is able to plot me a bar graph from 0-32 Hz, so from this i can see which frequency has the highest magnitude, just like a FFT plot. The problem is that it only works for one axis, and I do not want to plot three graphs for each axis because it is not presentable.

It only works for one axis because if i were to use the pythagorean theorem for all three axis like value = sqrt(x^2 + y^2 + z^2), there will always be 1g reading pointing to the ground because of gravity. The real problem however is this. Imagine if the acc is lying flat on the ground, and z = -1g. If the hand’s tremor is shaking along the x axis, the difference in the pythagorean value will be too small overall to detect any difference since nobody’s hand will be shaking with 1g acc. Even if the hand tremor is exactly along the z axis, the difference is not substantial in the FFT plot.

Is there a better way i can go about achieving this instead of having to compensate for gravity?

Forgive me for my “noobness” I’m really still pretty new to all this!

Try this . . .

Thanks for the information from your link, that was v helpful.

However, I’m still not very sure how to find the axis angle theta using gyroscope readings. Also, what is the math involved to rotate the acceleration vector by the conjugate of the orientation quaternion? Is it A = qAq^-1 where A is the matrix of the 3 axis accelerometer readings?

Ok, angular velocity is a vector. It has direction (the axis about which the rotation is occuring) and magnitude (the velocity component).

An axis angle has a vector (the axis) which represents direction and a scalar (the angle) that represents the amount of rotation around that vector.

To turn angular velocity into an axis angle, we already know the axis component because it’s the same as the angular velocity axis. The angle must be found by integrating the magnitude of the angular velocity - multiplying by the difference in time between gyroscope readings.

You’ve got the correct rule for multiplying a vector by a quaternion. The IMU maths library has a quaternion function called rotateVector(). It uses the faster quaternion-vector multiplication method.

Ok i got it, thanks!

Sorry i want to ask, that i have three angular velocity readings for each axis from the gyroscope, so how should i “combine” them before i can integrate (multiply) it with time to obtain the axis angle?

The answer to that question is in the IMU maths link that I posted earlier.

Here is some sample code. w is a vector that represents angular velocity. The components of w represent the readings from the relevant gyroscopes in radians per second.

double theta = w.magnitude() * dt; //integrate angular velocity to find the angle
w.normalize(); //the axis is w, normalized

Quaternion q;
q.fromAxisAngle(w, theta); //create a quaternion from the axis angle
rotation_buf = rotation_buf * q; //apply the rotation

Ok thanks!