Math Behind Quaternion to Gravity Conversion

Hi everyone,

I am using the MPU6050 to calculate the y gravity vector from quaternions. The equation used in the I2Cdev library is

gravity.y = 2 * (q.w * q.x + q.y * q.z);

where q.w is the scalar component and rest are the vector quaternions.

I wanted to know how does the math here gives us the gravity vector and if there is any other way to compute the y gravity vector using the least possible number of quaternion components.

Regards.

Sorry, that is meaningless out of context, can you show the entire operation, or point to the source for that code?

Sorry for the confusion. I am using the MPU6050 which is a 6 axis imu. The MPU spits out quaternion readings which can then be further converted to Euler angles or gravity for different computations. Here is the Arduino sketch where quaternions are read from the MPU6050 and conversion to gravity takes place:

This is the library I am using https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050 and this file has the function for gravity calculation from quaternions:

The specific function is:

uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) 

{
    v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);
    v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);
    v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;
    return 0;
}

I am unable to understand the conversion from quaternions to gravity here.

I think that's a hard-wired quaternion multiply with a constant quaternion to re-orient the quarternion? It will take some figuring out from the quat multiply definition to confirm, takes a cool head and read the conventions used by the 6050 for what the local/global frames are and whether the quat is local->global or global->local transform...

how does the math here gives us the gravity vector

It doesn’t. It returns only one scalar.

You’ll need to go through the math yourself in order to understand that equation. It is nonintuitive, but here is a great introduction.

Johnny1010: Sorry for the confusion. I am using the MPU6050 which is a 6 axis imu. The MPU spits out quaternion readings which can then be further converted to Euler angles or gravity for different computations. Here is the Arduino sketch where quaternions are read from the MPU6050 and conversion to gravity takes place:

https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino

This is the library I am using https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050 and this file has the function for gravity calculation from quaternions:

https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h

The specific function is:

uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) 

{    v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);    v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);    v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;    return 0; }




I am unable to understand the conversion from quaternions to gravity here.

I was actually looking into the same problem a couple of weeks ago and after some back-off-the-envelope calculations I was able to derive it for myself. I will share it here just in case someone else is looking into the same problem.

As explained on Wikipedia (https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation) the rotation of a vector v can expressed using the quaternion q as v' = qvp where p is the reciprocal of q. What is done in the calculations is to take the z unit vector in the rotated frame and rotating it back to the initial frame by calculating pzq. If you go through the exercise of the multiplications, you will find the code in the dmpGetGravity function. You will also notice that what is called the gravity vector is actually in the direction of the positive z-axis, which I actually think is a misstake. The sign however cancels out in the other calculations.

If you go through the math in detail you will also find that there is a misstake in the ypr calculations. If anyone is interested in the derivations, I can dig up my notes. The correct equations can however be found on wikipedia.

You will also notice that what is called the gravity vector is actually in the direction of the positive z-axis, which I actually think is a misstake.

Not a mistake.

Accelerometers measure the [u]difference[/u] between the forces acting on the sensing element and the IC framework.

An accelerometer sitting on a table is being pushed up by a force that cancels the downward acceleration due to gravity, so if Z is up, the measured acceleration is positive along the Z axis. In this case, "gravity" appears to be a positive force in the positive Z direction, but the actual force of gravity acts in the downward direction on both the sensing element and the IC framework.

For the same reason, a freely falling accelerometer measures 0 g along all axes, despite being accelerated by gravity.

Hey Sunqn,

I would like to come back on your offer, that you could dig out your notes on the correct mathematics for the calculation of the gravity vector and the ypr-angles. I´am trying to follow the calculations the library does and could need some help on this.

Thanks!