45 #include <mathlib/mathlib.h> 61 R_MAG = R_MAG * R_MAG;
65 SH_MAG[0] = 2.0f*magD*q3 + 2.0f*magE*q2 + 2.0f*magN*q1;
66 SH_MAG[1] = 2.0f*magD*q0 - 2.0f*magE*q1 + 2.0f*magN*q2;
67 SH_MAG[2] = 2.0f*magD*q1 + 2.0f*magE*q0 - 2.0f*magN*q3;
72 SH_MAG[7] = 2.0f*magN*q0;
73 SH_MAG[8] = 2.0f*magE*q3;
95 _mag_innov_var[0] = (
P[19][19] + R_MAG +
P[1][19]*SH_MAG[0] -
P[2][19]*SH_MAG[1] +
P[3][19]*SH_MAG[2] -
P[16][19]*(SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6]) + (2.0
f*q0*q3 + 2.0
f*q1*q2)*(
P[19][17] +
P[1][17]*SH_MAG[0] -
P[2][17]*SH_MAG[1] +
P[3][17]*SH_MAG[2] -
P[16][17]*(SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6]) +
P[17][17]*(2.0
f*q0*q3 + 2.0
f*q1*q2) -
P[18][17]*(2.0f*q0*q2 - 2.0f*q1*q3) +
P[0][17]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) - (2.0
f*q0*q2 - 2.0
f*q1*q3)*(
P[19][18] +
P[1][18]*SH_MAG[0] -
P[2][18]*SH_MAG[1] +
P[3][18]*SH_MAG[2] -
P[16][18]*(SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6]) +
P[17][18]*(2.0
f*q0*q3 + 2.0
f*q1*q2) -
P[18][18]*(2.0f*q0*q2 - 2.0f*q1*q3) +
P[0][18]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) + (SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)*(
P[19][0] +
P[1][0]*SH_MAG[0] -
P[2][0]*SH_MAG[1] +
P[3][0]*SH_MAG[2] -
P[16][0]*(SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6]) +
P[17][0]*(2.0
f*q0*q3 + 2.0
f*q1*q2) -
P[18][0]*(2.0f*q0*q2 - 2.0f*q1*q3) +
P[0][0]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) +
P[17][19]*(2.0
f*q0*q3 + 2.0
f*q1*q2) -
P[18][19]*(2.0f*q0*q2 - 2.0f*q1*q3) + SH_MAG[0]*(
P[19][1] +
P[1][1]*SH_MAG[0] -
P[2][1]*SH_MAG[1] +
P[3][1]*SH_MAG[2] -
P[16][1]*(SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6]) +
P[17][1]*(2.0f*q0*q3 + 2.0f*q1*q2) -
P[18][1]*(2.0
f*q0*q2 - 2.0
f*q1*q3) +
P[0][1]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) - SH_MAG[1]*(
P[19][2] +
P[1][2]*SH_MAG[0] -
P[2][2]*SH_MAG[1] +
P[3][2]*SH_MAG[2] -
P[16][2]*(SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6]) +
P[17][2]*(2.0
f*q0*q3 + 2.0
f*q1*q2) -
P[18][2]*(2.0f*q0*q2 - 2.0f*q1*q3) +
P[0][2]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) + SH_MAG[2]*(
P[19][3] +
P[1][3]*SH_MAG[0] -
P[2][3]*SH_MAG[1] +
P[3][3]*SH_MAG[2] -
P[16][3]*(SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6]) +
P[17][3]*(2.0f*q0*q3 + 2.0f*q1*q2) -
P[18][3]*(2.0
f*q0*q2 - 2.0
f*q1*q3) +
P[0][3]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) - (SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6])*(
P[19][16] +
P[1][16]*SH_MAG[0] -
P[2][16]*SH_MAG[1] +
P[3][16]*SH_MAG[2] -
P[16][16]*(SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6]) +
P[17][16]*(2.0f*q0*q3 + 2.0f*q1*q2) -
P[18][16]*(2.0
f*q0*q2 - 2.0
f*q1*q3) +
P[0][16]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) +
P[0][19]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2));
114 _mag_innov_var[1] = (
P[20][20] + R_MAG +
P[0][20]*SH_MAG[2] +
P[1][20]*SH_MAG[1] +
P[2][20]*SH_MAG[0] -
P[17][20]*(SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6]) - (2.0
f*q0*q3 - 2.0
f*q1*q2)*(
P[20][16] +
P[0][16]*SH_MAG[2] +
P[1][16]*SH_MAG[1] +
P[2][16]*SH_MAG[0] -
P[17][16]*(SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6]) -
P[16][16]*(2.0
f*q0*q3 - 2.0
f*q1*q2) +
P[18][16]*(2.0f*q0*q1 + 2.0f*q2*q3) -
P[3][16]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) + (2.0
f*q0*q1 + 2.0
f*q2*q3)*(
P[20][18] +
P[0][18]*SH_MAG[2] +
P[1][18]*SH_MAG[1] +
P[2][18]*SH_MAG[0] -
P[17][18]*(SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6]) -
P[16][18]*(2.0
f*q0*q3 - 2.0
f*q1*q2) +
P[18][18]*(2.0f*q0*q1 + 2.0f*q2*q3) -
P[3][18]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) - (SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)*(
P[20][3] +
P[0][3]*SH_MAG[2] +
P[1][3]*SH_MAG[1] +
P[2][3]*SH_MAG[0] -
P[17][3]*(SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6]) -
P[16][3]*(2.0
f*q0*q3 - 2.0
f*q1*q2) +
P[18][3]*(2.0f*q0*q1 + 2.0f*q2*q3) -
P[3][3]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) -
P[16][20]*(2.0
f*q0*q3 - 2.0
f*q1*q2) +
P[18][20]*(2.0f*q0*q1 + 2.0f*q2*q3) + SH_MAG[2]*(
P[20][0] +
P[0][0]*SH_MAG[2] +
P[1][0]*SH_MAG[1] +
P[2][0]*SH_MAG[0] -
P[17][0]*(SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6]) -
P[16][0]*(2.0f*q0*q3 - 2.0f*q1*q2) +
P[18][0]*(2.0
f*q0*q1 + 2.0
f*q2*q3) -
P[3][0]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) + SH_MAG[1]*(
P[20][1] +
P[0][1]*SH_MAG[2] +
P[1][1]*SH_MAG[1] +
P[2][1]*SH_MAG[0] -
P[17][1]*(SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6]) -
P[16][1]*(2.0
f*q0*q3 - 2.0
f*q1*q2) +
P[18][1]*(2.0f*q0*q1 + 2.0f*q2*q3) -
P[3][1]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) + SH_MAG[0]*(
P[20][2] +
P[0][2]*SH_MAG[2] +
P[1][2]*SH_MAG[1] +
P[2][2]*SH_MAG[0] -
P[17][2]*(SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6]) -
P[16][2]*(2.0f*q0*q3 - 2.0f*q1*q2) +
P[18][2]*(2.0
f*q0*q1 + 2.0
f*q2*q3) -
P[3][2]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) - (SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6])*(
P[20][17] +
P[0][17]*SH_MAG[2] +
P[1][17]*SH_MAG[1] +
P[2][17]*SH_MAG[0] -
P[17][17]*(SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6]) -
P[16][17]*(2.0f*q0*q3 - 2.0f*q1*q2) +
P[18][17]*(2.0
f*q0*q1 + 2.0
f*q2*q3) -
P[3][17]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) -
P[3][20]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2));
133 _mag_innov_var[2] = (
P[21][21] + R_MAG +
P[0][21]*SH_MAG[1] -
P[1][21]*SH_MAG[2] +
P[3][21]*SH_MAG[0] +
P[18][21]*(SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6]) + (2.0
f*q0*q2 + 2.0
f*q1*q3)*(
P[21][16] +
P[0][16]*SH_MAG[1] -
P[1][16]*SH_MAG[2] +
P[3][16]*SH_MAG[0] +
P[18][16]*(SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6]) +
P[16][16]*(2.0
f*q0*q2 + 2.0
f*q1*q3) -
P[17][16]*(2.0f*q0*q1 - 2.0f*q2*q3) +
P[2][16]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) - (2.0
f*q0*q1 - 2.0
f*q2*q3)*(
P[21][17] +
P[0][17]*SH_MAG[1] -
P[1][17]*SH_MAG[2] +
P[3][17]*SH_MAG[0] +
P[18][17]*(SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6]) +
P[16][17]*(2.0
f*q0*q2 + 2.0
f*q1*q3) -
P[17][17]*(2.0f*q0*q1 - 2.0f*q2*q3) +
P[2][17]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) + (SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)*(
P[21][2] +
P[0][2]*SH_MAG[1] -
P[1][2]*SH_MAG[2] +
P[3][2]*SH_MAG[0] +
P[18][2]*(SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6]) +
P[16][2]*(2.0
f*q0*q2 + 2.0
f*q1*q3) -
P[17][2]*(2.0f*q0*q1 - 2.0f*q2*q3) +
P[2][2]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) +
P[16][21]*(2.0
f*q0*q2 + 2.0
f*q1*q3) -
P[17][21]*(2.0f*q0*q1 - 2.0f*q2*q3) + SH_MAG[1]*(
P[21][0] +
P[0][0]*SH_MAG[1] -
P[1][0]*SH_MAG[2] +
P[3][0]*SH_MAG[0] +
P[18][0]*(SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6]) +
P[16][0]*(2.0f*q0*q2 + 2.0f*q1*q3) -
P[17][0]*(2.0
f*q0*q1 - 2.0
f*q2*q3) +
P[2][0]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) - SH_MAG[2]*(
P[21][1] +
P[0][1]*SH_MAG[1] -
P[1][1]*SH_MAG[2] +
P[3][1]*SH_MAG[0] +
P[18][1]*(SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6]) +
P[16][1]*(2.0
f*q0*q2 + 2.0
f*q1*q3) -
P[17][1]*(2.0f*q0*q1 - 2.0f*q2*q3) +
P[2][1]*(SH_MAG[7] + SH_MAG[8] - 2.0
f*magD*q2)) + SH_MAG[0]*(
P[21][3] +
P[0][3]*SH_MAG[1] -
P[1][3]*SH_MAG[2] +
P[3][3]*SH_MAG[0] +
P[18][3]*(SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6]) +
P[16][3]*(2.0f*q0*q2 + 2.0f*q1*q3) -
P[17][3]*(2.0
f*q0*q1 - 2.0
f*q2*q3) +
P[2][3]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) + (SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6])*(
P[21][18] +
P[0][18]*SH_MAG[1] -
P[1][18]*SH_MAG[2] +
P[3][18]*SH_MAG[0] +
P[18][18]*(SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6]) +
P[16][18]*(2.0f*q0*q2 + 2.0f*q1*q3) -
P[17][18]*(2.0
f*q0*q1 - 2.0
f*q2*q3) +
P[2][18]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2)) +
P[2][21]*(SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2));
154 for (uint8_t index = 0; index <= 2; index++) {
177 for (uint8_t index = 0; index <= 2; index++) {
182 memset(H_MAG, 0,
sizeof(H_MAG));
183 H_MAG[0] = SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2;
184 H_MAG[1] = SH_MAG[0];
185 H_MAG[2] = -SH_MAG[1];
186 H_MAG[3] = SH_MAG[2];
187 H_MAG[16] = SH_MAG[5] - SH_MAG[4] - SH_MAG[3] + SH_MAG[6];
188 H_MAG[17] = 2.0f*q0*q3 + 2.0f*q1*q2;
189 H_MAG[18] = 2.0f*q1*q3 - 2.0f*q0*q2;
195 SK_MX[1] = SH_MAG[3] + SH_MAG[4] - SH_MAG[5] - SH_MAG[6];
196 SK_MX[2] = SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2;
197 SK_MX[3] = 2.0f*q0*q2 - 2.0f*q1*q3;
198 SK_MX[4] = 2.0f*q0*q3 + 2.0f*q1*q2;
200 if (update_all_states) {
201 Kfusion[0] = SK_MX[0]*(
P[0][19] +
P[0][1]*SH_MAG[0] -
P[0][2]*SH_MAG[1] +
P[0][3]*SH_MAG[2] +
P[0][0]*SK_MX[2] -
P[0][16]*SK_MX[1] +
P[0][17]*SK_MX[4] -
P[0][18]*SK_MX[3]);
202 Kfusion[1] = SK_MX[0]*(
P[1][19] +
P[1][1]*SH_MAG[0] -
P[1][2]*SH_MAG[1] +
P[1][3]*SH_MAG[2] +
P[1][0]*SK_MX[2] -
P[1][16]*SK_MX[1] +
P[1][17]*SK_MX[4] -
P[1][18]*SK_MX[3]);
203 Kfusion[2] = SK_MX[0]*(
P[2][19] +
P[2][1]*SH_MAG[0] -
P[2][2]*SH_MAG[1] +
P[2][3]*SH_MAG[2] +
P[2][0]*SK_MX[2] -
P[2][16]*SK_MX[1] +
P[2][17]*SK_MX[4] -
P[2][18]*SK_MX[3]);
204 Kfusion[3] = SK_MX[0]*(
P[3][19] +
P[3][1]*SH_MAG[0] -
P[3][2]*SH_MAG[1] +
P[3][3]*SH_MAG[2] +
P[3][0]*SK_MX[2] -
P[3][16]*SK_MX[1] +
P[3][17]*SK_MX[4] -
P[3][18]*SK_MX[3]);
205 Kfusion[4] = SK_MX[0]*(
P[4][19] +
P[4][1]*SH_MAG[0] -
P[4][2]*SH_MAG[1] +
P[4][3]*SH_MAG[2] +
P[4][0]*SK_MX[2] -
P[4][16]*SK_MX[1] +
P[4][17]*SK_MX[4] -
P[4][18]*SK_MX[3]);
206 Kfusion[5] = SK_MX[0]*(
P[5][19] +
P[5][1]*SH_MAG[0] -
P[5][2]*SH_MAG[1] +
P[5][3]*SH_MAG[2] +
P[5][0]*SK_MX[2] -
P[5][16]*SK_MX[1] +
P[5][17]*SK_MX[4] -
P[5][18]*SK_MX[3]);
207 Kfusion[6] = SK_MX[0]*(
P[6][19] +
P[6][1]*SH_MAG[0] -
P[6][2]*SH_MAG[1] +
P[6][3]*SH_MAG[2] +
P[6][0]*SK_MX[2] -
P[6][16]*SK_MX[1] +
P[6][17]*SK_MX[4] -
P[6][18]*SK_MX[3]);
208 Kfusion[7] = SK_MX[0]*(
P[7][19] +
P[7][1]*SH_MAG[0] -
P[7][2]*SH_MAG[1] +
P[7][3]*SH_MAG[2] +
P[7][0]*SK_MX[2] -
P[7][16]*SK_MX[1] +
P[7][17]*SK_MX[4] -
P[7][18]*SK_MX[3]);
209 Kfusion[8] = SK_MX[0]*(
P[8][19] +
P[8][1]*SH_MAG[0] -
P[8][2]*SH_MAG[1] +
P[8][3]*SH_MAG[2] +
P[8][0]*SK_MX[2] -
P[8][16]*SK_MX[1] +
P[8][17]*SK_MX[4] -
P[8][18]*SK_MX[3]);
210 Kfusion[9] = SK_MX[0]*(
P[9][19] +
P[9][1]*SH_MAG[0] -
P[9][2]*SH_MAG[1] +
P[9][3]*SH_MAG[2] +
P[9][0]*SK_MX[2] -
P[9][16]*SK_MX[1] +
P[9][17]*SK_MX[4] -
P[9][18]*SK_MX[3]);
211 Kfusion[10] = SK_MX[0]*(
P[10][19] +
P[10][1]*SH_MAG[0] -
P[10][2]*SH_MAG[1] +
P[10][3]*SH_MAG[2] +
P[10][0]*SK_MX[2] -
P[10][16]*SK_MX[1] +
P[10][17]*SK_MX[4] -
P[10][18]*SK_MX[3]);
212 Kfusion[11] = SK_MX[0]*(
P[11][19] +
P[11][1]*SH_MAG[0] -
P[11][2]*SH_MAG[1] +
P[11][3]*SH_MAG[2] +
P[11][0]*SK_MX[2] -
P[11][16]*SK_MX[1] +
P[11][17]*SK_MX[4] -
P[11][18]*SK_MX[3]);
213 Kfusion[12] = SK_MX[0]*(
P[12][19] +
P[12][1]*SH_MAG[0] -
P[12][2]*SH_MAG[1] +
P[12][3]*SH_MAG[2] +
P[12][0]*SK_MX[2] -
P[12][16]*SK_MX[1] +
P[12][17]*SK_MX[4] -
P[12][18]*SK_MX[3]);
214 Kfusion[13] = SK_MX[0]*(
P[13][19] +
P[13][1]*SH_MAG[0] -
P[13][2]*SH_MAG[1] +
P[13][3]*SH_MAG[2] +
P[13][0]*SK_MX[2] -
P[13][16]*SK_MX[1] +
P[13][17]*SK_MX[4] -
P[13][18]*SK_MX[3]);
215 Kfusion[14] = SK_MX[0]*(
P[14][19] +
P[14][1]*SH_MAG[0] -
P[14][2]*SH_MAG[1] +
P[14][3]*SH_MAG[2] +
P[14][0]*SK_MX[2] -
P[14][16]*SK_MX[1] +
P[14][17]*SK_MX[4] -
P[14][18]*SK_MX[3]);
216 Kfusion[15] = SK_MX[0]*(
P[15][19] +
P[15][1]*SH_MAG[0] -
P[15][2]*SH_MAG[1] +
P[15][3]*SH_MAG[2] +
P[15][0]*SK_MX[2] -
P[15][16]*SK_MX[1] +
P[15][17]*SK_MX[4] -
P[15][18]*SK_MX[3]);
217 Kfusion[22] = SK_MX[0]*(
P[22][19] +
P[22][1]*SH_MAG[0] -
P[22][2]*SH_MAG[1] +
P[22][3]*SH_MAG[2] +
P[22][0]*SK_MX[2] -
P[22][16]*SK_MX[1] +
P[22][17]*SK_MX[4] -
P[22][18]*SK_MX[3]);
218 Kfusion[23] = SK_MX[0]*(
P[23][19] +
P[23][1]*SH_MAG[0] -
P[23][2]*SH_MAG[1] +
P[23][3]*SH_MAG[2] +
P[23][0]*SK_MX[2] -
P[23][16]*SK_MX[1] +
P[23][17]*SK_MX[4] -
P[23][18]*SK_MX[3]);
220 for (uint8_t i = 0; i < 16; i++) {
228 Kfusion[16] = SK_MX[0]*(
P[16][19] +
P[16][1]*SH_MAG[0] -
P[16][2]*SH_MAG[1] +
P[16][3]*SH_MAG[2] +
P[16][0]*SK_MX[2] -
P[16][16]*SK_MX[1] +
P[16][17]*SK_MX[4] -
P[16][18]*SK_MX[3]);
229 Kfusion[17] = SK_MX[0]*(
P[17][19] +
P[17][1]*SH_MAG[0] -
P[17][2]*SH_MAG[1] +
P[17][3]*SH_MAG[2] +
P[17][0]*SK_MX[2] -
P[17][16]*SK_MX[1] +
P[17][17]*SK_MX[4] -
P[17][18]*SK_MX[3]);
230 Kfusion[18] = SK_MX[0]*(
P[18][19] +
P[18][1]*SH_MAG[0] -
P[18][2]*SH_MAG[1] +
P[18][3]*SH_MAG[2] +
P[18][0]*SK_MX[2] -
P[18][16]*SK_MX[1] +
P[18][17]*SK_MX[4] -
P[18][18]*SK_MX[3]);
231 Kfusion[19] = SK_MX[0]*(
P[19][19] +
P[19][1]*SH_MAG[0] -
P[19][2]*SH_MAG[1] +
P[19][3]*SH_MAG[2] +
P[19][0]*SK_MX[2] -
P[19][16]*SK_MX[1] +
P[19][17]*SK_MX[4] -
P[19][18]*SK_MX[3]);
232 Kfusion[20] = SK_MX[0]*(
P[20][19] +
P[20][1]*SH_MAG[0] -
P[20][2]*SH_MAG[1] +
P[20][3]*SH_MAG[2] +
P[20][0]*SK_MX[2] -
P[20][16]*SK_MX[1] +
P[20][17]*SK_MX[4] -
P[20][18]*SK_MX[3]);
233 Kfusion[21] = SK_MX[0]*(
P[21][19] +
P[21][1]*SH_MAG[0] -
P[21][2]*SH_MAG[1] +
P[21][3]*SH_MAG[2] +
P[21][0]*SK_MX[2] -
P[21][16]*SK_MX[1] +
P[21][17]*SK_MX[4] -
P[21][18]*SK_MX[3]);
235 }
else if (index == 1) {
237 memset(H_MAG, 0,
sizeof(H_MAG));
238 H_MAG[0] = SH_MAG[2];
239 H_MAG[1] = SH_MAG[1];
240 H_MAG[2] = SH_MAG[0];
241 H_MAG[3] = 2.0f*magD*q2 - SH_MAG[8] - SH_MAG[7];
242 H_MAG[16] = 2.0f*q1*q2 - 2.0f*q0*q3;
243 H_MAG[17] = SH_MAG[4] - SH_MAG[3] - SH_MAG[5] + SH_MAG[6];
244 H_MAG[18] = 2.0f*q0*q1 + 2.0f*q2*q3;
250 SK_MY[1] = SH_MAG[3] - SH_MAG[4] + SH_MAG[5] - SH_MAG[6];
251 SK_MY[2] = SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2;
252 SK_MY[3] = 2.0f*q0*q3 - 2.0f*q1*q2;
253 SK_MY[4] = 2.0f*q0*q1 + 2.0f*q2*q3;
255 if (update_all_states) {
256 Kfusion[0] = SK_MY[0]*(
P[0][20] +
P[0][0]*SH_MAG[2] +
P[0][1]*SH_MAG[1] +
P[0][2]*SH_MAG[0] -
P[0][3]*SK_MY[2] -
P[0][17]*SK_MY[1] -
P[0][16]*SK_MY[3] +
P[0][18]*SK_MY[4]);
257 Kfusion[1] = SK_MY[0]*(
P[1][20] +
P[1][0]*SH_MAG[2] +
P[1][1]*SH_MAG[1] +
P[1][2]*SH_MAG[0] -
P[1][3]*SK_MY[2] -
P[1][17]*SK_MY[1] -
P[1][16]*SK_MY[3] +
P[1][18]*SK_MY[4]);
258 Kfusion[2] = SK_MY[0]*(
P[2][20] +
P[2][0]*SH_MAG[2] +
P[2][1]*SH_MAG[1] +
P[2][2]*SH_MAG[0] -
P[2][3]*SK_MY[2] -
P[2][17]*SK_MY[1] -
P[2][16]*SK_MY[3] +
P[2][18]*SK_MY[4]);
259 Kfusion[3] = SK_MY[0]*(
P[3][20] +
P[3][0]*SH_MAG[2] +
P[3][1]*SH_MAG[1] +
P[3][2]*SH_MAG[0] -
P[3][3]*SK_MY[2] -
P[3][17]*SK_MY[1] -
P[3][16]*SK_MY[3] +
P[3][18]*SK_MY[4]);
260 Kfusion[4] = SK_MY[0]*(
P[4][20] +
P[4][0]*SH_MAG[2] +
P[4][1]*SH_MAG[1] +
P[4][2]*SH_MAG[0] -
P[4][3]*SK_MY[2] -
P[4][17]*SK_MY[1] -
P[4][16]*SK_MY[3] +
P[4][18]*SK_MY[4]);
261 Kfusion[5] = SK_MY[0]*(
P[5][20] +
P[5][0]*SH_MAG[2] +
P[5][1]*SH_MAG[1] +
P[5][2]*SH_MAG[0] -
P[5][3]*SK_MY[2] -
P[5][17]*SK_MY[1] -
P[5][16]*SK_MY[3] +
P[5][18]*SK_MY[4]);
262 Kfusion[6] = SK_MY[0]*(
P[6][20] +
P[6][0]*SH_MAG[2] +
P[6][1]*SH_MAG[1] +
P[6][2]*SH_MAG[0] -
P[6][3]*SK_MY[2] -
P[6][17]*SK_MY[1] -
P[6][16]*SK_MY[3] +
P[6][18]*SK_MY[4]);
263 Kfusion[7] = SK_MY[0]*(
P[7][20] +
P[7][0]*SH_MAG[2] +
P[7][1]*SH_MAG[1] +
P[7][2]*SH_MAG[0] -
P[7][3]*SK_MY[2] -
P[7][17]*SK_MY[1] -
P[7][16]*SK_MY[3] +
P[7][18]*SK_MY[4]);
264 Kfusion[8] = SK_MY[0]*(
P[8][20] +
P[8][0]*SH_MAG[2] +
P[8][1]*SH_MAG[1] +
P[8][2]*SH_MAG[0] -
P[8][3]*SK_MY[2] -
P[8][17]*SK_MY[1] -
P[8][16]*SK_MY[3] +
P[8][18]*SK_MY[4]);
265 Kfusion[9] = SK_MY[0]*(
P[9][20] +
P[9][0]*SH_MAG[2] +
P[9][1]*SH_MAG[1] +
P[9][2]*SH_MAG[0] -
P[9][3]*SK_MY[2] -
P[9][17]*SK_MY[1] -
P[9][16]*SK_MY[3] +
P[9][18]*SK_MY[4]);
266 Kfusion[10] = SK_MY[0]*(
P[10][20] +
P[10][0]*SH_MAG[2] +
P[10][1]*SH_MAG[1] +
P[10][2]*SH_MAG[0] -
P[10][3]*SK_MY[2] -
P[10][17]*SK_MY[1] -
P[10][16]*SK_MY[3] +
P[10][18]*SK_MY[4]);
267 Kfusion[11] = SK_MY[0]*(
P[11][20] +
P[11][0]*SH_MAG[2] +
P[11][1]*SH_MAG[1] +
P[11][2]*SH_MAG[0] -
P[11][3]*SK_MY[2] -
P[11][17]*SK_MY[1] -
P[11][16]*SK_MY[3] +
P[11][18]*SK_MY[4]);
268 Kfusion[12] = SK_MY[0]*(
P[12][20] +
P[12][0]*SH_MAG[2] +
P[12][1]*SH_MAG[1] +
P[12][2]*SH_MAG[0] -
P[12][3]*SK_MY[2] -
P[12][17]*SK_MY[1] -
P[12][16]*SK_MY[3] +
P[12][18]*SK_MY[4]);
269 Kfusion[13] = SK_MY[0]*(
P[13][20] +
P[13][0]*SH_MAG[2] +
P[13][1]*SH_MAG[1] +
P[13][2]*SH_MAG[0] -
P[13][3]*SK_MY[2] -
P[13][17]*SK_MY[1] -
P[13][16]*SK_MY[3] +
P[13][18]*SK_MY[4]);
270 Kfusion[14] = SK_MY[0]*(
P[14][20] +
P[14][0]*SH_MAG[2] +
P[14][1]*SH_MAG[1] +
P[14][2]*SH_MAG[0] -
P[14][3]*SK_MY[2] -
P[14][17]*SK_MY[1] -
P[14][16]*SK_MY[3] +
P[14][18]*SK_MY[4]);
271 Kfusion[15] = SK_MY[0]*(
P[15][20] +
P[15][0]*SH_MAG[2] +
P[15][1]*SH_MAG[1] +
P[15][2]*SH_MAG[0] -
P[15][3]*SK_MY[2] -
P[15][17]*SK_MY[1] -
P[15][16]*SK_MY[3] +
P[15][18]*SK_MY[4]);
272 Kfusion[22] = SK_MY[0]*(
P[22][20] +
P[22][0]*SH_MAG[2] +
P[22][1]*SH_MAG[1] +
P[22][2]*SH_MAG[0] -
P[22][3]*SK_MY[2] -
P[22][17]*SK_MY[1] -
P[22][16]*SK_MY[3] +
P[22][18]*SK_MY[4]);
273 Kfusion[23] = SK_MY[0]*(
P[23][20] +
P[23][0]*SH_MAG[2] +
P[23][1]*SH_MAG[1] +
P[23][2]*SH_MAG[0] -
P[23][3]*SK_MY[2] -
P[23][17]*SK_MY[1] -
P[23][16]*SK_MY[3] +
P[23][18]*SK_MY[4]);
275 for (uint8_t i = 0; i < 16; i++) {
283 Kfusion[16] = SK_MY[0]*(
P[16][20] +
P[16][0]*SH_MAG[2] +
P[16][1]*SH_MAG[1] +
P[16][2]*SH_MAG[0] -
P[16][3]*SK_MY[2] -
P[16][17]*SK_MY[1] -
P[16][16]*SK_MY[3] +
P[16][18]*SK_MY[4]);
284 Kfusion[17] = SK_MY[0]*(
P[17][20] +
P[17][0]*SH_MAG[2] +
P[17][1]*SH_MAG[1] +
P[17][2]*SH_MAG[0] -
P[17][3]*SK_MY[2] -
P[17][17]*SK_MY[1] -
P[17][16]*SK_MY[3] +
P[17][18]*SK_MY[4]);
285 Kfusion[18] = SK_MY[0]*(
P[18][20] +
P[18][0]*SH_MAG[2] +
P[18][1]*SH_MAG[1] +
P[18][2]*SH_MAG[0] -
P[18][3]*SK_MY[2] -
P[18][17]*SK_MY[1] -
P[18][16]*SK_MY[3] +
P[18][18]*SK_MY[4]);
286 Kfusion[19] = SK_MY[0]*(
P[19][20] +
P[19][0]*SH_MAG[2] +
P[19][1]*SH_MAG[1] +
P[19][2]*SH_MAG[0] -
P[19][3]*SK_MY[2] -
P[19][17]*SK_MY[1] -
P[19][16]*SK_MY[3] +
P[19][18]*SK_MY[4]);
287 Kfusion[20] = SK_MY[0]*(
P[20][20] +
P[20][0]*SH_MAG[2] +
P[20][1]*SH_MAG[1] +
P[20][2]*SH_MAG[0] -
P[20][3]*SK_MY[2] -
P[20][17]*SK_MY[1] -
P[20][16]*SK_MY[3] +
P[20][18]*SK_MY[4]);
288 Kfusion[21] = SK_MY[0]*(
P[21][20] +
P[21][0]*SH_MAG[2] +
P[21][1]*SH_MAG[1] +
P[21][2]*SH_MAG[0] -
P[21][3]*SK_MY[2] -
P[21][17]*SK_MY[1] -
P[21][16]*SK_MY[3] +
P[21][18]*SK_MY[4]);
290 }
else if (index == 2) {
298 memset(H_MAG, 0,
sizeof(H_MAG));
299 H_MAG[0] = SH_MAG[1];
300 H_MAG[1] = -SH_MAG[2];
301 H_MAG[2] = SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2;
302 H_MAG[3] = SH_MAG[0];
303 H_MAG[16] = 2.0f*q0*q2 + 2.0f*q1*q3;
304 H_MAG[17] = 2.0f*q2*q3 - 2.0f*q0*q1;
305 H_MAG[18] = SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6];
311 SK_MZ[1] = SH_MAG[3] - SH_MAG[4] - SH_MAG[5] + SH_MAG[6];
312 SK_MZ[2] = SH_MAG[7] + SH_MAG[8] - 2.0f*magD*q2;
313 SK_MZ[3] = 2.0f*q0*q1 - 2.0f*q2*q3;
314 SK_MZ[4] = 2.0f*q0*q2 + 2.0f*q1*q3;
316 if (update_all_states) {
317 Kfusion[0] = SK_MZ[0]*(
P[0][21] +
P[0][0]*SH_MAG[1] -
P[0][1]*SH_MAG[2] +
P[0][3]*SH_MAG[0] +
P[0][2]*SK_MZ[2] +
P[0][18]*SK_MZ[1] +
P[0][16]*SK_MZ[4] -
P[0][17]*SK_MZ[3]);
318 Kfusion[1] = SK_MZ[0]*(
P[1][21] +
P[1][0]*SH_MAG[1] -
P[1][1]*SH_MAG[2] +
P[1][3]*SH_MAG[0] +
P[1][2]*SK_MZ[2] +
P[1][18]*SK_MZ[1] +
P[1][16]*SK_MZ[4] -
P[1][17]*SK_MZ[3]);
319 Kfusion[2] = SK_MZ[0]*(
P[2][21] +
P[2][0]*SH_MAG[1] -
P[2][1]*SH_MAG[2] +
P[2][3]*SH_MAG[0] +
P[2][2]*SK_MZ[2] +
P[2][18]*SK_MZ[1] +
P[2][16]*SK_MZ[4] -
P[2][17]*SK_MZ[3]);
320 Kfusion[3] = SK_MZ[0]*(
P[3][21] +
P[3][0]*SH_MAG[1] -
P[3][1]*SH_MAG[2] +
P[3][3]*SH_MAG[0] +
P[3][2]*SK_MZ[2] +
P[3][18]*SK_MZ[1] +
P[3][16]*SK_MZ[4] -
P[3][17]*SK_MZ[3]);
321 Kfusion[4] = SK_MZ[0]*(
P[4][21] +
P[4][0]*SH_MAG[1] -
P[4][1]*SH_MAG[2] +
P[4][3]*SH_MAG[0] +
P[4][2]*SK_MZ[2] +
P[4][18]*SK_MZ[1] +
P[4][16]*SK_MZ[4] -
P[4][17]*SK_MZ[3]);
322 Kfusion[5] = SK_MZ[0]*(
P[5][21] +
P[5][0]*SH_MAG[1] -
P[5][1]*SH_MAG[2] +
P[5][3]*SH_MAG[0] +
P[5][2]*SK_MZ[2] +
P[5][18]*SK_MZ[1] +
P[5][16]*SK_MZ[4] -
P[5][17]*SK_MZ[3]);
323 Kfusion[6] = SK_MZ[0]*(
P[6][21] +
P[6][0]*SH_MAG[1] -
P[6][1]*SH_MAG[2] +
P[6][3]*SH_MAG[0] +
P[6][2]*SK_MZ[2] +
P[6][18]*SK_MZ[1] +
P[6][16]*SK_MZ[4] -
P[6][17]*SK_MZ[3]);
324 Kfusion[7] = SK_MZ[0]*(
P[7][21] +
P[7][0]*SH_MAG[1] -
P[7][1]*SH_MAG[2] +
P[7][3]*SH_MAG[0] +
P[7][2]*SK_MZ[2] +
P[7][18]*SK_MZ[1] +
P[7][16]*SK_MZ[4] -
P[7][17]*SK_MZ[3]);
325 Kfusion[8] = SK_MZ[0]*(
P[8][21] +
P[8][0]*SH_MAG[1] -
P[8][1]*SH_MAG[2] +
P[8][3]*SH_MAG[0] +
P[8][2]*SK_MZ[2] +
P[8][18]*SK_MZ[1] +
P[8][16]*SK_MZ[4] -
P[8][17]*SK_MZ[3]);
326 Kfusion[9] = SK_MZ[0]*(
P[9][21] +
P[9][0]*SH_MAG[1] -
P[9][1]*SH_MAG[2] +
P[9][3]*SH_MAG[0] +
P[9][2]*SK_MZ[2] +
P[9][18]*SK_MZ[1] +
P[9][16]*SK_MZ[4] -
P[9][17]*SK_MZ[3]);
327 Kfusion[10] = SK_MZ[0]*(
P[10][21] +
P[10][0]*SH_MAG[1] -
P[10][1]*SH_MAG[2] +
P[10][3]*SH_MAG[0] +
P[10][2]*SK_MZ[2] +
P[10][18]*SK_MZ[1] +
P[10][16]*SK_MZ[4] -
P[10][17]*SK_MZ[3]);
328 Kfusion[11] = SK_MZ[0]*(
P[11][21] +
P[11][0]*SH_MAG[1] -
P[11][1]*SH_MAG[2] +
P[11][3]*SH_MAG[0] +
P[11][2]*SK_MZ[2] +
P[11][18]*SK_MZ[1] +
P[11][16]*SK_MZ[4] -
P[11][17]*SK_MZ[3]);
329 Kfusion[12] = SK_MZ[0]*(
P[12][21] +
P[12][0]*SH_MAG[1] -
P[12][1]*SH_MAG[2] +
P[12][3]*SH_MAG[0] +
P[12][2]*SK_MZ[2] +
P[12][18]*SK_MZ[1] +
P[12][16]*SK_MZ[4] -
P[12][17]*SK_MZ[3]);
330 Kfusion[13] = SK_MZ[0]*(
P[13][21] +
P[13][0]*SH_MAG[1] -
P[13][1]*SH_MAG[2] +
P[13][3]*SH_MAG[0] +
P[13][2]*SK_MZ[2] +
P[13][18]*SK_MZ[1] +
P[13][16]*SK_MZ[4] -
P[13][17]*SK_MZ[3]);
331 Kfusion[14] = SK_MZ[0]*(
P[14][21] +
P[14][0]*SH_MAG[1] -
P[14][1]*SH_MAG[2] +
P[14][3]*SH_MAG[0] +
P[14][2]*SK_MZ[2] +
P[14][18]*SK_MZ[1] +
P[14][16]*SK_MZ[4] -
P[14][17]*SK_MZ[3]);
332 Kfusion[15] = SK_MZ[0]*(
P[15][21] +
P[15][0]*SH_MAG[1] -
P[15][1]*SH_MAG[2] +
P[15][3]*SH_MAG[0] +
P[15][2]*SK_MZ[2] +
P[15][18]*SK_MZ[1] +
P[15][16]*SK_MZ[4] -
P[15][17]*SK_MZ[3]);
333 Kfusion[22] = SK_MZ[0]*(
P[22][21] +
P[22][0]*SH_MAG[1] -
P[22][1]*SH_MAG[2] +
P[22][3]*SH_MAG[0] +
P[22][2]*SK_MZ[2] +
P[22][18]*SK_MZ[1] +
P[22][16]*SK_MZ[4] -
P[22][17]*SK_MZ[3]);
334 Kfusion[23] = SK_MZ[0]*(
P[23][21] +
P[23][0]*SH_MAG[1] -
P[23][1]*SH_MAG[2] +
P[23][3]*SH_MAG[0] +
P[23][2]*SK_MZ[2] +
P[23][18]*SK_MZ[1] +
P[23][16]*SK_MZ[4] -
P[23][17]*SK_MZ[3]);
336 for (uint8_t i = 0; i < 16; i++) {
344 Kfusion[16] = SK_MZ[0]*(
P[16][21] +
P[16][0]*SH_MAG[1] -
P[16][1]*SH_MAG[2] +
P[16][3]*SH_MAG[0] +
P[16][2]*SK_MZ[2] +
P[16][18]*SK_MZ[1] +
P[16][16]*SK_MZ[4] -
P[16][17]*SK_MZ[3]);
345 Kfusion[17] = SK_MZ[0]*(
P[17][21] +
P[17][0]*SH_MAG[1] -
P[17][1]*SH_MAG[2] +
P[17][3]*SH_MAG[0] +
P[17][2]*SK_MZ[2] +
P[17][18]*SK_MZ[1] +
P[17][16]*SK_MZ[4] -
P[17][17]*SK_MZ[3]);
346 Kfusion[18] = SK_MZ[0]*(
P[18][21] +
P[18][0]*SH_MAG[1] -
P[18][1]*SH_MAG[2] +
P[18][3]*SH_MAG[0] +
P[18][2]*SK_MZ[2] +
P[18][18]*SK_MZ[1] +
P[18][16]*SK_MZ[4] -
P[18][17]*SK_MZ[3]);
347 Kfusion[19] = SK_MZ[0]*(
P[19][21] +
P[19][0]*SH_MAG[1] -
P[19][1]*SH_MAG[2] +
P[19][3]*SH_MAG[0] +
P[19][2]*SK_MZ[2] +
P[19][18]*SK_MZ[1] +
P[19][16]*SK_MZ[4] -
P[19][17]*SK_MZ[3]);
348 Kfusion[20] = SK_MZ[0]*(
P[20][21] +
P[20][0]*SH_MAG[1] -
P[20][1]*SH_MAG[2] +
P[20][3]*SH_MAG[0] +
P[20][2]*SK_MZ[2] +
P[20][18]*SK_MZ[1] +
P[20][16]*SK_MZ[4] -
P[20][17]*SK_MZ[3]);
349 Kfusion[21] = SK_MZ[0]*(
P[21][21] +
P[21][0]*SH_MAG[1] -
P[21][1]*SH_MAG[2] +
P[21][3]*SH_MAG[0] +
P[21][2]*SK_MZ[2] +
P[21][18]*SK_MZ[1] +
P[21][16]*SK_MZ[4] -
P[21][17]*SK_MZ[3]);
363 KH[0] = Kfusion[row] * H_MAG[0];
364 KH[1] = Kfusion[row] * H_MAG[1];
365 KH[2] = Kfusion[row] * H_MAG[2];
366 KH[3] = Kfusion[row] * H_MAG[3];
367 KH[4] = Kfusion[row] * H_MAG[16];
368 KH[5] = Kfusion[row] * H_MAG[17];
369 KH[6] = Kfusion[row] * H_MAG[18];
370 KH[7] = Kfusion[row] * H_MAG[19];
371 KH[8] = Kfusion[row] * H_MAG[20];
372 KH[9] = Kfusion[row] * H_MAG[21];
374 for (
unsigned column = 0; column <
_k_num_states; column++) {
375 float tmp = KH[0] *
P[0][column];
376 tmp += KH[1] * P[1][column];
377 tmp += KH[2] * P[2][column];
378 tmp += KH[3] * P[3][column];
379 tmp += KH[4] * P[16][column];
380 tmp += KH[5] * P[17][column];
381 tmp += KH[6] * P[18][column];
382 tmp += KH[7] * P[19][column];
383 tmp += KH[8] * P[20][column];
384 tmp += KH[9] * P[21][column];
385 KHP[row][column] = tmp;
396 if (
P[i][i] < KHP[i][i]) {
408 }
else if (index == 1) {
411 }
else if (index == 2) {
421 for (
unsigned column = 0; column <
_k_num_states; column++) {
422 P[row][column] =
P[row][column] - KHP[row][column];
462 float t7 = t3+t4-t5-
t6;
470 float t12 = t8*t11*4.0f;
471 float t13 = t12+1.0f;
473 if (fabsf(t13) > 1e-6
f) {
479 H_YAW[0] = t8*t14*(q3*t3-q3*t4+q3*t5+q3*t6+q0*q1*q2*2.0f)*-2.0
f;
480 H_YAW[1] = t8*t14*(-q2*t3+q2*t4+q2*t5+q2*t6+q0*q1*q3*2.0f)*-2.0
f;
481 H_YAW[2] = t8*t14*(q1*t3+q1*t4+q1*t5-q1*t6+q0*q2*q3*2.0f)*2.0
f;
482 H_YAW[3] = t8*t14*(q0*t3+q0*t4-q0*t5+q0*t6+q1*q2*q3*2.0f)*2.0
f;
486 predicted_hdg = euler321(2);
492 Dcmf R_to_earth(euler321);
504 measured_hdg = -atan2f(mag_earth_pred(1), mag_earth_pred(0)) +
getMagDeclination();
511 measured_hdg = atan2f(Tbn_1_0,Tbn_0_0);
516 measured_hdg = predicted_hdg;
533 float t7 = t3-t4+t5-
t6;
541 float t12 = t8*t11*4.0f;
542 float t13 = t12+1.0f;
545 if (fabsf(t13) > 1e-6
f) {
551 H_YAW[0] = t8*t14*(q3*t3+q3*t4-q3*t5+q3*t6-q0*q1*q2*2.0f)*-2.0
f;
552 H_YAW[1] = t8*t14*(q2*t3+q2*t4+q2*t5-q2*t6-q0*q1*q3*2.0f)*-2.0
f;
553 H_YAW[2] = t8*t14*(-q1*t3+q1*t4+q1*t5+q1*t6-q0*q2*q3*2.0f)*2.0
f;
554 H_YAW[3] = t8*t14*(q0*t3-q0*t4+q0*t5+q0*t6-q1*q2*q3*2.0f)*2.0
f;
578 float sy = sinf(yaw);
579 float cy = cosf(yaw);
580 float sp = sinf(pitch);
581 float cp = cosf(pitch);
582 float sr = sinf(roll);
583 float cr = cosf(roll);
584 R_to_earth(0,0) = cy*cp-sy*sp*sr;
585 R_to_earth(0,1) = -sy*cr;
586 R_to_earth(0,2) = cy*sp+sy*cp*sr;
587 R_to_earth(1,0) = sy*cp+cy*sp*sr;
588 R_to_earth(1,1) = cy*cr;
589 R_to_earth(1,2) = sy*sp-cy*cp*sr;
590 R_to_earth(2,0) = -sp*cr;
591 R_to_earth(2,1) = sr;
592 R_to_earth(2,2) = cp*cr;
603 measured_hdg = -atan2f(mag_earth_pred(1), mag_earth_pred(0)) +
getMagDeclination();
610 measured_hdg = atan2f(Tbn_0_1_neg,Tbn_1_1);
615 measured_hdg = predicted_hdg;
639 measured_hdg =
wrap_pi(measured_hdg);
675 for (
unsigned row = 0; row <= 3; row++) {
678 for (uint8_t col = 0; col <= 3; col++) {
679 PH[row] +=
P[row][col] * H_YAW[col];
685 float heading_innov_var_inv;
707 for (uint8_t row = 0; row <= 15; row++) {
710 for (uint8_t col = 0; col <= 3; col++) {
711 Kfusion[row] +=
P[row][col] * H_YAW[col];
714 Kfusion[row] *= heading_innov_var_inv;
718 for (uint8_t row = 22; row <= 23; row++) {
721 for (uint8_t col = 0; col <= 3; col++) {
722 Kfusion[row] +=
P[row][col] * H_YAW[col];
725 Kfusion[row] *= heading_innov_var_inv;
763 KH[0] = Kfusion[row] * H_YAW[0];
764 KH[1] = Kfusion[row] * H_YAW[1];
765 KH[2] = Kfusion[row] * H_YAW[2];
766 KH[3] = Kfusion[row] * H_YAW[3];
768 for (
unsigned column = 0; column <
_k_num_states; column++) {
769 float tmp = KH[0] *
P[0][column];
770 tmp += KH[1] * P[1][column];
771 tmp += KH[2] * P[2][column];
772 tmp += KH[3] * P[3][column];
773 KHP[row][column] = tmp;
783 if (
P[i][i] < KHP[i][i]) {
801 for (
unsigned column = 0; column <
_k_num_states; column++) {
802 P[row][column] =
P[row][column] - KHP[row][column];
822 float h_field_min = 0.001f;
825 float R_DECL =
sq(decl_sigma);
828 float t2 = magE*magE;
829 float t3 = magN*magN;
832 if (t4 < h_field_min*h_field_min) {
835 float t5 =
P[16][16]*
t2;
836 float t6 =
P[17][17]*
t3;
838 float t8 = R_DECL*
t7;
840 float t10 = R_DECL*
t9;
841 float t11 = R_DECL*t2*t3*2.0f;
842 float t14 =
P[16][17]*magE*magN;
843 float t15 =
P[17][16]*magE*magN;
844 float t12 = t5+t6+t8+t10+t11-t14-
t15;
846 if (fabsf(t12) > 1e-6
f) {
851 float t18 = magE*magE;
852 float t19 = magN*magN;
855 if (fabsf(t20) > 1e-6
f) {
863 float H_DECL[24] = {};
864 H_DECL[16] = -magE*
t21;
865 H_DECL[17] = magN*
t21;
869 Kfusion[0] = -t4*t13*(
P[0][16]*magE-
P[0][17]*magN);
870 Kfusion[1] = -t4*t13*(
P[1][16]*magE-
P[1][17]*magN);
871 Kfusion[2] = -t4*t13*(
P[2][16]*magE-
P[2][17]*magN);
872 Kfusion[3] = -t4*t13*(
P[3][16]*magE-
P[3][17]*magN);
873 Kfusion[4] = -t4*t13*(
P[4][16]*magE-
P[4][17]*magN);
874 Kfusion[5] = -t4*t13*(
P[5][16]*magE-
P[5][17]*magN);
875 Kfusion[6] = -t4*t13*(
P[6][16]*magE-
P[6][17]*magN);
876 Kfusion[7] = -t4*t13*(
P[7][16]*magE-
P[7][17]*magN);
877 Kfusion[8] = -t4*t13*(
P[8][16]*magE-
P[8][17]*magN);
878 Kfusion[9] = -t4*t13*(
P[9][16]*magE-
P[9][17]*magN);
879 Kfusion[10] = -t4*t13*(
P[10][16]*magE-
P[10][17]*magN);
880 Kfusion[11] = -t4*t13*(
P[11][16]*magE-
P[11][17]*magN);
881 Kfusion[12] = -t4*t13*(
P[12][16]*magE-
P[12][17]*magN);
882 Kfusion[13] = -t4*t13*(
P[13][16]*magE-
P[13][17]*magN);
883 Kfusion[14] = -t4*t13*(
P[14][16]*magE-
P[14][17]*magN);
884 Kfusion[15] = -t4*t13*(
P[15][16]*magE-
P[15][17]*magN);
885 Kfusion[16] = -t4*t13*(
P[16][16]*magE-
P[16][17]*magN);
886 Kfusion[17] = -t4*t13*(
P[17][16]*magE-
P[17][17]*magN);
887 Kfusion[18] = -t4*t13*(
P[18][16]*magE-
P[18][17]*magN);
888 Kfusion[19] = -t4*t13*(
P[19][16]*magE-
P[19][17]*magN);
889 Kfusion[20] = -t4*t13*(
P[20][16]*magE-
P[20][17]*magN);
890 Kfusion[21] = -t4*t13*(
P[21][16]*magE-
P[21][17]*magN);
891 Kfusion[22] = -t4*t13*(
P[22][16]*magE-
P[22][17]*magN);
892 Kfusion[23] = -t4*t13*(
P[23][16]*magE-
P[23][17]*magN);
906 KH[0] = Kfusion[row] * H_DECL[16];
907 KH[1] = Kfusion[row] * H_DECL[17];
909 for (
unsigned column = 0; column <
_k_num_states; column++) {
910 float tmp = KH[0] *
P[16][column];
911 tmp += KH[1] * P[17][column];
912 KHP[row][column] = tmp;
921 if (
P[i][i] < KHP[i][i]) {
939 for (
unsigned column = 0; column <
_k_num_states; column++) {
940 P[row][column] =
P[row][column] - KHP[row][column];
948 fuse(Kfusion, innovation);
959 float decl_reference;
960 float h_field_min = 0.001f;
978 if (h_field < h_field_min) {
979 if (h_field > 0.001
f * h_field_min) {
980 float h_scaler = h_field_min / h_field;
986 _state.
mag_I(0) = 2.0f * h_field_min * cosf(mag_declination);
987 _state.
mag_I(1) = 2.0f * h_field_min * sinf(mag_declination);
989 h_field = h_field_min;
993 const float decl_tolerance = 0.5f;
994 const float decl_max = decl_reference + decl_tolerance;
995 const float decl_min = decl_reference - decl_tolerance;
997 if (decl_estimate > decl_max) {
1000 }
else if (decl_estimate < decl_min) {
1010 float mag_z_abs = sqrtf(
math::max(
sq(mag_earth_predicted.length()) -
sq(mag_meas(0)) -
sq(mag_meas(1)), 0.0
f));
1015 return mag_z_body_pred < 0 ? -mag_z_abs : mag_z_abs;
Matrix3f quat_to_invrotmat(const Quatf &quat)
void fuseDeclination(float decl_sigma)
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
struct estimator::filter_control_status_u::@60 flags
Adapter / shim layer for system calls needed by ECL.
stateSample _state
state struct of the ekf running at the delayed time horizon
#define ECL_ERR_TIMESTAMPED
float mag_heading_noise
measurement noise used for simple heading fusion (rad)
bool bad_mag_x
0 - true if the fusion of the magnetometer X-axis has encountered a numerical error ...
bool bad_mag_y
1 - true if the fusion of the magnetometer Y-axis has encountered a numerical error ...
float _last_static_yaw
last yaw angle recorded when on ground motion checks were passing (rad)
bool bad_mag_decl
4 - true if the fusion of the magnetic declination has encountered a numerical error ...
Quatf quat
quaternion defining rotation from body to earth frame
float _heading_innov_var
heading measurement innovation variance (rad**2)
uint32_t mag_hdg
4 - true if a simple magnetic yaw heading is being fused
void initialiseCovariance()
Vector3f mag_I
NED earth magnetic field in gauss.
float _mag_inclination_gps
struct estimator::fault_status_u::@57 flags
float _mag_innov[3]
earth magnetic field innovations (Gauss)
float P[_k_num_states][_k_num_states]
state covariance matrix
void zeroCols(float(&cov_mat)[_k_num_states][_k_num_states], uint8_t first, uint8_t last)
bool _NED_origin_initialised
float _heading_innov
heading measurement innovation (rad)
#define MASK_USE_GEO_DECL
set to true to use the declination from the geo library when the GPS position becomes available...
void resetMagRelatedCovariances()
float getMagDeclination()
uint32_t synthetic_mag_z
25 - true when we are using a synthesized measurement for the magnetometer Z component ...
void fuse(float *K, float innovation)
Dcmf _R_to_earth
transformation matrix from body frame to earth frame from last EKF prediction
bool bad_mag_z
2 - true if the fusion of the magnetometer Z-axis has encountered a numerical error ...
float calculate_synthetic_mag_z_measurement(Vector3f mag_meas, Vector3f mag_earth_predicted)
int32_t mag_declination_source
bitmask used to control the handling of declination data
bool _mag_use_inhibit_prev
true when magnetometer use was being inhibited the previous frame
float mag_noise
measurement noise used for 3-axis magnetoemeter fusion (Gauss)
bool _flt_mag_align_converging
true when the in-flight mag field post alignment convergence is being performd
constexpr T radians(T degrees)
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
bool bad_hdg
3 - true if the fusion of the heading angle has encountered a numerical error
filter_control_status_u _control_status
float _mag_declination_gps
static constexpr float sq(float var)
float _mag_innov_var[3]
earth magnetic field innovation variance (Gauss**2)
uint32_t ev_yaw
13 - true when yaw data from external vision measurements is being fused
fault_status_u _fault_status
void fixCovarianceErrors()
bool reject_yaw
6 - true if the yaw observation has been rejected
Type wrap_pi(Type x)
Wrap value in range [-π, π)
Quatf quat_nominal
quaternion defining the rotation from body to earth frame
float mag_innov_gate
magnetometer fusion innovation consistency gate size (STD)
bool _mag_use_inhibit
true when magnetometer use is being inhibited
innovation_fault_status_u _innov_check_fail_status
Vector3< float > Vector3f
extVisionSample _ev_sample_delayed
Vector3f mag_B
magnetometer bias estimate in body frame in gauss
constexpr _Tp max(_Tp a, _Tp b)
uint32_t mag_3D
5 - true if 3-axis magnetometer measurement are being fused
void zeroRows(float(&cov_mat)[_k_num_states][_k_num_states], uint8_t first, uint8_t last)
uint32_t in_air
7 - true when the vehicle is airborne
float mag_declination_deg
magnetic declination (degrees)
uint32_t wind
8 - true when wind velocity is being estimated
float angErr
1-Sigma angular error (rad)
struct estimator::innovation_fault_status_u::@58 flags
Vector3f mag
NED magnetometer body frame measurements (Gauss)
static constexpr uint8_t _k_num_states
number of EKF states
float heading_innov_gate
heading fusion innovation consistency gate size (STD)
Class for core functions for ekf attitude and position estimator.
magSample _mag_sample_delayed