footPDR_prev.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #include "footPDR_prev.h"
  2. //当地的重力加速度
  3. static float g = 9.8179995f;
  4. static float dt = 0.014f;
  5. static float P[81], acc_n[3];
  6. static float Temporary_array1[9], Temporary_array2[9];
  7. static float K[27], P_prev[81], delta_x[9];
  8. static float C[9], C_prev[9];
  9. static float vel_n[3], pos_n[3];
  10. static float last_pos_n[3];
  11. static float pos_offset[3];
  12. static uint32_t frame_index = 0;
  13. static int stand_num = 0;
  14. static float gyr_extreme[6];
  15. static float gyr_mean[3];
  16. static float num_peak;
  17. static float gyrBias[3];
  18. static int SAVEFLASH = 1;
  19. //last_stage:0 为 走路状态;
  20. //last_stage:1 为 静止状态
  21. static float measure_degree = 1.0f;
  22. static float heading_buff[20];
  23. static float zupt_heading;
  24. static int step_index = 0;
  25. void Initialize_prev(float *gyr, float *acc)
  26. {
  27. frame_index = 1;
  28. stand_num = 0;
  29. memset(last_pos_n, 0, 3 * sizeof(float));
  30. memset(pos_offset, 0, 3 * sizeof(float));
  31. memset(P, 0, 81 * sizeof(float));
  32. memset(acc_n, 0, 3 * sizeof(float));
  33. memset(vel_n, 0, 3 * sizeof(float));
  34. memset(pos_n, 0, 3 * sizeof(float));
  35. memset(Temporary_array1, 0, 9 * sizeof(float));
  36. memset(Temporary_array2, 0, 9 * sizeof(float));
  37. memset(K, 0, 27 * sizeof(float));
  38. memset(P_prev, 0, 81 * sizeof(float));
  39. memset(delta_x, 0, 9 * sizeof(float));
  40. memset(C, 0, 9 * sizeof(float));
  41. memset(Temporary_array1, 0, 9 * sizeof(float));
  42. memset(Temporary_array2, 0, 9 * sizeof(float));
  43. init_attitude_matrix(C, acc, g);
  44. memcpy(C_prev, C, 9 * sizeof(float));
  45. // memcpy(gyrBias, (uint32_t *)FLASH_ADD, 3 * sizeof(float));
  46. }
  47. unsigned char footPDR_prev(uint32_t num, float *gyr, float *acc, int16_t vel_zero, int32_t* pos_res, int16_t* att)
  48. {
  49. unsigned char movement_e = 0;
  50. for (int i = 0; i < 3; i++)
  51. {
  52. gyr[i] *= (PI / 180);
  53. acc[i] *= g;
  54. }
  55. if (num_peak == 0)
  56. {
  57. for (int i = 0; i < 3; i++)
  58. {
  59. gyr_extreme[2 * i] = gyr[i];
  60. gyr_extreme[2 * i + 1] = gyr[i];
  61. }
  62. }
  63. for (int i = 0; i < 3; i++)
  64. {
  65. if (gyr[i] < gyr_extreme[2 * i])
  66. {
  67. gyr_extreme[2 * i] = gyr[i];
  68. }
  69. if (gyr[i] > gyr_extreme[2 * i + 1])
  70. {
  71. gyr_extreme[2 * i + 1] = gyr[i];
  72. }
  73. }
  74. for (int i = 0; i < 3; i++)
  75. {
  76. gyr_mean[i] += gyr[i];
  77. }
  78. num_peak++;
  79. //在线估计陀螺仪的零偏, 6050的零偏偏大
  80. if (num_peak == 300)
  81. {
  82. if (isStandCon(gyr_extreme))
  83. {
  84. if(SAVEFLASH)
  85. {
  86. //识别每一次游戏模式下,静止状态的陀螺仪令零偏
  87. for(int i = 0; i < 3; i++)
  88. {
  89. gyrBias[i] = gyr_mean[i] * 0.0033f;
  90. }
  91. DEBUG_LOG("gyrBias has cor!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
  92. }
  93. }
  94. num_peak = 0;
  95. memset(gyr_mean, 0, 3 * sizeof(float));
  96. }
  97. gyr[0] -= gyrBias[0];
  98. gyr[1] -= gyrBias[1];
  99. gyr[2] -= gyrBias[2];
  100. float gyr_norm_xyz = sqrt(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
  101. float acc_norm_xyz = sqrt(acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]);
  102. //需要一个滑动窗口来判断脚步是否在地上
  103. frame_index++;
  104. //下面为惯导解算
  105. if (num == 0|| frame_index == 0)
  106. {
  107. Initialize_prev(gyr, acc);
  108. gpio_mt_run(500);
  109. return movement_e;
  110. }
  111. //惯导解算: 姿态矩阵更新
  112. attitude_matrix_update(C, Temporary_array1, Temporary_array2, gyr, dt);
  113. //惯导解算: 将IMU坐标系的加速度转换到“导航坐标系”下
  114. multiply3x1(C, acc, acc_n);
  115. //惯导解算: 更新IMU速度
  116. vel_n[0] = vel_n[0] + acc_n[0] * dt;
  117. vel_n[1] = vel_n[1] + acc_n[1] * dt;
  118. vel_n[2] = vel_n[2] + (acc_n[2] - g) * dt;
  119. //惯导解算: 更新IMU位置
  120. pos_n[0] = pos_n[0] + vel_n[0] * dt;
  121. pos_n[1] = pos_n[1] + vel_n[1] * dt;
  122. pos_n[2] = pos_n[2] + vel_n[2] * dt;
  123. //ekf步骤: 状态协方差矩阵预测更新
  124. //P = F*P*F' + Q;
  125. State_covariance_matrix_update(P, acc_n, dt);
  126. //zupt
  127. if (vel_zero == 1)
  128. {
  129. //ekf步骤: 计算卡尔曼滤波增益
  130. //K = P*H'/(H*P*H' + R);
  131. calKafmanGain9x4(K, P);
  132. //ekf步骤: 观测误差更新
  133. //delta_x = K * [vel_n(:,i);];
  134. float now_heading = atan2(C[3], C[0]);
  135. float measure[4];
  136. //计算理想的角度
  137. memset(measure, 0, 4 *sizeof(float));
  138. measure[0] = calDeltaHeading(step_index, now_heading, heading_buff);
  139. if(measure[0] > 10.0f)
  140. {
  141. measure[0] = 0;
  142. }
  143. measure[1] = vel_n[0];
  144. measure[2] = vel_n[1];
  145. measure[3] = vel_n[2];
  146. calDeltaX9x4(K, measure, delta_x);
  147. //ekf步骤: 状态协方差矩阵观测更新
  148. calStateCov9x4(P, K);
  149. //这里先从设置 delta_x(3) = atan2(C(2,1),C(1,1));
  150. //意味着每一步的参考方向是IMU X轴方向
  151. // delta_x[2] = atan2(C[3], C[0]);
  152. // theta = -1.7801 + atan2(C[3], C[0]);
  153. // theta = 0.0f;
  154. //修正姿态矩阵
  155. Att_matrix_corr(C, C_prev, Temporary_array1, Temporary_array2, delta_x);
  156. //修正位置
  157. pos_n_corr(pos_n, delta_x);
  158. //修正速度
  159. vel_n_corr(vel_n, delta_x);
  160. //vel_n[2] = 0.8f * vel_n[2];
  161. if(vel_zero == 1)
  162. {
  163. zupt_heading = now_heading;
  164. stand_num ++;
  165. }
  166. memcpy(last_pos_n, pos_n, 3 * sizeof(float));
  167. }
  168. else
  169. {
  170. //存放一步内记录的mag数据以及heading数据
  171. if(stand_num != 0)
  172. {
  173. heading_buff[step_index % 20] = zupt_heading;
  174. step_index ++;
  175. }
  176. stand_num = 0;
  177. measure_degree = 1.0f;
  178. }
  179. //状态协方差矩阵保持正交性,以防出现退化
  180. State_covariance_matrix_orthogonalization(P);
  181. pos_offset[0] = pos_offset[0] + pos_n[0] - last_pos_n[0];
  182. pos_offset[1] = pos_offset[1] + pos_n[1] - last_pos_n[1];
  183. pos_offset[2] = pos_offset[2] + pos_n[2] - last_pos_n[2];
  184. memcpy(last_pos_n, pos_n, 3 * sizeof(float));
  185. dcm2angleTest(C, att); //航向角,俯仰角, 翻滚角(z y x)
  186. att[1] = (int16_t)(vel_n[0] * 1000.0f);
  187. att[2] = (int16_t)(vel_n[1] * 1000.0f);
  188. pos_res[0] = (int32_t) (pos_offset[0] * 100.0f);
  189. pos_res[1] = (int32_t) (pos_offset[1] * 100.0f);
  190. pos_res[2] = (int32_t) (pos_offset[2] * 100.0f);
  191. return movement_e;
  192. }