Skip to content

Commit 6948fb7

Browse files
authored
Blackbox - IMU quaternion - fix case when w is negative (betaflight#14275)
quaternion w can ce negative, causing problem with unit quaternion reconstruction. Send inverted quaternion in negative-w case (q and -q are identical rotations)
1 parent 1359b40 commit 6948fb7

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

src/main/blackbox/blackbox.c

+14-6
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ typedef struct blackboxMainState_s {
365365
int16_t gyroUnfilt[XYZ_AXIS_COUNT];
366366
#ifdef USE_ACC
367367
int16_t accADC[XYZ_AXIS_COUNT];
368-
int16_t imuAttitudeQuaternion[XYZ_AXIS_COUNT];
368+
int16_t imuAttitudeQuaternion3[XYZ_AXIS_COUNT]; // only x,y,z is stored; w is always positive
369369
#endif
370370
int16_t debug[DEBUG16_VALUE_COUNT];
371371
int16_t motor[MAX_SUPPORTED_MOTORS];
@@ -747,7 +747,7 @@ static void writeIntraframe(void)
747747
}
748748

749749
if (testBlackboxCondition(CONDITION(ATTITUDE))) {
750-
blackboxWriteSigned16VBArray(blackboxCurrent->imuAttitudeQuaternion, XYZ_AXIS_COUNT);
750+
blackboxWriteSigned16VBArray(blackboxCurrent->imuAttitudeQuaternion3, XYZ_AXIS_COUNT);
751751
}
752752
#endif
753753

@@ -932,7 +932,7 @@ static void writeInterframe(void)
932932
}
933933

934934
if (testBlackboxCondition(CONDITION(ATTITUDE))) {
935-
blackboxWriteMainStateArrayUsingAveragePredictor(offsetof(blackboxMainState_t, imuAttitudeQuaternion), XYZ_AXIS_COUNT);
935+
blackboxWriteMainStateArrayUsingAveragePredictor(offsetof(blackboxMainState_t, imuAttitudeQuaternion3), XYZ_AXIS_COUNT);
936936
}
937937
#endif
938938

@@ -1250,14 +1250,22 @@ static void loadMainState(timeUs_t currentTimeUs)
12501250

12511251
#if defined(USE_ACC)
12521252
blackboxCurrent->accADC[i] = lrintf(acc.accADC.v[i]);
1253-
STATIC_ASSERT(offsetof(quaternion_t, w) == 0, "Code expects quaternion in w, x, y, z order");
1254-
blackboxCurrent->imuAttitudeQuaternion[i] = lrintf(imuAttitudeQuaternion.v[i + 1] * 0x7FFF); //Scale to int16 by value 0x7FFF = 2^15 - 1; Use i+1 index for x,y,z components access, [0] - w
12551253
#endif
12561254
#ifdef USE_MAG
12571255
blackboxCurrent->magADC[i] = lrintf(mag.magADC.v[i]);
12581256
#endif
12591257
}
1260-
1258+
#if defined(USE_ACC) // IMU quaternion
1259+
{
1260+
// write x,y,z of IMU quaternion. Make sure that w is always positive
1261+
STATIC_ASSERT(offsetof(quaternion_t, w) == 0, "Code expects quaternion in w, x, y, z order");
1262+
const float q_sign = imuAttitudeQuaternion.w < 0 ? -1 : 1; // invert quaternion if w is negative
1263+
const float q_scale = q_sign * 0x7FFF; // Scale to int16 by value 0x7FFF = 2^15 - 1 (-1 <= x,y,z <= 1)
1264+
for (int i = 0; i < XYZ_AXIS_COUNT; i++) {
1265+
blackboxCurrent->imuAttitudeQuaternion3[i] = lrintf(imuAttitudeQuaternion.v[i + 1] * q_scale); // Use i+1 index for x,y,z components access, [0] - w
1266+
}
1267+
}
1268+
#endif
12611269
for (int i = 0; i < 4; i++) {
12621270
blackboxCurrent->rcCommand[i] = lrintf(rcCommand[i] * blackboxHighResolutionScale);
12631271
}

0 commit comments

Comments
 (0)