@@ -222,27 +222,48 @@ void loop()
222222 SERIAL_PORT.println(q3, 3);
223223*/
224224
225- // Convert the quaternions to Euler angles (roll, pitch, yaw)
226- // https://en.wikipedia.org/w/index.php?title=Conversion_between_quaternions_and_Euler_angles§ion=8#Source_code_2
225+ // The ICM 20948 chip has axes y-forward, x-right and Z-up - see Figure 12:
226+ // Orientation of Axes of Sensitivity and Polarity of Rotation
227+ // in DS-000189-ICM-20948-v1.6.pdf These are the axes for gyro and accel and quat
228+ //
229+ // For conversion to roll, pitch and yaw for the equations below, the coordinate frame
230+ // must be in aircraft reference frame.
231+ //
232+ // We use the Tait Bryan angles (in terms of flight dynamics):
233+ // ref: https://en.wikipedia.org/w/index.php?title=Conversion_between_quaternions_and_Euler_angles
234+ //
235+ // Heading – ψ : rotation about the Z-axis (+/- 180 deg.)
236+ // Pitch – θ : rotation about the new Y-axis (+/- 90 deg.)
237+ // Bank – ϕ : rotation about the new X-axis (+/- 180 deg.)
238+ //
239+ // where the X-axis points forward (pin 1 on chip), Y-axis to the right and Z-axis downward.
240+ // In the conversion example above the rotation occurs in the order heading, pitch, bank.
241+ // To get the roll, pitch and yaw equations to work properly we need to exchange the axes
242+
243+ // Note when pitch approaches +/- 90 deg. the heading and bank become less meaningfull because the
244+ // device is pointing up/down. (Gimbal lock)
227245
228246 double q0 = sqrt (1.0 - ((q1 * q1) + (q2 * q2) + (q3 * q3)));
229247
230- double q2sqr = q2 * q2;
248+ double qw = q0; // See issue #145 - thank you @Gord1
249+ double qx = q2;
250+ double qy = q1;
251+ double qz = -q3;
231252
232253 // roll (x-axis rotation)
233- double t0 = +2.0 * (q0 * q1 + q2 * q3 );
234- double t1 = +1.0 - 2.0 * (q1 * q1 + q2sqr );
254+ double t0 = +2.0 * (qw * qx + qy * qz );
255+ double t1 = +1.0 - 2.0 * (qx * qx + qy * qy );
235256 double roll = atan2 (t0, t1) * 180.0 / PI;
236257
237258 // pitch (y-axis rotation)
238- double t2 = +2.0 * (q0 * q2 - q3 * q1 );
259+ double t2 = +2.0 * (qw * qy - qx * qz );
239260 t2 = t2 > 1.0 ? 1.0 : t2;
240261 t2 = t2 < -1.0 ? -1.0 : t2;
241262 double pitch = asin (t2) * 180.0 / PI;
242263
243264 // yaw (z-axis rotation)
244- double t3 = +2.0 * (q0 * q3 + q1 * q2 );
245- double t4 = +1.0 - 2.0 * (q2sqr + q3 * q3 );
265+ double t3 = +2.0 * (qw * qz + qx * qy );
266+ double t4 = +1.0 - 2.0 * (qy * qy + qz * qz );
246267 double yaw = atan2 (t3, t4) * 180.0 / PI;
247268
248269#ifndef QUAT_ANIMATION
0 commit comments