求助关于卡尔曼滤波

[复制链接]
6734|7
 楼主| wang1987 发表于 2011-2-26 10:56 | 显示全部楼层 |阅读模式
刚开始学卡尔曼滤波,一直是一知半解,下面的源码注释是我自己加上的,但不知道对不对,求大虾们,给我注释完整,并在关键的地方能有个说明,先谢谢了,小弟拜上!
float kalmanUpdate(const float gyro_m,const float incAngle)//只读变量不可以修改
{              //         陀螺仪                角度
        float K_0;//含有卡尔曼增益的另外一个函数,用于计算最优估计值
        float K_1;//含有卡尔曼增益的函数,用于计算最优估计值的偏差
        float Y_0;
        float Y_1;
        
        float Rate;
        float Pdot[4];
        float angle_err;//角度偏量
        float E;
               
        static float angle = 0;            //下时刻最优估计值角度
        static float q_bias = 0;        //最优估计值的偏差                 
        static float P[2][2] = {{ 1, 0 }, { 0, 1 }};
                  
        Rate = gyro_m - q_bias;
                                                                  //#define dt                  0.0015//滞后
                                                              //#define R_angle          0.69
                                                              //#define Q_angle          0.0001
                                                               //#define Q_gyro           0.0003 //卡尔曼滤波参数
         
        Pdot[0] = Q_angle - P[0][1] - P[1][0]; //卡尔曼增益矩阵        
        Pdot[1] = - P[1][1];                        
        Pdot[2] = - P[1][1];                                 
        Pdot[3] = Q_gyro;                        

        angle += Rate * dt;

        P[0][0] += Pdot[0] * dt; //计算协方差矩阵
        P[0][1] += Pdot[1] * dt;
        P[1][0] += Pdot[2] * dt;
        P[1][1] += Pdot[3] * dt;
  
        angle_err = incAngle - angle;

        E = R_angle + P[0][0];
        K_0 = P[0][0] / E;
        K_1 = P[1][0] / E;

        Y_0 = P[0][0];   
        Y_1 = P[0][1];
  
        P[0][0] -= K_0 * Y_0; //跟新协方差矩阵
        P[0][1] -= K_0 * Y_1;
        P[1][0] -= K_1 * Y_0;
        P[1][1] -= K_1 * Y_1;


        angle += K_0 * angle_err; //给出最优估计值
        q_bias += K_1 * angle_err;//跟新最优估计值偏差

        return angle;
}
 楼主| wang1987 发表于 2011-3-1 16:31 | 显示全部楼层
求解啊
Chaos_zc 发表于 2011-8-9 23:06 | 显示全部楼层
本帖最后由 Chaos_zc 于 2011-8-9 23:08 编辑

