Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compass Alignment with Roll and Pitch Axes (DMP) #145

Closed
Gord1 opened this issue Aug 10, 2024 · 8 comments
Closed

Compass Alignment with Roll and Pitch Axes (DMP) #145

Gord1 opened this issue Aug 10, 2024 · 8 comments

Comments

@Gord1
Copy link

Gord1 commented Aug 10, 2024

Subject of the issue

I'm finding that the Compass (yaw) is 90 deg off from what I'm expecting with respect to the roll and pitch directions.

I'm using SparkFun Example11_DMP_Bias_Save_Restore_ESP32 that I have modified slightly for the ESP8266. This example takes the quaternion data and calculates roll, pitch and yaw. The angles are all good, except for the zero reference for the yaw angle. That seems to be rotated 90 deg.

If I set the board flat with 0 yaw, the "nose" of the board will point north. If I lift the nose up I would expect the pitch angle to change, but the roll changes.

issue #114 @texasfunambule may have made a comment about this > The quat9 example seems to work fine (except maybe for compass alignement)

Could the quaternion components be mixed in the roll, pitch, yaw equations?? That is beyond my pay grade.

@PaulZC
Copy link
Contributor

PaulZC commented Aug 12, 2024

Hi @Gord1 ,

Welcome to the weird and wonderful world of the ICM20948 DMP!

Agreed. I'm seeing the same thing. Looks like I've got a rotation in there.

My setup: SparkFun ESP32 Thing Plus C, connected to a SparkFun ICM-20948 breakout via I2C; Arduino IDE 1.8.19; Espressif ESP32 boards 3.0.1.

If I let Example11 run for a while, do the three rotations and six holds, the Yaw reports 0 degrees when the Accel/Gyro Y axis is pointing towards magnetic North. But, yes, roll and pitch are reversed. Also, Yaw goes negative when I rotate clockwise from North.

IIRC, I used the conversion code from here (or a very similar source):

https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Source_code_2

In the example code, I assumed Q0/1/2/3 mapped onto Qw/x/y/z. That appears to be untrue...

I don't have time to dig into this right now. I will try and get to it ~soon. If you have time and can correct the sequence, please do and send us a Pull Request.

Best wishes,
Paul

@PaulZC PaulZC changed the title Compass Alignment with Roll and Pitch Axes Compass Alignment with Roll and Pitch Axes (DMP) Aug 12, 2024
@Gord1
Copy link
Author

Gord1 commented Aug 12, 2024

Agreed. I'm seeing the same thing. Looks like I've got a rotation in there.

Hi @PaulZC

Many thanks for looking into this and confirming the issue.

In the example code, I assumed Q0/1/2/3 mapped onto Qw/x/y/z. That appears to be untrue...

The coordinate frame for the accelerometer and gyro are different than the magnetometer on the ICM20948. Do you have any information on the coordinate frame for the DMP and how it relates to the physical chip?

There are a lot of combinations to start trying them randomly shooting in the dark.

Thanks,
Gord

@PaulZC
Copy link
Contributor

PaulZC commented Aug 12, 2024

Hi Gord,

There are no clues about coordinate frames in the DMP application note...

But this may help:

https://github.com/ZaneL/quaternion_sensor_3d_nodejs/blob/34a289a251b9a593fd4d522e68a702f64de324d8/public/index.html#L56-L57

Best,
Paul

@Gord1
Copy link
Author

Gord1 commented Aug 13, 2024

Hi @PaulZC,

In the example 11 code the 4th quaternion is calculated by
double q0 = sqrt(1.0 - ((q1 * q1) + (q2 * q2) + (q3 * q3)));

This is always taken as positive while it could be +/- as it is the square root. Depending on whether you take the positive q0 or negative, don't you get a different rotation?

Regards,
Gord

@Gord1
Copy link
Author

Gord1 commented Aug 13, 2024

Screenshot 2024-08-13 at 17-10-45 DS-000189-ICM-20948-v1 6 pdf

This seems to be the directions for both the Gyro and the Quaternion.

If I tilt the board around the x-axis both the gx and q1 increase for +ve rotation. The same for the y and z axis.

For the roll, pitch, yaw calculation equations in example 11, I'm guessing that the x-axis is defined as forward and not the y-axis as shown above.

I'm not familiar with quats. I guess we should we switching q1,q2 and q3 around.

Gord

@Gord1
Copy link
Author

Gord1 commented Aug 14, 2024

Hi @PaulZC,

Here is the bit of code to swap the axis around so they work with the equations that are in standard aircraft dynamics form:

		// Scale to +/- 1
		//  -GW note The ICM 20948 chip has axes y-forward, x-right and Z-up
		//  -see Figure 12. Orientation of Axes of Sensitivity and Polarity of Rotation
		//	DS-000189-ICM-20948-v1.6.pdf  These are the axes for gyro and accel and quat
		//
		//  For conversion to roll, pitch and yaw for the equations below, the coordinate frame
		//  must be in aircraft reference frame.
		//  
		// we use the Tait Bryan angles (in terms of flight dynamics):
		// ref: https://en.wikipedia.org/w/index.php?title=Conversion_between_quaternions_and_Euler_angles
		//
		// Heading – ψ : rotation about the Z-axis (+/- 180 deg.)
		// Pitch – θ : rotation about the new Y-axis (+/- 90 deg.)
		// Bank – ϕ : rotation about the new X-axis  (+/- 180 deg.)
		//
		// where the X-axis points forward (pin 1 on chip), Y-axis to the right and Z-axis downward.
		// In the conversion example above the rotation occurs in the order heading, pitch, bank. 
		// To get the roll, pitch and yaw equations to work properly we need to exchange the axes
		
		// Note when pitch approaches +/- 90 deg. the heading and bank become less meaningfull because the
		// device is pointing up/down.

		double qx, qy;  // some temp vars for switching axis

		qx = q1;
		qy = q2;

		// w no change
		q1= qy;  //x and y exchanged
		q2= qx;
		q3= -q3; //neg z

Now do conversion ...

Regards,
Gord

@PaulZC
Copy link
Contributor

PaulZC commented Aug 15, 2024

Hi Gord (@Gord1 ),

Thank you.

I went with the following, to avoid messing up the QUAT_ANIMATION:

double q0 = sqrt(1.0 - ((q1 * q1) + (q2 * q2) + (q3 * q3)));
double qw = q0; // See issue #145 - thank you @Gord1
double qx = q2;
double qy = q1;
double qz = -q3;
// roll (x-axis rotation)
double t0 = +2.0 * (qw * qx + qy * qz);
double t1 = +1.0 - 2.0 * (qx * qx + qy * qy);
double roll = atan2(t0, t1) * 180.0 / PI;
// pitch (y-axis rotation)
double t2 = +2.0 * (qw * qy - qx * qz);
t2 = t2 > 1.0 ? 1.0 : t2;
t2 = t2 < -1.0 ? -1.0 : t2;
double pitch = asin(t2) * 180.0 / PI;
// yaw (z-axis rotation)
double t3 = +2.0 * (qw * qz + qx * qy);
double t4 = +1.0 - 2.0 * (qy * qy + qz * qz);
double yaw = atan2(t3, t4) * 180.0 / PI;

I'll release these changes in a few minutes.

Thanks again,
Paul

@PaulZC
Copy link
Contributor

PaulZC commented Aug 15, 2024

@PaulZC PaulZC closed this as completed Aug 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants