/sw/airborne/subsystems/ahrs/ahrs_float_ekf.c

https://bitbucket.org/tamasszabo/paparazzi_mavlink · C · 164 lines · 52 code · 20 blank · 92 comment · 0 complexity · 4a1323d9906a5594f2895829ce3f47b7 MD5 · raw file

  1. /*
  2. * Copyright (C) 2008-2009 Antoine Drouin <poinix@gmail.com>
  3. *
  4. * This file is part of paparazzi.
  5. *
  6. * paparazzi is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2, or (at your option)
  9. * any later version.
  10. *
  11. * paparazzi is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with paparazzi; see the file COPYING. If not, write to
  18. * the Free Software Foundation, 59 Temple Place - Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. */
  21. #include "math/pprz_algebra_float.h"
  22. /* our estimated attitude */
  23. struct FloatQuat bafe_quat;
  24. /* our estimated gyro biases */
  25. struct FloatRates bafe_bias;
  26. /* we get unbiased body rates as byproduct */
  27. struct FloatRates bafe_rates;
  28. /* maintain a euler angles representation */
  29. struct FloatEulers bafe_eulers;
  30. /* maintains a rotation matrix representation */
  31. struct FloatEulers bafe_dcm;
  32. /* time derivative of our quaternion */
  33. struct FloatQuat bafe_qdot;
  34. #define BAFE_SSIZE 7
  35. /* covariance matrix and its time derivative */
  36. float bafe_P[BAFE_SSIZE][BAFE_SSIZE];
  37. float bafe_Pdot[BAFE_SSIZE][BAFE_SSIZE];
  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 bafe_F[4][7];
  44. /*
  45. * Kalman filter variables.
  46. */
  47. float bafe_PHt[7];
  48. float bafe_K[7];
  49. float bafe_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 bafe_H[4];
  57. /* temporary variable used during state covariance update */
  58. float bafe_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 bafe_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 BAFE_R_PHI 1.3 * 1.3
  76. #define BAFE_R_THETA 1.3 * 1.3
  77. #define BAFE_R_PSI 2.5 * 2.5
  78. #ifndef BAFE_DT
  79. #define BAFE_DT (1./512.)
  80. #endif
  81. extern void ahrs_init(void);
  82. extern void ahrs_align(void);
  83. /*
  84. * Propagate our dynamic system
  85. *
  86. * quat_dot = Wxq(pqr) * quat
  87. * bias_dot = 0
  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 ahrs_propagate(void) {
  109. /* compute unbiased rates */
  110. RATES_FLOAT_OF_BFP(bafe_rates, imu.gyro);
  111. RATES_SUB(bafe_rates, bafe_bias);
  112. /* compute F
  113. F is only needed later on to update the state covariance P.
  114. However, its [0:3][0:3] region is actually the Wxq(pqr) which is needed to
  115. compute the time derivative of the quaternion, so we compute F now
  116. */
  117. /* Fill in Wxq(pqr) into F */
  118. bafe_F[0][0] = bafe_F[1][1] = bafe_F[2][2] = bafe_F[3][3] = 0;
  119. bafe_F[1][0] = bafe_F[2][3] = bafe_rates.p * 0.5;
  120. bafe_F[2][0] = bafe_F[3][1] = bafe_rates.q * 0.5;
  121. bafe_F[3][0] = bafe_F[1][2] = bafe_rates.r * 0.5;
  122. bafe_F[0][1] = bafe_F[3][2] = -bafe_F[1][0];
  123. bafe_F[0][2] = bafe_F[1][3] = -bafe_F[2][0];
  124. bafe_F[0][3] = bafe_F[2][1] = -bafe_F[3][0];
  125. /* Fill in [4:6][0:3] region */
  126. bafe_F[0][4] = bafe_F[2][6] = bafe_quat.qx * 0.5;
  127. bafe_F[0][5] = bafe_F[3][4] = bafe_quat.qy * 0.5;
  128. bafe_F[0][6] = bafe_F[1][5] = bafe_quat.qz * 0.5;
  129. bafe_F[1][4] = bafe_F[2][5] = bafe_F[3][6] = bafe_quat.qi * -0.5;
  130. bafe_F[3][5] = -bafe_F[0][4];
  131. bafe_F[1][6] = -bafe_F[0][5];
  132. bafe_F[2][4] = -bafe_F[0][6];
  133. /* quat_dot = Wxq(pqr) * quat */
  134. bafe_qdot.qi= bafe_F[0][1]*bafe_quat.qx+bafe_F[0][2]*bafe_quat.qy+bafe_F[0][3] * bafe_quat.qz;
  135. bafe_qdot.qx= bafe_F[1][0]*bafe_quat.qi +bafe_F[1][2]*bafe_quat.qy+bafe_F[1][3] * bafe_quat.qz;
  136. bafe_qdot.qy= bafe_F[2][0]*bafe_quat.qi+bafe_F[2][1]*bafe_quat.qx +bafe_F[2][3] * bafe_quat.qz;
  137. bafe_qdot.qz= bafe_F[3][0]*bafe_quat.qi+bafe_F[3][1]*bafe_quat.qx+bafe_F[3][2]*bafe_quat.qy ;
  138. /* propagate quaternion */
  139. bafe_quat.qi += bafe_qdot.qi * BAFE_DT;
  140. bafe_quat.qx += bafe_qdot.qx * BAFE_DT;
  141. bafe_quat.qy += bafe_qdot.qy * BAFE_DT;
  142. bafe_quat.qz += bafe_qdot.qz * BAFE_DT;
  143. }
  144. extern void ahrs_update(void);