footPDR.c 23 KB

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