footPDR.c 25 KB

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