3 #if HAL_CPU_CLASS >= HAL_CPU_CLASS_150 37 bool flightResetAllowed =
false;
38 bool initialResetAllowed =
false;
48 bool angRateOK = deltaRotVecTemp.
length() < 0.1745f;
50 initialResetAllowed = angRateOK;
51 flightResetAllowed = angRateOK && !
onGround;
56 bool finalResetRequest =
false;
57 bool interimResetRequest =
false;
68 bool yawInnovIncreasing = yawInnovIncrease > 0.25f;
73 bool largeAngleChange = deltaRotVecTemp.
length() > yawInnovIncrease;
77 interimResetRequest = hgtIncreasing && yawInnovIncreasing && !largeAngleChange;
85 initialResetRequest ||
86 interimResetRequest ||
151 if (finalResetRequest) {
152 gcs().
send_text(MAV_SEVERITY_INFO,
"EKF2 IMU%u in-flight yaw alignment complete",(
unsigned)
imu_index);
153 }
else if (interimResetRequest) {
154 gcs().
send_text(MAV_SEVERITY_WARNING,
"EKF2 IMU%u ground mag anomaly, yaw re-aligned",(
unsigned)
imu_index);
165 if (interimResetRequest) {
190 float yawErr =
MAX(fabsf(
wrap_PI(gpsYaw - velYaw)),fabsf(
wrap_PI(gpsYaw - eulerAngles.
z)));
378 DCM[0][0] = q0*q0 + q1*q1 - q2*q2 - q3*
q3;
379 DCM[0][1] = 2.0f*(q1*q2 + q0*
q3);
380 DCM[0][2] = 2.0f*(q1*q3-q0*
q2);
381 DCM[1][0] = 2.0f*(q1*q2 - q0*
q3);
382 DCM[1][1] = q0*q0 - q1*q1 + q2*q2 - q3*
q3;
383 DCM[1][2] = 2.0f*(q2*q3 + q0*
q1);
384 DCM[2][0] = 2.0f*(q1*q3 + q0*
q2);
385 DCM[2][1] = 2.0f*(q2*q3 - q0*
q1);
386 DCM[2][2] = q0*q0 - q1*q1 - q2*q2 + q3*
q3;
387 MagPred[0] = DCM[0][0]*magN + DCM[0][1]*magE + DCM[0][2]*magD +
magXbias;
388 MagPred[1] = DCM[1][0]*magN + DCM[1][1]*magE + DCM[1][2]*magD +
magYbias;
389 MagPred[2] = DCM[2][0]*magN + DCM[2][1]*magE + DCM[2][2]*magD +
magZbias;
392 for (uint8_t i = 0; i<=2; i++) {
400 SH_MAG[0] =
sq(q0) -
sq(q1) +
sq(q2) -
sq(q3);
401 SH_MAG[1] =
sq(q0) +
sq(q1) -
sq(q2) -
sq(q3);
402 SH_MAG[2] =
sq(q0) -
sq(q1) -
sq(q2) +
sq(q3);
403 SH_MAG[3] = 2.0f*q0*q1 + 2.0f*q2*
q3;
404 SH_MAG[4] = 2.0f*q0*q3 + 2.0f*q1*
q2;
405 SH_MAG[5] = 2.0f*q0*q2 + 2.0f*q1*
q3;
406 SH_MAG[6] = magE*(2.0f*q0*q1 - 2.0f*q2*
q3);
407 SH_MAG[7] = 2.0f*q1*q3 - 2.0f*q0*
q2;
408 SH_MAG[8] = 2.0f*q0*
q3;
412 varInnovMag[0] = (
P[19][19] + R_MAG -
P[1][19]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[16][19]*SH_MAG[1] +
P[17][19]*SH_MAG[4] +
P[18][19]*SH_MAG[7] +
P[2][19]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2)) - (magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5])*(
P[19][1] -
P[1][1]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[16][1]*SH_MAG[1] +
P[17][1]*SH_MAG[4] +
P[18][1]*SH_MAG[7] +
P[2][1]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2))) + SH_MAG[1]*(
P[19][16] -
P[1][16]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[16][16]*SH_MAG[1] +
P[17][16]*SH_MAG[4] +
P[18][16]*SH_MAG[7] +
P[2][16]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2))) + SH_MAG[4]*(
P[19][17] -
P[1][17]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[16][17]*SH_MAG[1] +
P[17][17]*SH_MAG[4] +
P[18][17]*SH_MAG[7] +
P[2][17]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2))) + SH_MAG[7]*(
P[19][18] -
P[1][18]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[16][18]*SH_MAG[1] +
P[17][18]*SH_MAG[4] +
P[18][18]*SH_MAG[7] +
P[2][18]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2))) + (magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*
q2))*(
P[19][2] -
P[1][2]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[16][2]*SH_MAG[1] +
P[17][2]*SH_MAG[4] +
P[18][2]*SH_MAG[7] +
P[2][2]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2))));
428 varInnovMag[1] = (
P[20][20] + R_MAG +
P[0][20]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[17][20]*SH_MAG[0] +
P[18][20]*SH_MAG[3] - (SH_MAG[8] - 2.0
f*q1*q2)*(
P[20][16] +
P[0][16]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[17][16]*SH_MAG[0] +
P[18][16]*SH_MAG[3] -
P[2][16]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[16][16]*(SH_MAG[8] - 2.0f*q1*
q2)) -
P[2][20]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) + (magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5])*(
P[20][0] +
P[0][0]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[17][0]*SH_MAG[0] +
P[18][0]*SH_MAG[3] -
P[2][0]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[16][0]*(SH_MAG[8] - 2.0f*q1*
q2)) + SH_MAG[0]*(
P[20][17] +
P[0][17]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[17][17]*SH_MAG[0] +
P[18][17]*SH_MAG[3] -
P[2][17]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[16][17]*(SH_MAG[8] - 2.0f*q1*
q2)) + SH_MAG[3]*(
P[20][18] +
P[0][18]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[17][18]*SH_MAG[0] +
P[18][18]*SH_MAG[3] -
P[2][18]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[16][18]*(SH_MAG[8] - 2.0f*q1*
q2)) -
P[16][20]*(SH_MAG[8] - 2.0f*q1*
q2) - (magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1])*(
P[20][2] +
P[0][2]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) +
P[17][2]*SH_MAG[0] +
P[18][2]*SH_MAG[3] -
P[2][2]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[16][2]*(SH_MAG[8] - 2.0f*q1*
q2)));
444 varInnovMag[2] = (
P[21][21] + R_MAG +
P[16][21]*SH_MAG[5] +
P[18][21]*SH_MAG[2] - (2.0f*q0*q1 - 2.0f*q2*
q3)*(
P[21][17] +
P[16][17]*SH_MAG[5] +
P[18][17]*SH_MAG[2] -
P[0][17]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2)) +
P[1][17]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[17][17]*(2.0
f*q0*q1 - 2.0
f*q2*q3)) -
P[0][21]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2)) +
P[1][21]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) + SH_MAG[5]*(
P[21][16] +
P[16][16]*SH_MAG[5] +
P[18][16]*SH_MAG[2] -
P[0][16]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*
q2)) +
P[1][16]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[17][16]*(2.0
f*q0*q1 - 2.0
f*q2*q3)) + SH_MAG[2]*(
P[21][18] +
P[16][18]*SH_MAG[5] +
P[18][18]*SH_MAG[2] -
P[0][18]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2)) +
P[1][18]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[17][18]*(2.0f*q0*q1 - 2.0f*q2*
q3)) - (magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*
q2))*(
P[21][0] +
P[16][0]*SH_MAG[5] +
P[18][0]*SH_MAG[2] -
P[0][0]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*
q2)) +
P[1][0]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[17][0]*(2.0
f*q0*q1 - 2.0
f*q2*q3)) -
P[17][21]*(2.0
f*q0*q1 - 2.0
f*q2*q3) + (magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1])*(
P[21][1] +
P[16][1]*SH_MAG[5] +
P[18][1]*SH_MAG[2] -
P[0][1]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0
f*q1*q2)) +
P[1][1]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) -
P[17][1]*(2.0f*q0*q1 - 2.0f*q2*
q3)));
460 for (uint8_t i = 0; i<=2; i++) {
474 H_MAG[1] = SH_MAG[6] - magD*SH_MAG[2] - magN*SH_MAG[5];
475 H_MAG[2] = magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*
q2);
476 H_MAG[16] = SH_MAG[1];
477 H_MAG[17] = SH_MAG[4];
478 H_MAG[18] = SH_MAG[7];
483 SK_MX[1] = magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*
q2);
484 SK_MX[2] = magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5];
485 SK_MX[3] = SH_MAG[7];
486 Kfusion[0] = SK_MX[0]*(
P[0][19] +
P[0][16]*SH_MAG[1] +
P[0][17]*SH_MAG[4] -
P[0][1]*SK_MX[2] +
P[0][2]*SK_MX[1] +
P[0][18]*SK_MX[3]);
487 Kfusion[1] = SK_MX[0]*(
P[1][19] +
P[1][16]*SH_MAG[1] +
P[1][17]*SH_MAG[4] -
P[1][1]*SK_MX[2] +
P[1][2]*SK_MX[1] +
P[1][18]*SK_MX[3]);
488 Kfusion[2] = SK_MX[0]*(
P[2][19] +
P[2][16]*SH_MAG[1] +
P[2][17]*SH_MAG[4] -
P[2][1]*SK_MX[2] +
P[2][2]*SK_MX[1] +
P[2][18]*SK_MX[3]);
489 Kfusion[3] = SK_MX[0]*(
P[3][19] +
P[3][16]*SH_MAG[1] +
P[3][17]*SH_MAG[4] -
P[3][1]*SK_MX[2] +
P[3][2]*SK_MX[1] +
P[3][18]*SK_MX[3]);
490 Kfusion[4] = SK_MX[0]*(
P[4][19] +
P[4][16]*SH_MAG[1] +
P[4][17]*SH_MAG[4] -
P[4][1]*SK_MX[2] +
P[4][2]*SK_MX[1] +
P[4][18]*SK_MX[3]);
491 Kfusion[5] = SK_MX[0]*(
P[5][19] +
P[5][16]*SH_MAG[1] +
P[5][17]*SH_MAG[4] -
P[5][1]*SK_MX[2] +
P[5][2]*SK_MX[1] +
P[5][18]*SK_MX[3]);
492 Kfusion[6] = SK_MX[0]*(
P[6][19] +
P[6][16]*SH_MAG[1] +
P[6][17]*SH_MAG[4] -
P[6][1]*SK_MX[2] +
P[6][2]*SK_MX[1] +
P[6][18]*SK_MX[3]);
493 Kfusion[7] = SK_MX[0]*(
P[7][19] +
P[7][16]*SH_MAG[1] +
P[7][17]*SH_MAG[4] -
P[7][1]*SK_MX[2] +
P[7][2]*SK_MX[1] +
P[7][18]*SK_MX[3]);
494 Kfusion[8] = SK_MX[0]*(
P[8][19] +
P[8][16]*SH_MAG[1] +
P[8][17]*SH_MAG[4] -
P[8][1]*SK_MX[2] +
P[8][2]*SK_MX[1] +
P[8][18]*SK_MX[3]);
495 Kfusion[9] = SK_MX[0]*(
P[9][19] +
P[9][16]*SH_MAG[1] +
P[9][17]*SH_MAG[4] -
P[9][1]*SK_MX[2] +
P[9][2]*SK_MX[1] +
P[9][18]*SK_MX[3]);
496 Kfusion[10] = SK_MX[0]*(
P[10][19] +
P[10][16]*SH_MAG[1] +
P[10][17]*SH_MAG[4] -
P[10][1]*SK_MX[2] +
P[10][2]*SK_MX[1] +
P[10][18]*SK_MX[3]);
497 Kfusion[11] = SK_MX[0]*(
P[11][19] +
P[11][16]*SH_MAG[1] +
P[11][17]*SH_MAG[4] -
P[11][1]*SK_MX[2] +
P[11][2]*SK_MX[1] +
P[11][18]*SK_MX[3]);
498 Kfusion[12] = SK_MX[0]*(
P[12][19] +
P[12][16]*SH_MAG[1] +
P[12][17]*SH_MAG[4] -
P[12][1]*SK_MX[2] +
P[12][2]*SK_MX[1] +
P[12][18]*SK_MX[3]);
499 Kfusion[13] = SK_MX[0]*(
P[13][19] +
P[13][16]*SH_MAG[1] +
P[13][17]*SH_MAG[4] -
P[13][1]*SK_MX[2] +
P[13][2]*SK_MX[1] +
P[13][18]*SK_MX[3]);
500 Kfusion[14] = SK_MX[0]*(
P[14][19] +
P[14][16]*SH_MAG[1] +
P[14][17]*SH_MAG[4] -
P[14][1]*SK_MX[2] +
P[14][2]*SK_MX[1] +
P[14][18]*SK_MX[3]);
501 Kfusion[15] = SK_MX[0]*(
P[15][19] +
P[15][16]*SH_MAG[1] +
P[15][17]*SH_MAG[4] -
P[15][1]*SK_MX[2] +
P[15][2]*SK_MX[1] +
P[15][18]*SK_MX[3]);
506 Kfusion[22] = SK_MX[0]*(
P[22][19] +
P[22][16]*SH_MAG[1] +
P[22][17]*SH_MAG[4] -
P[22][1]*SK_MX[2] +
P[22][2]*SK_MX[1] +
P[22][18]*SK_MX[3]);
507 Kfusion[23] = SK_MX[0]*(
P[23][19] +
P[23][16]*SH_MAG[1] +
P[23][17]*SH_MAG[4] -
P[23][1]*SK_MX[2] +
P[23][2]*SK_MX[1] +
P[23][18]*SK_MX[3]);
514 Kfusion[16] = SK_MX[0]*(
P[16][19] +
P[16][16]*SH_MAG[1] +
P[16][17]*SH_MAG[4] -
P[16][1]*SK_MX[2] +
P[16][2]*SK_MX[1] +
P[16][18]*SK_MX[3]);
515 Kfusion[17] = SK_MX[0]*(
P[17][19] +
P[17][16]*SH_MAG[1] +
P[17][17]*SH_MAG[4] -
P[17][1]*SK_MX[2] +
P[17][2]*SK_MX[1] +
P[17][18]*SK_MX[3]);
516 Kfusion[18] = SK_MX[0]*(
P[18][19] +
P[18][16]*SH_MAG[1] +
P[18][17]*SH_MAG[4] -
P[18][1]*SK_MX[2] +
P[18][2]*SK_MX[1] +
P[18][18]*SK_MX[3]);
517 Kfusion[19] = SK_MX[0]*(
P[19][19] +
P[19][16]*SH_MAG[1] +
P[19][17]*SH_MAG[4] -
P[19][1]*SK_MX[2] +
P[19][2]*SK_MX[1] +
P[19][18]*SK_MX[3]);
518 Kfusion[20] = SK_MX[0]*(
P[20][19] +
P[20][16]*SH_MAG[1] +
P[20][17]*SH_MAG[4] -
P[20][1]*SK_MX[2] +
P[20][2]*SK_MX[1] +
P[20][18]*SK_MX[3]);
519 Kfusion[21] = SK_MX[0]*(
P[21][19] +
P[21][16]*SH_MAG[1] +
P[21][17]*SH_MAG[4] -
P[21][1]*SK_MX[2] +
P[21][2]*SK_MX[1] +
P[21][18]*SK_MX[3]);
521 for (uint8_t i=16; i<=21; i++) {
537 else if (obsIndex == 1)
544 H_MAG[0] = magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5];
545 H_MAG[2] = - magE*SH_MAG[4] - magD*SH_MAG[7] - magN*SH_MAG[1];
546 H_MAG[16] = 2.0f*q1*q2 - SH_MAG[8];
547 H_MAG[17] = SH_MAG[0];
548 H_MAG[18] = SH_MAG[3];
553 SK_MY[1] = magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1];
554 SK_MY[2] = magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5];
555 SK_MY[3] = SH_MAG[8] - 2.0f*q1*
q2;
556 Kfusion[0] = SK_MY[0]*(
P[0][20] +
P[0][17]*SH_MAG[0] +
P[0][18]*SH_MAG[3] +
P[0][0]*SK_MY[2] -
P[0][2]*SK_MY[1] -
P[0][16]*SK_MY[3]);
557 Kfusion[1] = SK_MY[0]*(
P[1][20] +
P[1][17]*SH_MAG[0] +
P[1][18]*SH_MAG[3] +
P[1][0]*SK_MY[2] -
P[1][2]*SK_MY[1] -
P[1][16]*SK_MY[3]);
558 Kfusion[2] = SK_MY[0]*(
P[2][20] +
P[2][17]*SH_MAG[0] +
P[2][18]*SH_MAG[3] +
P[2][0]*SK_MY[2] -
P[2][2]*SK_MY[1] -
P[2][16]*SK_MY[3]);
559 Kfusion[3] = SK_MY[0]*(
P[3][20] +
P[3][17]*SH_MAG[0] +
P[3][18]*SH_MAG[3] +
P[3][0]*SK_MY[2] -
P[3][2]*SK_MY[1] -
P[3][16]*SK_MY[3]);
560 Kfusion[4] = SK_MY[0]*(
P[4][20] +
P[4][17]*SH_MAG[0] +
P[4][18]*SH_MAG[3] +
P[4][0]*SK_MY[2] -
P[4][2]*SK_MY[1] -
P[4][16]*SK_MY[3]);
561 Kfusion[5] = SK_MY[0]*(
P[5][20] +
P[5][17]*SH_MAG[0] +
P[5][18]*SH_MAG[3] +
P[5][0]*SK_MY[2] -
P[5][2]*SK_MY[1] -
P[5][16]*SK_MY[3]);
562 Kfusion[6] = SK_MY[0]*(
P[6][20] +
P[6][17]*SH_MAG[0] +
P[6][18]*SH_MAG[3] +
P[6][0]*SK_MY[2] -
P[6][2]*SK_MY[1] -
P[6][16]*SK_MY[3]);
563 Kfusion[7] = SK_MY[0]*(
P[7][20] +
P[7][17]*SH_MAG[0] +
P[7][18]*SH_MAG[3] +
P[7][0]*SK_MY[2] -
P[7][2]*SK_MY[1] -
P[7][16]*SK_MY[3]);
564 Kfusion[8] = SK_MY[0]*(
P[8][20] +
P[8][17]*SH_MAG[0] +
P[8][18]*SH_MAG[3] +
P[8][0]*SK_MY[2] -
P[8][2]*SK_MY[1] -
P[8][16]*SK_MY[3]);
565 Kfusion[9] = SK_MY[0]*(
P[9][20] +
P[9][17]*SH_MAG[0] +
P[9][18]*SH_MAG[3] +
P[9][0]*SK_MY[2] -
P[9][2]*SK_MY[1] -
P[9][16]*SK_MY[3]);
566 Kfusion[10] = SK_MY[0]*(
P[10][20] +
P[10][17]*SH_MAG[0] +
P[10][18]*SH_MAG[3] +
P[10][0]*SK_MY[2] -
P[10][2]*SK_MY[1] -
P[10][16]*SK_MY[3]);
567 Kfusion[11] = SK_MY[0]*(
P[11][20] +
P[11][17]*SH_MAG[0] +
P[11][18]*SH_MAG[3] +
P[11][0]*SK_MY[2] -
P[11][2]*SK_MY[1] -
P[11][16]*SK_MY[3]);
568 Kfusion[12] = SK_MY[0]*(
P[12][20] +
P[12][17]*SH_MAG[0] +
P[12][18]*SH_MAG[3] +
P[12][0]*SK_MY[2] -
P[12][2]*SK_MY[1] -
P[12][16]*SK_MY[3]);
569 Kfusion[13] = SK_MY[0]*(
P[13][20] +
P[13][17]*SH_MAG[0] +
P[13][18]*SH_MAG[3] +
P[13][0]*SK_MY[2] -
P[13][2]*SK_MY[1] -
P[13][16]*SK_MY[3]);
570 Kfusion[14] = SK_MY[0]*(
P[14][20] +
P[14][17]*SH_MAG[0] +
P[14][18]*SH_MAG[3] +
P[14][0]*SK_MY[2] -
P[14][2]*SK_MY[1] -
P[14][16]*SK_MY[3]);
571 Kfusion[15] = SK_MY[0]*(
P[15][20] +
P[15][17]*SH_MAG[0] +
P[15][18]*SH_MAG[3] +
P[15][0]*SK_MY[2] -
P[15][2]*SK_MY[1] -
P[15][16]*SK_MY[3]);
574 Kfusion[22] = SK_MY[0]*(
P[22][20] +
P[22][17]*SH_MAG[0] +
P[22][18]*SH_MAG[3] +
P[22][0]*SK_MY[2] -
P[22][2]*SK_MY[1] -
P[22][16]*SK_MY[3]);
575 Kfusion[23] = SK_MY[0]*(
P[23][20] +
P[23][17]*SH_MAG[0] +
P[23][18]*SH_MAG[3] +
P[23][0]*SK_MY[2] -
P[23][2]*SK_MY[1] -
P[23][16]*SK_MY[3]);
582 Kfusion[16] = SK_MY[0]*(
P[16][20] +
P[16][17]*SH_MAG[0] +
P[16][18]*SH_MAG[3] +
P[16][0]*SK_MY[2] -
P[16][2]*SK_MY[1] -
P[16][16]*SK_MY[3]);
583 Kfusion[17] = SK_MY[0]*(
P[17][20] +
P[17][17]*SH_MAG[0] +
P[17][18]*SH_MAG[3] +
P[17][0]*SK_MY[2] -
P[17][2]*SK_MY[1] -
P[17][16]*SK_MY[3]);
584 Kfusion[18] = SK_MY[0]*(
P[18][20] +
P[18][17]*SH_MAG[0] +
P[18][18]*SH_MAG[3] +
P[18][0]*SK_MY[2] -
P[18][2]*SK_MY[1] -
P[18][16]*SK_MY[3]);
585 Kfusion[19] = SK_MY[0]*(
P[19][20] +
P[19][17]*SH_MAG[0] +
P[19][18]*SH_MAG[3] +
P[19][0]*SK_MY[2] -
P[19][2]*SK_MY[1] -
P[19][16]*SK_MY[3]);
586 Kfusion[20] = SK_MY[0]*(
P[20][20] +
P[20][17]*SH_MAG[0] +
P[20][18]*SH_MAG[3] +
P[20][0]*SK_MY[2] -
P[20][2]*SK_MY[1] -
P[20][16]*SK_MY[3]);
587 Kfusion[21] = SK_MY[0]*(
P[21][20] +
P[21][17]*SH_MAG[0] +
P[21][18]*SH_MAG[3] +
P[21][0]*SK_MY[2] -
P[21][2]*SK_MY[1] -
P[21][16]*SK_MY[3]);
589 for (uint8_t i=16; i<=21; i++) {
602 else if (obsIndex == 2)
609 H_MAG[0] = magN*(SH_MAG[8] - 2.0f*q1*
q2) - magD*SH_MAG[3] - magE*SH_MAG[0];
610 H_MAG[1] = magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1];
611 H_MAG[16] = SH_MAG[5];
612 H_MAG[17] = 2.0f*q2*q3 - 2.0f*q0*
q1;
613 H_MAG[18] = SH_MAG[2];
618 SK_MZ[1] = magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*
q2);
619 SK_MZ[2] = magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1];
620 SK_MZ[3] = 2.0f*q0*q1 - 2.0f*q2*
q3;
621 Kfusion[0] = SK_MZ[0]*(
P[0][21] +
P[0][18]*SH_MAG[2] +
P[0][16]*SH_MAG[5] -
P[0][0]*SK_MZ[1] +
P[0][1]*SK_MZ[2] -
P[0][17]*SK_MZ[3]);
622 Kfusion[1] = SK_MZ[0]*(
P[1][21] +
P[1][18]*SH_MAG[2] +
P[1][16]*SH_MAG[5] -
P[1][0]*SK_MZ[1] +
P[1][1]*SK_MZ[2] -
P[1][17]*SK_MZ[3]);
623 Kfusion[2] = SK_MZ[0]*(
P[2][21] +
P[2][18]*SH_MAG[2] +
P[2][16]*SH_MAG[5] -
P[2][0]*SK_MZ[1] +
P[2][1]*SK_MZ[2] -
P[2][17]*SK_MZ[3]);
624 Kfusion[3] = SK_MZ[0]*(
P[3][21] +
P[3][18]*SH_MAG[2] +
P[3][16]*SH_MAG[5] -
P[3][0]*SK_MZ[1] +
P[3][1]*SK_MZ[2] -
P[3][17]*SK_MZ[3]);
625 Kfusion[4] = SK_MZ[0]*(
P[4][21] +
P[4][18]*SH_MAG[2] +
P[4][16]*SH_MAG[5] -
P[4][0]*SK_MZ[1] +
P[4][1]*SK_MZ[2] -
P[4][17]*SK_MZ[3]);
626 Kfusion[5] = SK_MZ[0]*(
P[5][21] +
P[5][18]*SH_MAG[2] +
P[5][16]*SH_MAG[5] -
P[5][0]*SK_MZ[1] +
P[5][1]*SK_MZ[2] -
P[5][17]*SK_MZ[3]);
627 Kfusion[6] = SK_MZ[0]*(
P[6][21] +
P[6][18]*SH_MAG[2] +
P[6][16]*SH_MAG[5] -
P[6][0]*SK_MZ[1] +
P[6][1]*SK_MZ[2] -
P[6][17]*SK_MZ[3]);
628 Kfusion[7] = SK_MZ[0]*(
P[7][21] +
P[7][18]*SH_MAG[2] +
P[7][16]*SH_MAG[5] -
P[7][0]*SK_MZ[1] +
P[7][1]*SK_MZ[2] -
P[7][17]*SK_MZ[3]);
629 Kfusion[8] = SK_MZ[0]*(
P[8][21] +
P[8][18]*SH_MAG[2] +
P[8][16]*SH_MAG[5] -
P[8][0]*SK_MZ[1] +
P[8][1]*SK_MZ[2] -
P[8][17]*SK_MZ[3]);
630 Kfusion[9] = SK_MZ[0]*(
P[9][21] +
P[9][18]*SH_MAG[2] +
P[9][16]*SH_MAG[5] -
P[9][0]*SK_MZ[1] +
P[9][1]*SK_MZ[2] -
P[9][17]*SK_MZ[3]);
631 Kfusion[10] = SK_MZ[0]*(
P[10][21] +
P[10][18]*SH_MAG[2] +
P[10][16]*SH_MAG[5] -
P[10][0]*SK_MZ[1] +
P[10][1]*SK_MZ[2] -
P[10][17]*SK_MZ[3]);
632 Kfusion[11] = SK_MZ[0]*(
P[11][21] +
P[11][18]*SH_MAG[2] +
P[11][16]*SH_MAG[5] -
P[11][0]*SK_MZ[1] +
P[11][1]*SK_MZ[2] -
P[11][17]*SK_MZ[3]);
633 Kfusion[12] = SK_MZ[0]*(
P[12][21] +
P[12][18]*SH_MAG[2] +
P[12][16]*SH_MAG[5] -
P[12][0]*SK_MZ[1] +
P[12][1]*SK_MZ[2] -
P[12][17]*SK_MZ[3]);
634 Kfusion[13] = SK_MZ[0]*(
P[13][21] +
P[13][18]*SH_MAG[2] +
P[13][16]*SH_MAG[5] -
P[13][0]*SK_MZ[1] +
P[13][1]*SK_MZ[2] -
P[13][17]*SK_MZ[3]);
635 Kfusion[14] = SK_MZ[0]*(
P[14][21] +
P[14][18]*SH_MAG[2] +
P[14][16]*SH_MAG[5] -
P[14][0]*SK_MZ[1] +
P[14][1]*SK_MZ[2] -
P[14][17]*SK_MZ[3]);
636 Kfusion[15] = SK_MZ[0]*(
P[15][21] +
P[15][18]*SH_MAG[2] +
P[15][16]*SH_MAG[5] -
P[15][0]*SK_MZ[1] +
P[15][1]*SK_MZ[2] -
P[15][17]*SK_MZ[3]);
639 Kfusion[22] = SK_MZ[0]*(
P[22][21] +
P[22][18]*SH_MAG[2] +
P[22][16]*SH_MAG[5] -
P[22][0]*SK_MZ[1] +
P[22][1]*SK_MZ[2] -
P[22][17]*SK_MZ[3]);
640 Kfusion[23] = SK_MZ[0]*(
P[23][21] +
P[23][18]*SH_MAG[2] +
P[23][16]*SH_MAG[5] -
P[23][0]*SK_MZ[1] +
P[23][1]*SK_MZ[2] -
P[23][17]*SK_MZ[3]);
647 Kfusion[16] = SK_MZ[0]*(
P[16][21] +
P[16][18]*SH_MAG[2] +
P[16][16]*SH_MAG[5] -
P[16][0]*SK_MZ[1] +
P[16][1]*SK_MZ[2] -
P[16][17]*SK_MZ[3]);
648 Kfusion[17] = SK_MZ[0]*(
P[17][21] +
P[17][18]*SH_MAG[2] +
P[17][16]*SH_MAG[5] -
P[17][0]*SK_MZ[1] +
P[17][1]*SK_MZ[2] -
P[17][17]*SK_MZ[3]);
649 Kfusion[18] = SK_MZ[0]*(
P[18][21] +
P[18][18]*SH_MAG[2] +
P[18][16]*SH_MAG[5] -
P[18][0]*SK_MZ[1] +
P[18][1]*SK_MZ[2] -
P[18][17]*SK_MZ[3]);
650 Kfusion[19] = SK_MZ[0]*(
P[19][21] +
P[19][18]*SH_MAG[2] +
P[19][16]*SH_MAG[5] -
P[19][0]*SK_MZ[1] +
P[19][1]*SK_MZ[2] -
P[19][17]*SK_MZ[3]);
651 Kfusion[20] = SK_MZ[0]*(
P[20][21] +
P[20][18]*SH_MAG[2] +
P[20][16]*SH_MAG[5] -
P[20][0]*SK_MZ[1] +
P[20][1]*SK_MZ[2] -
P[20][17]*SK_MZ[3]);
652 Kfusion[21] = SK_MZ[0]*(
P[21][21] +
P[21][18]*SH_MAG[2] +
P[21][16]*SH_MAG[5] -
P[21][0]*SK_MZ[1] +
P[21][1]*SK_MZ[2] -
P[21][17]*SK_MZ[3]);
654 for (uint8_t i=16; i<=21; i++) {
674 for (
unsigned j = 0; j<=2; j++) {
677 for (
unsigned j = 3; j<=15; j++) {
680 for (
unsigned j = 16; j<=21; j++) {
683 for (
unsigned j = 22; j<=23; j++) {
690 res +=
KH[i][0] *
P[0][j];
691 res +=
KH[i][1] * P[1][j];
692 res +=
KH[i][2] * P[2][j];
693 res +=
KH[i][16] * P[16][j];
694 res +=
KH[i][17] * P[17][j];
695 res +=
KH[i][18] * P[18][j];
696 res +=
KH[i][19] * P[19][j];
697 res +=
KH[i][20] * P[20][j];
698 res +=
KH[i][21] * P[21][j];
703 bool healthyFusion =
true;
705 if (
KHP[i][i] >
P[i][i]) {
706 healthyFusion =
false;
713 P[i][j] =
P[i][j] -
KHP[i][j];
738 }
else if (obsIndex == 1) {
740 }
else if (obsIndex == 2) {
784 float t6 = t2+t3-t4-
t5;
785 float t7 = q0*q3*2.0f;
786 float t8 = q1*q2*2.0f;
796 float t13 = t12+1.0f;
798 if (fabsf(t13) > 1e-3
f) {
805 H_YAW[1] = t14*(t15*(q0*q1*2.0f-q2*q3*2.0f)+t9*t10*(q0*q2*2.0
f+q1*q3*2.0
f));
806 H_YAW[2] = t14*(t15*(t2-t3+t4-
t5)+t9*t10*(t7-t8));
811 predicted_yaw = euler321.z;
814 Tbn_zeroYaw.
from_euler(euler321.x, euler321.y, 0.0f);
820 measured_yaw = euler321.z;
823 measured_yaw = predicted_yaw;
831 float t6 = t2-t3+t4-
t5;
832 float t7 = q0*q3*2.0f;
833 float t10 = q1*q2*2.0f;
843 float t13 = t12+1.0f;
845 if (fabsf(t13) > 1e-3
f) {
851 H_YAW[0] = -t14*(t15*(q0*q2*2.0+q1*q3*2.0)-t8*t9*(q0*q1*2.0-q2*q3*2.0));
853 H_YAW[2] = t14*(t15*(t2+t3-t4-
t5)+t8*t9*(t7+t10));
857 predicted_yaw = euler312.
z;
866 measured_yaw = euler312.
z;
869 measured_yaw = predicted_yaw;
874 float innovation =
wrap_PI(predicted_yaw - measured_yaw);
881 float varInnov = R_YAW;
882 for (uint8_t rowIndex=0; rowIndex<=2; rowIndex++) {
884 for (uint8_t colIndex=0; colIndex<=2; colIndex++) {
885 PH[rowIndex] +=
P[rowIndex][colIndex]*H_YAW[colIndex];
887 varInnov += H_YAW[rowIndex]*PH[rowIndex];
890 if (varInnov >= R_YAW) {
891 varInnovInv = 1.0f / varInnov;
904 for (uint8_t rowIndex=0; rowIndex<=
stateIndexLim; rowIndex++) {
906 for (uint8_t colIndex=0; colIndex<=2; colIndex++) {
907 Kfusion[rowIndex] +=
P[rowIndex][colIndex]*H_YAW[colIndex];
909 Kfusion[rowIndex] *= varInnovInv;
928 if (innovation > 0.5
f) {
930 }
else if (innovation < -0.5
f) {
937 for (uint8_t column = 0; column <= 2; column++) {
938 KH[row][column] =
Kfusion[row] * H_YAW[column];
942 for (uint8_t column = 0; column <=
stateIndexLim; column++) {
943 float tmp =
KH[row][0] *
P[0][column];
944 tmp +=
KH[row][1] * P[1][column];
945 tmp +=
KH[row][2] * P[2][column];
946 KHP[row][column] = tmp;
951 bool healthyFusion =
true;
953 if (
KHP[i][i] >
P[i][i]) {
954 healthyFusion =
false;
961 P[i][j] =
P[i][j] -
KHP[i][j];
1002 const float R_DECL =
sq(declErr);
1018 float t22 = magE*
t5;
1019 float t23 = magN*
t5;
1020 float t6 =
P[16][16]*
t22;
1024 float t9 =
P[16][17]*
t22;
1028 float t11 = R_DECL+t8-
t15;
1035 H_MAG[16] = -magE*
t5;
1036 H_MAG[17] = magN*
t5;
1038 for (uint8_t i=0; i<=15; i++) {
1042 Kfusion[17] = t12*(t14-
P[17][16]*
t22);
1043 for (uint8_t i=17; i<=23; i++) {
1044 Kfusion[i] = -t12*(
P[i][16]*t22-
P[i][17]*
t23);
1051 float innovation = atan2f(magE , magN) - magDecAng;
1054 if (innovation > 0.5
f) {
1056 }
else if (innovation < -0.5
f) {
1064 for (
unsigned j = 0; j<=15; j++) {
1067 KH[i][16] = Kfusion[i] * H_MAG[16];
1068 KH[i][17] = Kfusion[i] * H_MAG[17];
1069 for (
unsigned j = 18; j<=23; j++) {
1075 KHP[i][j] =
KH[i][16] *
P[16][j] +
KH[i][17] *
P[17][j];
1080 bool healthyFusion =
true;
1082 if (
KHP[i][i] >
P[i][i]) {
1083 healthyFusion =
false;
1087 if (healthyFusion) {
1091 P[i][j] =
P[i][j] -
KHP[i][j];
1136 float magLengthNE =
norm(initMagNED.
x,initMagNED.
y);
1142 float var_16 =
P[16][16];
1143 float var_17 =
P[17][17];
1171 #endif // HAL_CPU_CLASS
float norm(const T first, const U second, const Params... parameters)
void to_euler(float &roll, float &pitch, float &yaw) const
gps_elements gpsDataDelayed
void controlMagYawReset()
#define EKF2_MAG_FINAL_RESET_ALT
void zeroCols(Matrix24 &covMat, uint8_t first, uint8_t last)
const float magVarRateScale
Quaternion quatAtLastMagReset
bool extNavYawResetRequest
void to_axis_angle(Vector3f &v)
float get_declination() const
Quaternion prevQuatMagReset
mag_elements magDataDelayed
Interface definition for the various Ground Control System.
bool assume_zero_sideslip(void) const
float yawInnovAtLastMagReset
struct NavEKF2_core::@147 mag_state
void zeroRows(Matrix24 &covMat, uint8_t first, uint8_t last)
void from_euler(float roll, float pitch, float yaw)
bool finalInflightMagInit
void from_euler(float roll, float pitch, float yaw)
Quaternion calcQuatAndFieldStates(float roll, float pitch)
struct NavEKF2_core::state_elements & stateStruct
uint32_t imuSampleTime_ms
static auto MAX(const A &one, const B &two) -> decltype(one > two ? one :two)
const Compass * get_compass() const
imu_elements imuDataDelayed
Vector3f earthMagFieldVar
struct NavEKF2_core::@145 faultStatus
float wrap_PI(const T radian)
uint32_t lastHealthyMagTime_ms
const AP_HAL::HAL & hal
-*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
virtual void perf_end(perf_counter_t h)
float posDownAtLastMagReset
obs_ring_buffer_t< mag_elements > storedMag
void send_text(MAV_SEVERITY severity, const char *fmt,...)
bool use_compass(void) const
AP_HAL::Util::perf_counter_t _perf_test[10]
bool magStateInitComplete
AP_HAL::Util::perf_counter_t _perf_FuseMagnetometer
void ConstrainVariances()
void from_euler312(float roll, float pitch, float yaw)
bool finalInflightYawInit
float constrain_float(const float amt, const float low, const float high)
ext_nav_elements extNavDataDelayed
Vector3f to_vector312(void) const
virtual void perf_begin(perf_counter_t h)
void alignMagStateDeclination()
const uint16_t magFailTimeLimit_ms
void FuseDeclination(float declErr)
void rotate(const Vector3f &v)
bool magStateResetRequest
void StoreQuatRotate(Quaternion deltaQuat)