PageRenderTime 28ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/sw/in_progress/inertial/C/ahrs_quat_fast_ekf.c

https://github.com/AshuLara/paparazzi_lisa
C | 404 lines | 203 code | 51 blank | 150 comment | 29 complexity | b0fa3029d0c5597793dbda0239ad24fa MD5 | raw file
  1. #include "ahrs_quat_fast_ekf.h"
  2. #include <math.h>
  3. #include <inttypes.h>
  4. #include <string.h>
  5. /* Time step */
  6. #define afe_dt 0.0166667
  7. /* We have seven variables in our state -- the quaternion attitude
  8. * estimate and three gyro bias values
  9. */
  10. FLOAT_T afe_q0, afe_q1, afe_q2, afe_q3;
  11. FLOAT_T afe_bias_p, afe_bias_q, afe_bias_r;
  12. /* We maintain unbiased rates. */
  13. FLOAT_T afe_p, afe_q, afe_r;
  14. /* We maintain eulers */
  15. FLOAT_T afe_phi, afe_theta, afe_psi;
  16. /* time derivative of state
  17. * we know that bias_p_dot = bias_q_dot = bias_r_dot = 0
  18. */
  19. FLOAT_T afe_q0_dot, afe_q1_dot, afe_q2_dot, afe_q3_dot;
  20. /*
  21. * The Direction Cosine Matrix is used to help rotate measurements
  22. * to and from the body frame. We only need five elements from it,
  23. * so those are computed explicitly rather than the entire matrix
  24. *
  25. * External routines might want these (to until sensor readings),
  26. * so we export them.
  27. */
  28. FLOAT_T afe_dcm00;
  29. FLOAT_T afe_dcm01;
  30. FLOAT_T afe_dcm02;
  31. FLOAT_T afe_dcm12;
  32. FLOAT_T afe_dcm22;
  33. /*
  34. * Covariance matrix and covariance matrix derivative
  35. */
  36. FLOAT_T afe_P[7][7];
  37. FLOAT_T afe_Pdot[7][7];
  38. /*
  39. * F represents the Jacobian of the derivative of the system with respect
  40. * its states. We do not allocate the bottom three rows since we know that
  41. * the derivatives of bias_dot are all zero.
  42. */
  43. FLOAT_T afe_F[4][7];
  44. /*
  45. * Kalman filter variables.
  46. */
  47. FLOAT_T afe_PHt[7];
  48. FLOAT_T afe_K[7];
  49. FLOAT_T afe_E;
  50. /*
  51. * H represents the Jacobian of the measurements of the attitude
  52. * with respect to the states of the filter. We do not allocate the bottom
  53. * three rows since we know that the attitude measurements have no
  54. * relationship to gyro bias.
  55. */
  56. FLOAT_T afe_H[4];
  57. /* temporary variable used during state covariance update */
  58. FLOAT_T afe_FP[4][7];
  59. /*
  60. * Q is our estimate noise variance. It is supposed to be an NxN
  61. * matrix, but with elements only on the diagonals. Additionally,
  62. * since the quaternion has no expected noise (we can't directly measure
  63. * it), those are zero. For the gyro, we expect around 5 deg/sec noise,
  64. * which is 0.08 rad/sec. The variance is then 0.08^2 ~= 0.0075.
  65. */
  66. /* I measured about 0.009 rad/s noise */
  67. #define afe_Q_gyro 8e-03
  68. /*
  69. * R is our measurement noise estimate. Like Q, it is supposed to be
  70. * an NxN matrix with elements on the diagonals. However, since we can
  71. * not directly measure the gyro bias, we have no estimate for it.
  72. * We only have an expected noise in the pitch and roll accelerometers
  73. * and in the compass.
  74. */
  75. #define AFE_R_PHI 1.3 * 1.3
  76. #define AFE_R_THETA 1.3 * 1.3
  77. #define AFE_R_PSI 2.5 * 2.5
  78. #include "ahrs_quat_fast_ekf_utils.h"
  79. /*
  80. * Call ahrs_state_update every dt seconds with the raw body frame angular
  81. * rates. It updates the attitude state estimate via this function:
  82. *
  83. * quat_dot = Wxq(pqr) * quat
  84. * bias_dot = 0
  85. *
  86. * Since F also contains Wxq, we fill it in here and then reuse the computed
  87. * values. This avoids the extra floating point math.
  88. *
  89. * Wxq is the quaternion omega matrix:
  90. *
  91. * [ 0, -p, -q, -r ]
  92. * 1/2 * [ p, 0, r, -q ]
  93. * [ q, -r, 0, p ]
  94. * [ r, q, -p, 0 ]
  95. *
  96. *
  97. *
  98. *
  99. * [ 0 -p -q -r q1 q2 q3]
  100. * F = 1/2 * [ p 0 r -q -q0 q3 -q2]
  101. * [ q -r 0 p -q3 q0 q1]
  102. * [ r q -p 0 q2 -q1 -q0]
  103. * [ 0 0 0 0 0 0 0]
  104. * [ 0 0 0 0 0 0 0]
  105. * [ 0 0 0 0 0 0 0]
  106. *
  107. */
  108. void afe_predict( const FLOAT_T* gyro ) {
  109. /* Unbias our gyro values */
  110. afe_p = gyro[0] - afe_bias_p;
  111. afe_q = gyro[1] - afe_bias_q;
  112. afe_r = gyro[2] - afe_bias_r;
  113. /* compute F
  114. F is only needed later on to update the state covariance P.
  115. However, its [0:3][0:3] region is actually the Wxq(pqr) which is needed to
  116. compute the time derivative of the quaternion, so we compute F now */
  117. /* Fill in Wxq(pqr) into F */
  118. afe_F[0][0] = afe_F[1][1] = afe_F[2][2] = afe_F[3][3] = 0;
  119. afe_F[1][0] = afe_F[2][3] = afe_p * 0.5;
  120. afe_F[2][0] = afe_F[3][1] = afe_q * 0.5;
  121. afe_F[3][0] = afe_F[1][2] = afe_r * 0.5;
  122. afe_F[0][1] = afe_F[3][2] = -afe_F[1][0];
  123. afe_F[0][2] = afe_F[1][3] = -afe_F[2][0];
  124. afe_F[0][3] = afe_F[2][1] = -afe_F[3][0];
  125. /* Fill in [4:6][0:3] region */
  126. afe_F[0][4] = afe_F[2][6] = afe_q1 * 0.5;
  127. afe_F[0][5] = afe_F[3][4] = afe_q2 * 0.5;
  128. afe_F[0][6] = afe_F[1][5] = afe_q3 * 0.5;
  129. afe_F[1][4] = afe_F[2][5] = afe_F[3][6] = afe_q0 * -0.5;
  130. afe_F[3][5] = -afe_F[0][4];
  131. afe_F[1][6] = -afe_F[0][5];
  132. afe_F[2][4] = -afe_F[0][6];
  133. /* update state */
  134. /* quat_dot = Wxq(pqr) * quat */
  135. afe_q0_dot = afe_F[0][1] * afe_q1 + afe_F[0][2] * afe_q2 + afe_F[0][3] * afe_q3;
  136. afe_q1_dot = afe_F[1][0] * afe_q0 + afe_F[1][2] * afe_q2 + afe_F[1][3] * afe_q3;
  137. afe_q2_dot = afe_F[2][0] * afe_q0 + afe_F[2][1] * afe_q1 + afe_F[2][3] * afe_q3;
  138. afe_q3_dot = afe_F[3][0] * afe_q0 + afe_F[3][1] * afe_q1 + afe_F[3][2] * afe_q2;
  139. /* quat = quat + quat_dot * dt */
  140. afe_q0 += afe_q0_dot * afe_dt;
  141. afe_q1 += afe_q1_dot * afe_dt;
  142. afe_q2 += afe_q2_dot * afe_dt;
  143. afe_q3 += afe_q3_dot * afe_dt;
  144. /* normalize quaternion */
  145. AFE_NORM_QUAT();
  146. /* */
  147. AFE_DCM_OF_QUAT();
  148. AFE_EULER_OF_DCM();
  149. #ifdef EKF_UPDATE_DISCRETE
  150. /*
  151. * update covariance
  152. * Pdot = F*P*F' + Q
  153. * P += Pdot * dt
  154. */
  155. uint8_t i, j, k;
  156. for (i=0; i<4; i++) {
  157. for (j=0; j<7; j++) {
  158. afe_FP[i][j] = 0.;
  159. for (k=0; k<7; k++) {
  160. afe_FP[i][j] += afe_F[i][k] * afe_P[k][j];
  161. }
  162. }
  163. }
  164. for (i=0; i<4; i++) {
  165. for (j=0; j<4; j++) {
  166. afe_Pdot[i][j] = 0.;
  167. for (k=0; k<7; k++) {
  168. afe_Pdot[i][j] += afe_FP[i][k] * afe_F[j][k];
  169. }
  170. }
  171. }
  172. /* add Q !!! added below*/
  173. // Pdot[4][4] = afe_Q_gyro;
  174. // Pdot[5][5] = afe_Q_gyro;
  175. // Pdot[6][6] = afe_Q_gyro;
  176. /* P = P + Pdot * dt */
  177. for (i=0; i<4; i++)
  178. for (j=0; j<4; j++)
  179. afe_P[i][j] += afe_Pdot[i][j] * afe_dt;
  180. afe_P[4][4] += afe_Q_gyro * afe_dt;
  181. afe_P[5][5] += afe_Q_gyro * afe_dt;
  182. afe_P[6][6] += afe_Q_gyro * afe_dt;
  183. #endif
  184. #ifdef EKF_UPDATE_CONTINUOUS
  185. /* Pdot = F*P + F'*P + Q */
  186. memset( afe_Pdot, 0, sizeof(afe_Pdot) );
  187. /*
  188. * Compute the A*P+P*At for the bottom rows of P and A_tranpose
  189. */
  190. uint8_t i, j, k;
  191. for( i=0 ; i<4 ; i++ )
  192. for( j=0 ; j<7 ; j++ )
  193. for( k=4 ; k<7 ; k++ )
  194. {
  195. const FLOAT_T F_i_k = afe_F[i][k];
  196. afe_Pdot[i][j] += F_i_k * afe_P[k][j];
  197. afe_Pdot[j][i] += afe_P[j][k] * F_i_k;
  198. }
  199. /*
  200. * Compute F*P + P*Ft for the region [0..3][0..3]
  201. */
  202. for( i=0 ; i<4 ; i++ )
  203. for( j=0 ; j<4 ; j++ )
  204. for( k=0 ; k<4 ; k++ )
  205. {
  206. /* The diagonals of A are zero */
  207. if( i == k && j == k )
  208. continue;
  209. if( j == k )
  210. afe_Pdot[i][j] += afe_F[i][k] * afe_P[k][j];
  211. else
  212. if( i == k )
  213. afe_Pdot[i][j] += afe_P[i][k] * afe_F[j][k];
  214. else
  215. afe_Pdot[i][j] += ( afe_F[i][k] * afe_P[k][j] +
  216. afe_P[i][k] * afe_F[j][k] );
  217. }
  218. /* Add in the non-zero parts of Q. The quaternion portions
  219. * are all zero, and all the gyros share the same value.
  220. */
  221. for( i=4 ; i<7 ; i++ )
  222. afe_Pdot[i][i] += afe_Q_gyro;
  223. /* Compute P = P + Pdot * dt */
  224. for( i=0 ; i<7 ; i++ )
  225. for( j=0 ; j<7 ; j++ )
  226. afe_P[i][j] += afe_Pdot[i][j] * afe_dt;
  227. #endif
  228. }
  229. /*
  230. *
  231. */
  232. static void run_kalman( const FLOAT_T R_axis, const FLOAT_T error ) {
  233. int i, j;
  234. /* PHt = P * H' */
  235. afe_PHt[0] = afe_P[0][0] * afe_H[0] + afe_P[0][1] * afe_H[1] + afe_P[0][2] * afe_H[2] + afe_P[0][3] * afe_H[3];
  236. afe_PHt[1] = afe_P[1][0] * afe_H[0] + afe_P[1][1] * afe_H[1] + afe_P[1][2] * afe_H[2] + afe_P[1][3] * afe_H[3];
  237. afe_PHt[2] = afe_P[2][0] * afe_H[0] + afe_P[2][1] * afe_H[1] + afe_P[2][2] * afe_H[2] + afe_P[2][3] * afe_H[3];
  238. afe_PHt[3] = afe_P[3][0] * afe_H[0] + afe_P[3][1] * afe_H[1] + afe_P[3][2] * afe_H[2] + afe_P[3][3] * afe_H[3];
  239. afe_PHt[4] = afe_P[4][0] * afe_H[0] + afe_P[4][1] * afe_H[1] + afe_P[4][2] * afe_H[2] + afe_P[4][3] * afe_H[3];
  240. afe_PHt[5] = afe_P[5][0] * afe_H[0] + afe_P[5][1] * afe_H[1] + afe_P[5][2] * afe_H[2] + afe_P[5][3] * afe_H[3];
  241. afe_PHt[6] = afe_P[6][0] * afe_H[0] + afe_P[6][1] * afe_H[1] + afe_P[6][2] * afe_H[2] + afe_P[6][3] * afe_H[3];
  242. /* E = H * PHt + R */
  243. afe_E = R_axis;
  244. afe_E += afe_H[0] * afe_PHt[0];
  245. afe_E += afe_H[1] * afe_PHt[1];
  246. afe_E += afe_H[2] * afe_PHt[2];
  247. afe_E += afe_H[3] * afe_PHt[3];
  248. /* Compute the inverse of E */
  249. afe_E = 1.0 / afe_E;
  250. /* Compute K = P * H' * inv(E) */
  251. afe_K[0] = afe_PHt[0] * afe_E;
  252. afe_K[1] = afe_PHt[1] * afe_E;
  253. afe_K[2] = afe_PHt[2] * afe_E;
  254. afe_K[3] = afe_PHt[3] * afe_E;
  255. afe_K[4] = afe_PHt[4] * afe_E;
  256. afe_K[5] = afe_PHt[5] * afe_E;
  257. afe_K[6] = afe_PHt[6] * afe_E;
  258. /* Update our covariance matrix: P = P - K * H * P */
  259. /* Compute HP = H * P, reusing the PHt array. */
  260. afe_PHt[0] = afe_H[0] * afe_P[0][0] + afe_H[1] * afe_P[1][0] + afe_H[2] * afe_P[2][0] + afe_H[3] * afe_P[3][0];
  261. afe_PHt[1] = afe_H[0] * afe_P[0][1] + afe_H[1] * afe_P[1][1] + afe_H[2] * afe_P[2][1] + afe_H[3] * afe_P[3][1];
  262. afe_PHt[2] = afe_H[0] * afe_P[0][2] + afe_H[1] * afe_P[1][2] + afe_H[2] * afe_P[2][2] + afe_H[3] * afe_P[3][2];
  263. afe_PHt[3] = afe_H[0] * afe_P[0][3] + afe_H[1] * afe_P[1][3] + afe_H[2] * afe_P[2][3] + afe_H[3] * afe_P[3][3];
  264. afe_PHt[4] = afe_H[0] * afe_P[0][4] + afe_H[1] * afe_P[1][4] + afe_H[2] * afe_P[2][4] + afe_H[3] * afe_P[3][4];
  265. afe_PHt[5] = afe_H[0] * afe_P[0][5] + afe_H[1] * afe_P[1][5] + afe_H[2] * afe_P[2][5] + afe_H[3] * afe_P[3][5];
  266. afe_PHt[6] = afe_H[0] * afe_P[0][6] + afe_H[1] * afe_P[1][6] + afe_H[2] * afe_P[2][6] + afe_H[3] * afe_P[3][6];
  267. /* Compute P -= K * HP (aliased to PHt) */
  268. for( i=0 ; i<4 ; i++ )
  269. for( j=0 ; j<7 ; j++ )
  270. afe_P[i][j] -= afe_K[i] * afe_PHt[j];
  271. /* Update our state: X += K * error */
  272. afe_q0 += afe_K[0] * error;
  273. afe_q1 += afe_K[1] * error;
  274. afe_q2 += afe_K[2] * error;
  275. afe_q3 += afe_K[3] * error;
  276. afe_bias_p += afe_K[4] * error;
  277. afe_bias_q += afe_K[5] * error;
  278. afe_bias_r += afe_K[6] * error;
  279. /* normalize quaternion */
  280. AFE_NORM_QUAT();
  281. }
  282. /*
  283. * Do the Kalman filter on the acceleration and compass readings.
  284. * This is normally a very simple:
  285. *
  286. * E = H * P * H' + R
  287. * K = P * H' * inv(E)
  288. * P = P - K * H * P
  289. * X = X + K * error
  290. *
  291. * We notice that P * H' is used twice, so we can cache the
  292. * results of it.
  293. *
  294. * H represents the Jacobian of measurements to states, which we know
  295. * to only have the top four rows filled in since the attitude
  296. * measurement does not relate to the gyro bias. This allows us to
  297. * ignore parts of PHt
  298. *
  299. * We also only process one axis at a time to avoid having to perform
  300. * the 3x3 matrix inversion.
  301. */
  302. void afe_update_phi( const FLOAT_T* accel ) {
  303. AFE_COMPUTE_H_PHI();
  304. FLOAT_T accel_phi = afe_phi_of_accel(accel);
  305. FLOAT_T err_phi = accel_phi - afe_phi;
  306. AFE_WARP( err_phi, M_PI);
  307. run_kalman( AFE_R_PHI, err_phi );
  308. AFE_DCM_OF_QUAT();
  309. AFE_EULER_OF_DCM();
  310. }
  311. void afe_update_theta( const FLOAT_T* accel ) {
  312. AFE_COMPUTE_H_THETA();
  313. FLOAT_T accel_theta = afe_theta_of_accel(accel);
  314. FLOAT_T err_theta = accel_theta - afe_theta;
  315. AFE_WARP( err_theta, M_PI_2);
  316. run_kalman( AFE_R_THETA, err_theta );
  317. AFE_DCM_OF_QUAT();
  318. AFE_EULER_OF_DCM();
  319. }
  320. void afe_update_psi( const int16_t* mag ) {
  321. AFE_COMPUTE_H_PSI();
  322. FLOAT_T mag_psi = afe_psi_of_mag(mag);
  323. FLOAT_T err_psi = mag_psi - afe_psi;
  324. AFE_WARP( err_psi, M_PI);
  325. run_kalman( AFE_R_PSI, err_psi );
  326. AFE_DCM_OF_QUAT();
  327. AFE_EULER_OF_DCM();
  328. }
  329. /*
  330. * Initialize the AHRS state data and covariance matrix.
  331. */
  332. void afe_init( const int16_t *mag, const FLOAT_T* accel, const FLOAT_T* gyro ) {
  333. /* F and P will be updated only on the non zero locations */
  334. memset( (void*) afe_F, 0, sizeof( afe_F ) );
  335. memset( (void*) afe_P, 0, sizeof( afe_P ) );
  336. int i;
  337. for( i=0 ; i<4 ; i++ )
  338. afe_P[i][i] = 1.;
  339. for( i=4 ; i<7 ; i++ )
  340. afe_P[i][i] = .5;
  341. /* assume vehicle is still, so initial bias are gyro readings */
  342. afe_bias_p = gyro[0];
  343. afe_bias_q = gyro[1];
  344. afe_bias_r = gyro[2];
  345. afe_phi = afe_phi_of_accel(accel);
  346. afe_theta = afe_theta_of_accel(accel);
  347. afe_psi = 0.;
  348. AFE_QUAT_OF_EULER();
  349. AFE_DCM_OF_QUAT();
  350. afe_psi = afe_psi_of_mag( mag );
  351. AFE_QUAT_OF_EULER();
  352. AFE_DCM_OF_QUAT();
  353. }