Go Down

Topic: Math Behind Quaternion to Gravity Conversion (Read 1 time) previous topic - next topic

Johnny1010

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.

MarkT

Sorry, that is meaningless out of context, can you show the entire operation, or point to the source for that code?
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

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:

Code: [Select]



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.

MarkT

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...
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

jremington

#4
Jan 11, 2017, 05:01 pm Last Edit: Jan 11, 2017, 05:03 pm by jremington
Quote
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.

Sunqn

#5
Jan 25, 2018, 09:28 pm Last Edit: Jan 25, 2018, 09:44 pm by Sunqn
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:

Code: [Select]



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.

jremington

#6
Jan 25, 2018, 10:09 pm Last Edit: Jan 25, 2018, 10:12 pm by jremington
Quote
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 difference 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.

Go Up