footPDR.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <stdint.h>
  6. #include "footPDR.h"
  7. #include "ekfPDR.h"
  8. #include "ukfPDR.h"
  9. #define ZUPT_threshold 0.81
  10. #define SIGMA 0.01
  11. #define SIGMA_V 0.01
  12. #define PI 3.14159265f
  13. #define RUN 1
  14. #define STAND 0
  15. extern void sen_step_to_host(uint8_t, uint16_t);
  16. //当地的重力加速度
  17. float g = 9.8179995f;
  18. float dt = 0.01f;
  19. float P[81], acc_n[3];
  20. float Temporary_array1[9], Temporary_array2[9];
  21. float K[27], P_prev[81], delta_x[9];
  22. float C[9], C_prev[9];
  23. float vel_n[3], pos_n[3];
  24. float last_pos_n[3];
  25. float pos_offset[3];
  26. int frame_index = 0;
  27. int stand_num = 0;
  28. float gyr_norm_window[10];
  29. float gyr_extreme[6];
  30. float gyr_mean[3];
  31. float num_peak;
  32. float acc_mean[3];
  33. float gyrBias[3];
  34. float last_gyr[3];
  35. float last_acc[3];
  36. float last_vel_n[3];
  37. float accSum;
  38. float accSize;
  39. int press_data[10];
  40. int ZUPT_STATUS;
  41. int press_index;
  42. int time_zupt;
  43. //last_stage:0 为 走路状态;
  44. //last_stage:1 为 静止状态
  45. int last_stage;
  46. uint8_t step_count;
  47. uint16_t step_distance;
  48. int step_time = 0;
  49. //UKF参数
  50. int UKF_L = 4;
  51. float UKF_alpha = 0.01f;
  52. float UKF_beta = 2.0f;
  53. float UKF_kappa = 0.0f;
  54. float gamma;
  55. float wm[9];
  56. float wc[9];
  57. float UKF_Q[4];
  58. float UKF_P[4][4];
  59. int UKF_iter;
  60. float mag_prev[3];
  61. float deltaC[9];
  62. float UKF_C[9];
  63. float UKF_roll;
  64. float UKF_pitch;
  65. float UKF_yaw;
  66. float EKF_roll;
  67. float EKF_pitch;
  68. float EKF_yaw;
  69. int canUKF = 0;
  70. int stand_zupt_count = 0;
  71. //重置磁航向,计算双脚的磁航向,以确定身体的正朝向
  72. float magSum_xyz[3];
  73. float accSum_xyz[3];
  74. float calHeading(float mag[3], float acc[3])
  75. {
  76. float hSqrt;
  77. float eSqrt;
  78. float h[3]; //东向
  79. h[0] = mag[1] * acc[2] - mag[2] * acc[1];
  80. h[1] = mag[2] * acc[0] - mag[0] * acc[2];
  81. h[2] = mag[0] * acc[1] - mag[1] * acc[0];
  82. hSqrt = 1/sqrt(h[0] * h[0] + h[1] * h[1] + h[2] * h[2]);
  83. for(int i = 0; i < 3; i++)
  84. {
  85. h[i] *= hSqrt;
  86. }
  87. float e[3]; //北向
  88. e[0] = acc[1] * h[2] - acc[2] * h[1];
  89. e[1] = acc[2] * h[0] - acc[0] * h[2];
  90. e[2] = acc[0] * h[1] - acc[1] * h[0];
  91. eSqrt = 1/sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
  92. for(int i = 0; i < 3; i++)
  93. {
  94. e[i] *= eSqrt;
  95. }
  96. return atan2(-h[1], e[1]);
  97. }
  98. void resetAttbyMag(float *C, float acc[3], float mag[3])
  99. {
  100. float pitch = asin(-acc[0]);
  101. float roll = atan2(acc[1], acc[2]);
  102. float pitch_sin = sin(pitch);
  103. float pitch_cos = cos(pitch);
  104. float roll_sin = sin(roll);
  105. float roll_cos = cos(roll);
  106. float mag_heading;
  107. C[0] = pitch_cos;
  108. C[1] = pitch_sin * roll_sin;
  109. C[2] = pitch_sin * roll_cos;
  110. C[3] = 0.0;
  111. C[4] = roll_cos;
  112. C[5] = -roll_sin;
  113. mag_heading = atan2(C[4] * mag[1] + C[5] * mag[2], C[0] * mag[0] + C[1] * mag[1] + C[2] * mag[2]);
  114. float yaw_sin = sin(mag_heading);
  115. float yaw_cos = cos(mag_heading);
  116. C[0] = pitch_cos * yaw_cos;
  117. C[1] = pitch_sin * roll_sin * yaw_cos - roll_cos * yaw_sin;
  118. C[2] = pitch_sin * roll_cos * yaw_cos + roll_sin * yaw_sin;
  119. C[3] = pitch_cos * yaw_sin;
  120. C[4] = pitch_sin * roll_sin * yaw_sin + roll_cos * yaw_cos;
  121. C[5] = pitch_sin * roll_cos * yaw_sin - roll_sin * yaw_cos;
  122. C[6] = acc[0];
  123. C[7] = acc[1];
  124. C[8] = acc[2];
  125. }
  126. void cal_step_data(void)
  127. {
  128. static int step_count_sum = 0;
  129. step_count = 1;
  130. step_count_sum += step_count;
  131. float step_length = sqrt((last_pos_n[0] - pos_n[0])*(last_pos_n[0] - pos_n[0]) + (last_pos_n[1] - pos_n[1])*(last_pos_n[1] - pos_n[1]));
  132. if (step_length > 5.0f)
  133. {
  134. step_length = 1.2f;
  135. }
  136. step_distance = (uint16_t)(step_length * 100.0f);
  137. //sen_step_to_host(step_count, step_distance);
  138. }
  139. uint8_t get_step_count(void)
  140. {
  141. return step_count;
  142. }
  143. uint16_t get_step_length(void)
  144. {
  145. return step_distance;
  146. }
  147. void Initialize(float *gyr, float *acc)
  148. {
  149. frame_index = 1;
  150. stand_num = 0;
  151. accSize = 1.0f;
  152. accSum = 0.0f;
  153. ZUPT_STATUS = 0;
  154. memset(last_pos_n, 0, 3 * sizeof(float));
  155. memset(pos_offset, 0, 3 * sizeof(float));
  156. memset(gyr_norm_window, 0, 10 * sizeof(float));
  157. memset(P, 0, 81 * sizeof(float));
  158. memset(acc_n, 0, 3 * sizeof(float));
  159. memset(vel_n, 0, 3 * sizeof(float));
  160. memset(pos_n, 0, 3 * sizeof(float));
  161. memset(Temporary_array1, 0, 9 * sizeof(float));
  162. memset(Temporary_array2, 0, 9 * sizeof(float));
  163. memset(K, 0, 27 * sizeof(float));
  164. memset(P_prev, 0, 81 * sizeof(float));
  165. memset(delta_x, 0, 9 * sizeof(float));
  166. memset(C, 0, 9 * sizeof(float));
  167. memset(Temporary_array1, 0, 9 * sizeof(float));
  168. memset(Temporary_array2, 0, 9 * sizeof(float));
  169. memset(press_data, 0, 10 * sizeof(int));
  170. init_attitude_matrix(C, acc, g);
  171. memcpy(C_prev, C, 9 * sizeof(float));
  172. }
  173. void attitude_matrix_update(float *C, float *Temporary_array1, float *Temporary_array2, float *gyr, float dt)
  174. {
  175. Temporary_array1[0] = 2.0f;
  176. Temporary_array1[1] = dt * gyr[2];
  177. Temporary_array1[2] = -dt * gyr[1];
  178. Temporary_array1[3] = -dt * gyr[2];
  179. Temporary_array1[4] = 2.0f;
  180. Temporary_array1[5] = dt * gyr[0];
  181. Temporary_array1[6] = dt * gyr[1];
  182. Temporary_array1[7] = -dt * gyr[0];
  183. Temporary_array1[8] = 2.0f;
  184. invert3x3(Temporary_array1, Temporary_array2);
  185. memset(Temporary_array1, 0, 9 * sizeof(float));
  186. Temporary_array1[0] = 2 * C[0] + C[1] * dt * gyr[2] - C[2] * dt * gyr[1];
  187. Temporary_array1[1] = 2 * C[1] - C[0] * dt * gyr[2] + C[2] * dt * gyr[0];
  188. Temporary_array1[2] = 2 * C[2] + C[0] * dt * gyr[1] - C[1] * dt * gyr[0];
  189. Temporary_array1[3] = 2 * C[3] + C[4] * dt * gyr[2] - C[5] * dt * gyr[1];
  190. Temporary_array1[4] = 2 * C[4] - C[3] * dt * gyr[2] + C[5] * dt * gyr[0];
  191. Temporary_array1[5] = 2 * C[5] + C[3] * dt * gyr[1] - C[4] * dt * gyr[0];
  192. Temporary_array1[6] = 2 * C[6] + C[7] * dt * gyr[2] - C[8] * dt * gyr[1];
  193. Temporary_array1[7] = 2 * C[7] - C[6] * dt * gyr[2] + C[8] * dt * gyr[0];
  194. Temporary_array1[8] = 2 * C[8] + C[6] * dt * gyr[1] - C[7] * dt * gyr[0];
  195. multiply3x3(Temporary_array1, Temporary_array2, C);
  196. }
  197. float max_window_val(float *window, int window_size)
  198. {
  199. float val = window[0];
  200. for (int i = 0; i < window_size; i++)
  201. {
  202. if (window[i] > val)
  203. val = window[i];
  204. }
  205. return val;
  206. }
  207. int max_window_int(int *window, int window_size)
  208. {
  209. int val = window[0];
  210. for (int i = 0; i < window_size; i++)
  211. {
  212. if (window[i] > val)
  213. val = window[i];
  214. }
  215. return val;
  216. }
  217. float min_window_val(float *window, int window_size)
  218. {
  219. float val = window[0];
  220. for (int i = 0; i < window_size; i++)
  221. {
  222. if (window[i] < val)
  223. val = window[i];
  224. }
  225. return val;
  226. }
  227. int min_window_int(int *window, int window_size)
  228. {
  229. int val = window[0];
  230. for (int i = 0; i < window_size; i++)
  231. {
  232. if (window[i] < val)
  233. val = window[i];
  234. }
  235. return val;
  236. }
  237. //press_tren 函数功能:提供走路过程中上升沿,下降沿
  238. //1 为上升 2 为 下降 0为不需要得状态
  239. int press_trend(int index, int *window, int window_size)
  240. {
  241. int i;
  242. int max_val = window[(index - 1) % window_size];
  243. int max_index = index;
  244. int min_val = max_val;
  245. int min_index = max_index;
  246. for (i = 1; i < window_size + 1; i++)
  247. {
  248. if (max_val < window[(index - i) % window_size])
  249. {
  250. max_index = index - i + 1;
  251. max_val = window[(index - i) % window_size];
  252. }
  253. if (min_val > window[(index - i) % window_size])
  254. {
  255. min_index = index - i + 1;
  256. min_val = window[(index - i) % window_size];
  257. }
  258. }
  259. if (max_index > min_index && max_val > min_val + 50000)
  260. {
  261. return 1;
  262. }
  263. if (max_index < min_index && max_val > min_val + 50000)
  264. {
  265. return 2;
  266. }
  267. return 0;
  268. }
  269. void dcm2angle(float *dcm, float *roll, float *pitch, float *yaw)
  270. {
  271. *yaw = atan2(dcm[3], dcm[0]);
  272. *pitch = asin(-dcm[6]);
  273. *roll = atan2(dcm[7], dcm[8]);
  274. }
  275. void quat2angleTest(float qin[4], float *roll, float *pitch, float *yaw)
  276. {
  277. //float r11 = qin[0] * qin[0] + qin[1] * qin[1] - qin[2] * qin[2] - qin[3] * qin[3];
  278. float r11 = 2.0f * (qin[1] * qin[2] + qin[0] * qin[3]);
  279. //float r21 = 2.0f * (qin[1] * qin[2] - qin[0] * qin[3]);
  280. float r12 = qin[0] * qin[0] + qin[1] * qin[1] - qin[2] * qin[2] - qin[3] * qin[3];
  281. float r21 = -2.0f * (qin[1] * qin[3] - qin[0] * qin[2]);
  282. float r31 = 2.0f * (qin[2] * qin[3] + qin[0] * qin[1]);
  283. float r32 = qin[0] * qin[0] - qin[1] * qin[1] - qin[2] * qin[2] + qin[3] * qin[3];
  284. if (r21 < -0.999999999f)
  285. r21 = -1.0f;
  286. else if (r21 > 0.999999999f)
  287. r21 = 1.0f;
  288. *roll = atan2(r11, r12);
  289. *pitch = asin(r21);
  290. *yaw = atan2(r31, r32);
  291. }
  292. void dcm2angleTest(float C[9], short att[3])
  293. {
  294. float yaw, pitch, roll;
  295. pitch = asin(-C[6]);
  296. if(C[6] > 0.999999f || C[6] < -0.999999f)
  297. {
  298. //当俯仰角为90度的时候,则假设翻滚角为0度
  299. yaw = atan2(-C[1], C[4]);
  300. roll = 0.0f;
  301. }
  302. else
  303. {
  304. yaw = atan2(C[3], C[0]);
  305. roll = atan2(C[7], C[8]);
  306. }
  307. att[0] = (short)(yaw * 10000.f); //yaw
  308. att[1] = (short)(pitch * 10000.f); //pitch
  309. att[2] = (short)(roll * 10000.f); //roll
  310. }
  311. void quat2dcm(float *qin, float *dcm)
  312. {
  313. float qin_norm = 1 / sqrt(qin[0] * qin[0] + qin[1] * qin[1] + qin[2] * qin[2] + qin[3] * qin[3]);
  314. for (int i = 0; i < 4; i++)
  315. qin[i] *= qin_norm;
  316. dcm[0] = qin[0] * qin[0] + qin[1] * qin[1] - qin[2] * qin[2] - qin[3] * qin[3];
  317. dcm[1] = 2.0f * (qin[1] * qin[2] + qin[0] * qin[3]);
  318. dcm[2] = 2.0f * (qin[1] * qin[3] - qin[0] * qin[2]);
  319. dcm[3] = 2.0f * (qin[1] * qin[2] - qin[0] * qin[3]);
  320. dcm[4] = qin[0] * qin[0] - qin[1] * qin[1] + qin[2] * qin[2] - qin[3] * qin[3];
  321. dcm[5] = 2.0f * (qin[2] * qin[3] + qin[0] * qin[1]);
  322. dcm[6] = 2.0f * (qin[1] * qin[3] + qin[0] * qin[2]);
  323. dcm[7] = 2.0f * (qin[2] * qin[3] - qin[0] * qin[1]);
  324. dcm[8] = qin[0] * qin[0] - qin[1] * qin[1] - qin[2] * qin[2] + qin[3] * qin[3];
  325. }
  326. void multiply3x3T(float *a, float *b, float* dst)
  327. {
  328. dst[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
  329. dst[1] = a[0] * b[3] + a[1] * b[4] + a[2] * b[5];
  330. dst[2] = a[0] * b[6] + a[1] * b[7] + a[2] * b[8];
  331. dst[3] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
  332. dst[4] = a[3] * b[3] + a[4] * b[4] + a[5] * b[5];
  333. dst[5] = a[3] * b[6] + a[4] * b[7] + a[5] * b[8];
  334. dst[6] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
  335. dst[7] = a[6] * b[3] + a[7] * b[4] + a[8] * b[5];
  336. dst[8] = a[6] * b[6] + a[7] * b[7] + a[8] * b[8];
  337. }
  338. void deltaAttMatrix(float C_prev[9], float C_now[9], float deltaC[9])
  339. {
  340. //detaC = C_prev'* C;
  341. deltaC[0] = C_now[0] * C_prev[0] + C_now[3] * C_prev[3] + C_now[6] * C_prev[6];
  342. deltaC[1] = C_now[1] * C_prev[0] + C_now[4] * C_prev[3] + C_now[7] * C_prev[6];
  343. deltaC[2] = C_now[2] * C_prev[0] + C_now[5] * C_prev[3] + C_now[8] * C_prev[6];
  344. deltaC[3] = C_now[0] * C_prev[1] + C_now[3] * C_prev[4] + C_now[6] * C_prev[7];
  345. deltaC[4] = C_now[1] * C_prev[1] + C_now[4] * C_prev[4] + C_now[7] * C_prev[7];
  346. deltaC[5] = C_now[2] * C_prev[1] + C_now[5] * C_prev[4] + C_now[8] * C_prev[7];
  347. deltaC[6] = C_now[0] * C_prev[2] + C_now[3] * C_prev[5] + C_now[6] * C_prev[8];
  348. deltaC[7] = C_now[1] * C_prev[2] + C_now[4] * C_prev[5] + C_now[7] * C_prev[8];
  349. deltaC[8] = C_now[2] * C_prev[2] + C_now[5] * C_prev[5] + C_now[8] * C_prev[8];
  350. }
  351. void resetUKF(float *UKF_Q, float UKF_P[4][4], float *mag_prev, float *mag, float *UKF_C, float *C)
  352. {
  353. memset(UKF_Q, 0, 4 * sizeof(float));
  354. UKF_Q[0] = 1.0f;
  355. memcpy(mag_prev, mag, 3 * sizeof(float));
  356. memcpy(UKF_C, C, 9 * sizeof(float));
  357. for (int i = 0; i < 4; i++)
  358. for (int j = 0; j < 4; j++)
  359. {
  360. UKF_P[i][j] = 0.0f;
  361. }
  362. for (int i = 0; i < 4; i++)
  363. {
  364. UKF_P[i][i] = 0.0000001f;
  365. }
  366. }
  367. //利用陀螺仪的双极端盘判断是否在稳定的范围
  368. int isStandCon(float gyr_extreme[6])
  369. {
  370. if(gyr_extreme[1] - gyr_extreme[0] < 0.008f && gyr_extreme[3] - gyr_extreme[2] < 0.008f && gyr_extreme[5] - gyr_extreme[4] < 0.008f)
  371. {
  372. return 1;
  373. }
  374. return 0;
  375. }
  376. unsigned char footPDR(int num, float *gyr, float *acc, float *mag ,int press, int16_t* pos_res, int16_t* att, int16_t* zupt)
  377. {
  378. unsigned char movement_e = 0;
  379. for (int i = 0; i < 3; i++)
  380. {
  381. accSum_xyz[i] += acc[i];
  382. magSum_xyz[i] += mag[i];
  383. gyr[i] *= (PI / 180);
  384. acc[i] *= g;
  385. }
  386. if (num_peak == 0)
  387. {
  388. for (int i = 0; i < 3; i++)
  389. {
  390. gyr_extreme[2 * i] = gyr[i];
  391. gyr_extreme[2 * i + 1] = gyr[i];
  392. }
  393. }
  394. for (int i = 0; i < 3; i++)
  395. {
  396. if (gyr[i] < gyr_extreme[2 * i])
  397. {
  398. gyr_extreme[2 * i] = gyr[i];
  399. }
  400. if (gyr[i] > gyr_extreme[2 * i + 1])
  401. {
  402. gyr_extreme[2 * i + 1] = gyr[i];
  403. }
  404. }
  405. accSum += sqrt(acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]);
  406. for (int i = 0; i < 3; i++)
  407. {
  408. gyr_mean[i] += gyr[i];
  409. }
  410. num_peak++;
  411. //在线估计陀螺仪的零偏, 6050的零偏偏大
  412. if (num_peak == 500)
  413. {
  414. if (isStandCon(gyr_extreme))
  415. {
  416. float accSqrt = 1/sqrt(accSum_xyz[0] * accSum_xyz[0] + accSum_xyz[1] * accSum_xyz[1] + accSum_xyz[2] * accSum_xyz[2]);
  417. float magSqrt = 1/sqrt(magSum_xyz[0] * magSum_xyz[0] + magSum_xyz[1] * magSum_xyz[1] + magSum_xyz[2] * magSum_xyz[2]);
  418. for(int i = 0; i < 3; i++)
  419. {
  420. gyrBias[i] = gyr_mean[i] * 0.002f;
  421. accSum_xyz[i] *= accSqrt;
  422. magSum_xyz[i] *= magSqrt;
  423. }
  424. resetAttbyMag(C, accSum_xyz, magSum_xyz);
  425. resetUKF(UKF_Q, UKF_P, mag_prev, magSum_xyz, UKF_C, C);
  426. memset(P, 0, 81 * sizeof(float));
  427. canUKF = 1;
  428. gpio_mt_run(50);
  429. }
  430. num_peak = 0;
  431. accSum = 0.0f;
  432. memset(gyr_mean, 0, 3 * sizeof(float));
  433. memset(accSum_xyz, 0, 3 * sizeof(float));
  434. memset(magSum_xyz, 0, 3 * sizeof(float));
  435. }
  436. gyr[0] -= gyrBias[0];
  437. gyr[1] -= gyrBias[1];
  438. gyr[2] -= gyrBias[2];
  439. float gyr_norm_xyz = sqrt(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
  440. //需要一个滑动窗口来判断脚步是否在地上
  441. frame_index++;
  442. //下面为惯导解算
  443. if (num == 1 || frame_index < 0)
  444. {
  445. Initialize(gyr, acc);
  446. UKF_para(UKF_L, UKF_alpha, UKF_beta, UKF_kappa, &gamma, wm, wc);
  447. return movement_e;
  448. }
  449. //惯导解算: 姿态矩阵更新
  450. attitude_matrix_update(C, Temporary_array1, Temporary_array2, gyr, dt);
  451. //惯导解算: 将IMU坐标系的加速度转换到“导航坐标系”下
  452. multiply3x1(C, acc, acc_n);
  453. //惯导解算: 更新IMU速度
  454. vel_n[0] = vel_n[0] + acc_n[0] * dt;
  455. vel_n[1] = vel_n[1] + acc_n[1] * dt;
  456. vel_n[2] = vel_n[2] + (acc_n[2] - g) * dt;
  457. //惯导解算: 更新IMU位置
  458. pos_n[0] = pos_n[0] + vel_n[0] * dt;
  459. pos_n[1] = pos_n[1] + vel_n[1] * dt;
  460. pos_n[2] = pos_n[2] + vel_n[2] * dt;
  461. //ekf步骤: 状态协方差矩阵预测更新
  462. //P = F*P*F' + Q;
  463. State_covariance_matrix_update(P, acc_n, dt);
  464. int window_index = (frame_index - 1) % 10;
  465. float gyr_norm_xz = sqrt(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
  466. gyr_norm_window[window_index] = gyr_norm_xz;
  467. press_data[window_index] = press;
  468. //当press_trend函数返回是1,判断为踩地上
  469. // 返回2 的时候,判断为离地
  470. // 返回0 的时候,需要保持状态
  471. int press_trend_val = press_trend(frame_index, press_data, 10);
  472. if (press_trend_val == 1)
  473. {
  474. ZUPT_STATUS = 1;
  475. }
  476. else if (press_trend_val == 2)
  477. {
  478. ZUPT_STATUS = 2;
  479. }
  480. //RUN_ZUPT mean detect on floor when running
  481. int RUN_ZUPT = 0;
  482. if ((frame_index > 10 && ZUPT_STATUS == 1))
  483. RUN_ZUPT = 1;
  484. //STAND_ZUPT mean detect on floor when no any moving
  485. int STAND_ZUPT = 0;
  486. if ((frame_index > 15 && gyr_norm_window[window_index] < 0.35f && fabs(min_window_val(gyr_norm_window, 10) - max_window_val(gyr_norm_window, 10)) < 0.1f))
  487. STAND_ZUPT = 1;
  488. //zupt
  489. if ((STAND_ZUPT || RUN_ZUPT))
  490. {
  491. //计算一步的距离及步数+1
  492. //做一个计算时间时间,防止非正常走路的情况出来
  493. if (last_stage == 2 && frame_index - step_time > 30)
  494. {
  495. cal_step_data();
  496. step_time = frame_index;
  497. }
  498. stand_num = stand_num + 1;
  499. time_zupt++;
  500. //ekf步骤: 计算卡尔曼滤波增益
  501. //K = P*H'/(H*P*H' + R);
  502. Kalfman_gain(P, Temporary_array1, Temporary_array2, K);
  503. //ekf步骤: 观测误差更新
  504. //delta_x = K * [vel_n(:,i);];
  505. multiply9x3(K, vel_n, delta_x);
  506. //ekf步骤: 状态协方差矩阵观测更新
  507. State_covariance_matrix_corr(P, P_prev, K);
  508. //这里先从设置 delta_x(3) = atan2(C(2,1),C(1,1));
  509. //意味着每一步的参考方向是IMU X轴方向
  510. // delta_x[2] = atan2(C[3], C[0]);
  511. // theta = -1.7801 + atan2(C[3], C[0]);
  512. // theta = 0.0f;
  513. //delta_x[2] = 0.0f;
  514. //修正姿态矩阵
  515. Att_matrix_corr(C, C_prev, Temporary_array1, Temporary_array2, delta_x);
  516. //修正位置
  517. pos_n_corr(pos_n, delta_x);
  518. //修正速度
  519. vel_n_corr(vel_n, delta_x);
  520. last_pos_n[0] = pos_n[0];
  521. last_pos_n[1] = pos_n[1];
  522. last_pos_n[2] = pos_n[2];
  523. last_stage = 1;
  524. *zupt = 1;
  525. }
  526. else
  527. {
  528. stand_num = 0;
  529. *zupt = 0;
  530. }
  531. //融合磁力计数据
  532. //
  533. float mag_norm = sqrt(mag[0] * mag[0] + mag[1] * mag[1] + mag[2] * mag[2]);
  534. if(STAND_ZUPT)
  535. {
  536. stand_zupt_count ++;
  537. }
  538. else
  539. {
  540. stand_zupt_count = 0;
  541. }
  542. if(stand_zupt_count == 100 &&(mag_norm < 1.2f && mag_norm > 0.8f))
  543. {
  544. mag[0] /= mag_norm;
  545. mag[1] /= mag_norm;
  546. mag[2] /= mag_norm;
  547. resetUKF(UKF_Q, UKF_P, mag_prev, mag, UKF_C, C);
  548. memset(P, 0, 81 * sizeof(float));
  549. stand_zupt_count = 0;
  550. }
  551. if (canUKF && (mag_norm < 1.2f && mag_norm > 0.8f))
  552. {
  553. mag[0] /= mag_norm;
  554. mag[1] /= mag_norm;
  555. mag[2] /= mag_norm;
  556. float magEst[3];
  557. deltaAttMatrix(UKF_C, C, deltaC);
  558. multiply3x1(deltaC, mag, magEst);
  559. UKF_quat(UKF_Q, UKF_P, gyr, mag_prev, magEst, gamma, wm, wc, UKF_L, dt);
  560. //dcm=C_tmp * quat2dcm(X') * C_tmp' ;
  561. float dcm[9];
  562. quat2dcm(UKF_Q, dcm);
  563. multiply3x3(UKF_C, dcm, deltaC);
  564. multiply3x3T(deltaC, UKF_C, dcm);
  565. dcm2angle(dcm, &EKF_roll, &EKF_pitch, &EKF_yaw);
  566. //float ukf_norm = 1 / sqrt(UKF_Q[0] * UKF_Q[0] + UKF_Q[1] * UKF_Q[1] + UKF_Q[2] * UKF_Q[2] + UKF_Q[3] * UKF_Q[3]);
  567. //UKF_Q[0] *= ukf_norm;
  568. //UKF_Q[1] *= ukf_norm;
  569. //UKF_Q[2] *= ukf_norm;
  570. //UKF_Q[3] *= ukf_norm;
  571. //quat2angle(UKF_Q, UKF_yaw, UKF_pitch, UKF_roll);
  572. Kalfman_gain_angle(P, Temporary_array1, Temporary_array2, K);
  573. State_covariance_matrix_corr_angle(P, P_prev, K);
  574. float angleErr[3];
  575. angleErr[0] = 0.1f*( EKF_roll);
  576. angleErr[1] = 0.1f*( EKF_pitch);
  577. angleErr[2] = 0.1f*( EKF_yaw);
  578. multiply9x3(K, angleErr, delta_x);
  579. Att_matrix_corr(C, C_prev, Temporary_array1, Temporary_array2, delta_x);
  580. //修正位置
  581. pos_n_corr(pos_n, delta_x);
  582. //修正速度
  583. vel_n_corr(vel_n, delta_x);
  584. }
  585. //状态协方差矩阵保持正交性,以防出现退化
  586. State_covariance_matrix_orthogonalization(P);
  587. memcpy(last_vel_n, vel_n, 3 * sizeof(float));
  588. pos_offset[0] = pos_n[0] - last_pos_n[0];
  589. pos_offset[1] = pos_n[1] - last_pos_n[1];
  590. pos_offset[2] = pos_n[2] - last_pos_n[2];
  591. dcm2angleTest(C, att); //航向角,俯仰角, 翻滚角(z y x)
  592. // att[0] = (short)(atan2(C[3], C[0]) * 10000.f); //yaw
  593. // att[1] = (short)(asin(-C[6]) * 10000.f); //pitch
  594. // att[2] = (short)(atan2(C[7], C[8]) * 10000.f); //roll
  595. // att[0] = (short)(1 ); //yaw
  596. // att[1] = (short)(2 ); //pitch
  597. // att[2] = (short)(3 ); //roll
  598. pos_res[0] = (short) (pos_offset[0] * 100.0f);
  599. pos_res[1] = (short) (pos_offset[1] * 100.0f);
  600. pos_res[2] = (short) (pos_offset[2] * 100.0f);
  601. if ((pos_res[0] * pos_res[0] + pos_res[1] * pos_res[1] + pos_res[2] * pos_res[2]) > 10)
  602. {
  603. last_stage = 2;
  604. }
  605. return movement_e;
  606. }