貌似是好久以前的帖了,其实我也一知半解,不过确实花了很多时间在kalman滤波上面,权当探讨一下,兄弟有什么新的见解也请不吝赐教:

  1. // float gyro_m:陀螺仪测得的量(角速度)
  2. //float incAngle:加计测得的角度值

  3. #define dt                  0.0015//卡尔曼滤波采样频率
  4. #define R_angle          0.69 //测量噪声的协方差(即是测量偏差)
  5. #define Q_angle          0.0001//过程噪声的协方差
  6. #define Q_gyro           0.0003 //过程噪声的协方差  过程噪声协方差为一个一行两列矩阵

  7. float kalmanUpdate(const float gyro_m,const float incAngle  
  8. {         
  9.         float K_0;//含有卡尔曼增益的另外一个函数,用于计算最优估计值
  10.         float K_1;//含有卡尔曼增益的函数,用于计算最优估计值的偏差
  11.         float Y_0;
  12.         float Y_1;
  13.         
  14.         float Rate;//去除偏差后的角速度
  15.         float Pdot[4];//过程协方差矩阵的微分矩阵
  16.         float angle_err;//角度偏量
  17.         float E;//计算的过程量
  18.                
  19.         static float angle = 0;            //下时刻最优估计值角度
  20.         static float q_bias = 0;        //陀螺仪的偏差                 
  21.         static float P[2][2] = {{ 1, 0 }, { 0, 1 }};//过程协方差矩阵
  22.                   
  23.         Rate = gyro_m - q_bias;
  24.   
  25.         //计算过程协方差矩阵的微分矩阵     
  26.         Pdot[0] = Q_angle - P[0][1] - P[1][0];         
  27.         Pdot[1] = - P[1][1];                        
  28.         Pdot[2] = - P[1][1];                                 
  29.         Pdot[3] = Q_gyro;                        

  30.         angle += Rate * dt; //角速度积分得出角度

  31.         P[0][0] += Pdot[0] * dt; //计算协方差矩阵
  32.         P[0][1] += Pdot[1] * dt;
  33.         P[1][0] += Pdot[2] * dt;
  34.         P[1][1] += Pdot[3] * dt;
  35.   
  36.         angle_err = incAngle - angle; //计算角度偏差

  37.         E = R_angle + P[0][0];
  38.         K_0 = P[0][0] / E; //计算卡尔曼增益
  39.         K_1 = P[1][0] / E;

  40.         Y_0 = P[0][0];   
  41.         Y_1 = P[0][1];
  42.   
  43.         P[0][0] -= K_0 * Y_0; //跟新协方差矩阵
  44.         P[0][1] -= K_0 * Y_1;
  45.         P[1][0] -= K_1 * Y_0;
  46.         P[1][1] -= K_1 * Y_1;


  47.         angle += K_0 * angle_err; //给出最优估计值
  48.         q_bias += K_1 * angle_err;//跟新最优估计值偏差

  49.         return angle;

Chaos_zc 发表于 2011-8-9 23:11 | 显示全部楼层
看懂英文的话这个应该解释的比较清楚,虽然有点长,但很有价值。感觉卡尔曼滤波确实很难,看了之后可以交流一下。


  1. #include "ars.h"



  2. #include <math.h>


  3. /*
  4. * Our covariance matrix. This is updated at every time step to
  5. * determine how well the sensors are tracking the actual state.
  6. */
  7. static float P[2][2] = {
  8. { 1, 0 },
  9. { 0, 1 },
  10. };


  11. /*
  12. * Our two states, the angle and the gyro bias. As a byproduct of computing
  13. * the angle, we also have an unbiased angular rate available. These are
  14. * read-only to the user of the module.
  15. */
  16. float angle;
  17. float q_bias;
  18. float rate;


  19. /*
  20. * R represents the measurement covariance noise. In this case,
  21. * it is a 1x1 matrix that says that we expect 0.3 rad jitter
  22. * from the accelerometer.
  23. */
  24. static const float R_angle = 0.3;


  25. /*
  26. * Q is a 2x2 matrix that represents the process covariance noise.
  27. * In this case, it indicates how much we trust the acceleromter
  28. * relative to the gyros.
  29. */
  30. static const float Q_angle = 0.001;
  31. static const float Q_gyro = 0.003;


  32. /*
  33. * state_update is called every dt with a biased gyro measurement
  34. * by the user of the module. It updates the current angle and
  35. * rate estimate.
  36. *
  37. * The pitch gyro measurement should be scaled into real units, but
  38. * does not need any bias removal. The filter will track the bias.
  39. *
  40. * Our state vector is:
  41. *
  42. * X = [ angle, gyro_bias ]
  43. *
  44. * It runs the state estimation forward via the state functions:
  45. *
  46. * Xdot = [ angle_dot, gyro_bias_dot ]
  47. *
  48. * angle_dot = gyro - gyro_bias
  49. * gyro_bias_dot = 0
  50. *
  51. * And updates the covariance matrix via the function:
  52. *
  53. * Pdot = A*P + P*A' + Q
  54. *
  55. * A is the Jacobian of Xdot with respect to the states:
  56. *
  57. * A = [ d(angle_dot)/d(angle) d(angle_dot)/d(gyro_bias) ]
  58. * [ d(gyro_bias_dot)/d(angle) d(gyro_bias_dot)/d(gyro_bias) ]
  59. *
  60. * = [ 0 -1 ]
  61. * [ 0 0 ]
  62. *
  63. * Due to the small CPU available on the microcontroller, we've
  64. * hand optimized the C code to only compute the terms that are
  65. * explicitly non-zero, as well as expanded out the matrix math
  66. * to be done in as few steps as possible. This does make it harder
  67. * to read, debug and extend, but also allows us to do this with
  68. * very little CPU time.
  69. */
  70. void ars_predict(float gyro, float dt)
  71. {
  72. /* Unbias our gyro */
  73. const float q = gyro - q_bias;

  74. /*
  75. * Compute the derivative of the covariance matrix
  76. *
  77. * Pdot = A*P + P*A' + Q
  78. *
  79. * We've hand computed the expansion of A = [ 0 -1, 0 0 ] multiplied
  80. * by P and P multiplied by A' = [ 0 0, -1, 0 ]. This is then added
  81. * to the diagonal elements of Q, which are Q_angle and Q_gyro.
  82. */
  83. const float Pdot[2 * 2] = {
  84. Q_angle - P[0][1] - P[1][0], /* 0,0 */
  85. - P[1][1], /* 0,1 */
  86. - P[1][1], /* 1,0 */
  87. Q_gyro /* 1,1 */
  88. };

  89. /* Store our unbias gyro estimate */
  90. rate = q;

  91. /*
  92. * Update our angle estimate
  93. * angle += angle_dot * dt
  94. * += (gyro - gyro_bias) * dt
  95. * += q * dt
  96. */
  97. angle += q * dt;

  98. /* Update the covariance matrix */
  99. P[0][0] += Pdot[0] * dt;
  100. P[0][1] += Pdot[1] * dt;
  101. P[1][0] += Pdot[2] * dt;
  102. P[1][1] += Pdot[3] * dt;
  103. }


  104. /*
  105. * kalman_update is called by a user of the module when a new
  106. * accelerometer measurement is available. ax_m and az_m do not
  107. * need to be scaled into actual units, but must be zeroed and have
  108. * the same scale.
  109. *
  110. * This does not need to be called every time step, but can be if
  111. * the accelerometer data are available at the same rate as the
  112. * rate gyro measurement.
  113. *
  114. * For a two-axis accelerometer mounted perpendicular to the rotation
  115. * axis, we can compute the angle for the full 360 degree rotation
  116. * with no linearization errors by using the arctangent of the two
  117. * readings.
  118. *
  119. * As commented in state_update, the math here is simplified to
  120. * make it possible to execute on a small microcontroller with no
  121. * floating point unit. It will be hard to read the actual code and
  122. * see what is happening, which is why there is this extensive
  123. * comment block.
  124. *
  125. * The C matrix is a 1x2 (measurements x states) matrix that
  126. * is the Jacobian matrix of the measurement value with respect
  127. * to the states. In this case, C is:
  128. *
  129. * C = [ d(angle_m)/d(angle) d(angle_m)/d(gyro_bias) ]
  130. * = [ 1 0 ]
  131. *
  132. * because the angle measurement directly corresponds to the angle
  133. * estimate and the angle measurement has no relation to the gyro
  134. * bias.
  135. */
  136. float
  137. ars_update(const float angle_m)
  138. {
  139. /* Compute our measured angle and the error in our estimate */
  140. const float angle_err = angle_m - angle;

  141. /*
  142. * C_0 shows how the state measurement directly relates to
  143. * the state estimate.
  144. *
  145. * The C_1 shows that the state measurement does not relate
  146. * to the gyro bias estimate. We don't actually use this, so
  147. * we comment it out.
  148. */
  149. const float C_0 = 1;
  150. /* const float C_1 = 0; */

  151. /*
  152. * PCt<2,1> = P<2,2> * C'<2,1>, which we use twice. This makes
  153. * it worthwhile to precompute and store the two values.
  154. * Note that C[0,1] = C_1 is zero, so we do not compute that
  155. * term.
  156. */
  157. const float PCt_0 = C_0 * P[0][0]; /* + C_1 * P[0][1] = 0 */
  158. const float PCt_1 = C_0 * P[1][0]; /* + C_1 * P[1][1] = 0 */

  159. /*
  160. * Compute the error estimate. From the Kalman filter paper:
  161. *
  162. * E = C P C' + R
  163. *
  164. * Dimensionally,
  165. *
  166. * E<1,1> = C<1,2> P<2,2> C'<2,1> + R<1,1>
  167. *
  168. * Again, note that C_1 is zero, so we do not compute the term.
  169. */
  170. const float E =
  171. R_angle
  172. + C_0 * PCt_0
  173. /* + C_1 * PCt_1 = 0 */
  174. ;

  175. /*
  176. * Compute the Kalman filter gains. From the Kalman paper:
  177. *
  178. * K = P C' inv(E)
  179. *
  180. * Dimensionally:
  181. *
  182. * K<2,1> = P<2,2> C'<2,1> inv(E)<1,1>
  183. *
  184. * Luckilly, E is <1,1>, so the inverse of E is just 1/E.
  185. */
  186. const float K_0 = PCt_0 / E;
  187. const float K_1 = PCt_1 / E;

  188. /*
  189. * Update covariance matrix. Again, from the Kalman filter paper:
  190. *
  191. * P = P - K C P
  192. *
  193. * Dimensionally:
  194. *
  195. * P<2,2> -= K<2,1> C<1,2> P<2,2>
  196. *
  197. * We first compute t<1,2> = C P. Note that:
  198. *
  199. * t[0,0] = C[0,0] * P[0,0] + C[0,1] * P[1,0]
  200. *
  201. * But, since C_1 is zero, we have:
  202. *
  203. * t[0,0] = C[0,0] * P[0,0] = PCt[0,0]
  204. *
  205. * This saves us a floating point multiply.
  206. */
  207. const float t_0 = PCt_0; /* C_0 * P[0][0] + C_1 * P[1][0] */
  208. const float t_1 = C_0 * P[0][1]; /* + C_1 * P[1][1] = 0 */

  209. P[0][0] -= K_0 * t_0;
  210. P[0][1] -= K_0 * t_1;
  211. P[1][0] -= K_1 * t_0;
  212. P[1][1] -= K_1 * t_1;

  213. /*
  214. * Update our state estimate. Again, from the Kalman paper:
  215. *
  216. * X += K * err
  217. *
  218. * And, dimensionally,
  219. *
  220. * X<2> = X<2> + K<2,1> * err<1,1>
  221. *
  222. * err is a measurement of the difference in the measured state
  223. * and the estimate state. In our case, it is just the difference
  224. * between the two accelerometer measured angle and our estimated
  225. * angle.
  226. */
  227. angle += K_0 * angle_err;
  228. q_bias += K_1 * angle_err;

  229. return angle;
  230. }
干洗牛河 发表于 2011-11-14 20:38 | 显示全部楼层
#define dt                  0.0015//卡尔曼滤波采样频率

#define R_angle          0.69 //测量噪声的协方差(即是测量偏差)

#define Q_angle          0.0001//过程噪声的协方差

#define Q_gyro           0.0003 //过程噪声的协方差  过程噪声协方差为一个一行两列矩阵


请问上述那些值如何得出滴?:)
Periodic 发表于 2011-12-14 20:48 | 显示全部楼层
 楼主| wang1987 发表于 2011-12-21 17:32 | 显示全部楼层
4# Chaos_zc
谢谢兄弟了,卡尔曼这个东东要是完全理解,需要有很深的数学知识
半城夜 发表于 2015-6-4 11:40 | 显示全部楼层
请问各位大大
卡尔曼滤波里面

#define dt                  0.02//卡尔曼滤波采样频率

#define R_angle          0.5 //测量噪声的协方差(即是测量偏差)

#define Q_angle          0.0001//过程噪声的协方差

#define Q_gyro           0.0003 //过程噪声的协方差  
这几个值怎么确定?是都要调吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

87

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部