detect_step_by_acc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. #include "detect_step_by_acc.h"
  2. static int ACC_WINDOW_SIZE=20;
  3. static int16_t acc_y_buff[20];
  4. static int16_t acc_z_buff[20];
  5. static int16_t acc_x_buff[20];
  6. static int32_t acc_xyz_buff[20];
  7. //static int acc_y_wait;
  8. //static int acc_z_wait;
  9. //static int acc_x_wait;
  10. static int acc_y_status = 1;
  11. static int acc_z_status = 1;
  12. static int acc_x_status = 1;
  13. //static int last_zupt;
  14. static int last_acc_x_status;
  15. static int last_acc_y_status;
  16. static int last_acc_z_status;
  17. static int x_raised;
  18. static int y_raised;
  19. static int z_raised;
  20. static int x_hollow;
  21. static int y_hollow;
  22. static int z_hollow;
  23. static int zero_x_wait;
  24. static int zero_y_wait;
  25. static int zero_z_wait;
  26. //static int can_detect_zupt = 1;
  27. //static int stop_out_zupt = 0;
  28. //static int acc_diff_wait_count = 0;
  29. static int last_time_stamp = 0;
  30. //static int PDR_step_count = 0;
  31. static int16_t max_z_unzero = 2048;
  32. static int16_t min_z_unzero = 2048;
  33. void detect_raised_hollow(int16_t *acc, int length, int16_t max_val_thresh, int16_t min_val_thresh, int16_t distance, int *raised, int *hollow)
  34. {
  35. //本函数用来检测加速度曲线的凹凸标志
  36. //1、遍历加速度窗口的最大值及最小值
  37. int start_index = ACC_WINDOW_SIZE - length;
  38. if(start_index < 0)
  39. {
  40. return;
  41. }
  42. int16_t max_val = acc[ACC_WINDOW_SIZE - length / 2];
  43. int16_t min_val = acc[ACC_WINDOW_SIZE - length / 2];
  44. for(int i = ACC_WINDOW_SIZE - length / 2; i < ACC_WINDOW_SIZE; i++)
  45. {
  46. if(max_val < acc[i])
  47. {
  48. max_val = acc[i];
  49. }
  50. if(min_val > acc[i])
  51. {
  52. min_val = acc[i];
  53. }
  54. }
  55. //检测到平稳信号,需要重新检测凹凸性
  56. if(max_val - min_val < 410) //0.2*2048
  57. {
  58. *raised = 0;
  59. *hollow = 0;
  60. return;
  61. }
  62. for(int i = 0; i < ACC_WINDOW_SIZE - length / 2; i++)
  63. {
  64. if(max_val < acc[i])
  65. {
  66. max_val = acc[i];
  67. }
  68. if(min_val > acc[i])
  69. {
  70. min_val = acc[i];
  71. }
  72. }
  73. //检测凹凸性
  74. if(max_val - acc[0] > distance && max_val - acc[ACC_WINDOW_SIZE-1] > distance && *raised == 0 && max_val > max_val_thresh)
  75. {
  76. *raised = 1;
  77. }
  78. if(acc[0] - min_val > distance && acc[ACC_WINDOW_SIZE - 1] - min_val > distance && *hollow == 0 && min_val < min_val_thresh)
  79. {
  80. *hollow = 1;
  81. }
  82. }
  83. //求取拐点
  84. int detect_turn_line(int16_t *acc, int length, int tag)
  85. {
  86. int start_index = ACC_WINDOW_SIZE - length;
  87. int16_t min_val = acc[start_index];
  88. int min_index = start_index;
  89. int16_t max_val = acc[start_index];
  90. int max_index = start_index;
  91. for(int i = 8; i < ACC_WINDOW_SIZE; i ++)
  92. {
  93. if(min_val > acc[i])
  94. {
  95. min_val = acc[i];
  96. min_index = i;
  97. }
  98. if(max_val < acc[i])
  99. {
  100. max_val = acc[i];
  101. max_index = i;
  102. }
  103. }
  104. int16_t min_val_5 = acc[ACC_WINDOW_SIZE - 5];
  105. int16_t max_val_5 = acc[ACC_WINDOW_SIZE - 5];
  106. for(int i = ACC_WINDOW_SIZE - 5; i < ACC_WINDOW_SIZE; i++ )
  107. {
  108. if(min_val_5 > acc[i])
  109. {
  110. min_val_5 = acc[i];
  111. }
  112. if(max_val_5 < acc[i])
  113. {
  114. max_val_5 = acc[i];
  115. }
  116. }
  117. if(max_val - min_val > 1024 && max_val_5 - min_val_5 < 410)
  118. {
  119. if(tag == 1)
  120. {
  121. if(max_index < min_index)
  122. {
  123. return 1;
  124. }
  125. else
  126. {
  127. return 0;
  128. }
  129. }
  130. return 1;
  131. }
  132. return 0;
  133. }
  134. //求取平稳信号
  135. int station_signal(int16_t *acc, int length)
  136. {
  137. int start_index = ACC_WINDOW_SIZE - length;
  138. int16_t max_val = acc[start_index];
  139. int16_t min_val = acc[start_index];
  140. for(int i = start_index; i < ACC_WINDOW_SIZE; i++)
  141. {
  142. if(max_val < acc[i])
  143. {
  144. max_val = acc[i];
  145. }
  146. if(min_val > acc[i])
  147. {
  148. min_val = acc[i];
  149. }
  150. }
  151. if(max_val - min_val < 307)
  152. {
  153. return 1;
  154. }
  155. return 0;
  156. }
  157. //剧烈信号探测拐点
  158. int severe_turn_point_z(int16_t *acc, int length)
  159. {
  160. int16_t max_val = acc[0];
  161. int16_t min_val = acc[0];
  162. int16_t min_temp = acc[0];
  163. int16_t max_distance = max_val - min_val;
  164. for(int i = 1 ; i < ACC_WINDOW_SIZE; i++)
  165. {
  166. int16_t distance_tmp = acc[i-1] - acc[i];
  167. if(i > 1 && distance_tmp < (acc[i-2] - acc[i]))
  168. distance_tmp = (acc[i-2] - acc[i]);
  169. if(i > 2 && distance_tmp < (acc[i-3] - acc[i]))
  170. distance_tmp = (acc[i-3] - acc[i]);
  171. if(i > 3 && distance_tmp < (acc[i-4] - acc[i]))
  172. distance_tmp = (acc[i-4] - acc[i]);
  173. if(i > 4 && distance_tmp < (acc[i-5] - acc[i]))
  174. distance_tmp = (acc[i-5] - acc[i]);
  175. if(max_distance < distance_tmp)
  176. {
  177. max_distance = distance_tmp;
  178. }
  179. if(min_temp > acc[i])
  180. {
  181. min_temp = acc[i];
  182. }
  183. }
  184. max_val = acc[ACC_WINDOW_SIZE-5];
  185. min_val = acc[ACC_WINDOW_SIZE-5];
  186. for(int i = ACC_WINDOW_SIZE - 5; i< ACC_WINDOW_SIZE; i++)
  187. {
  188. if(max_val < acc[i])
  189. {
  190. max_val = acc[i];
  191. }
  192. if(min_val > acc[i])
  193. {
  194. min_val = acc[i];
  195. }
  196. }
  197. int16_t min_distance = max_val - min_val;
  198. if(max_distance > 3072 && min_distance < 614 && min_temp > 1024)
  199. {
  200. return 1;
  201. }
  202. return 0;
  203. }
  204. int severe_turn_point(int16_t *acc, int length)
  205. {
  206. int16_t max_val = acc[0];
  207. int16_t min_val = acc[0];
  208. int16_t max_distance = max_val - min_val;
  209. for(int i = 1 ; i < ACC_WINDOW_SIZE; i++)
  210. {
  211. int16_t distance_tmp = acc[i] - acc[i-1];
  212. if(i > 1 && distance_tmp < fabsf(acc[i] - acc[i-2]))
  213. distance_tmp = fabsf(acc[i] - acc[i-2]);
  214. if(i > 2 && distance_tmp < fabsf(acc[i] - acc[i-3]))
  215. distance_tmp = fabsf(acc[i] - acc[i-3]);
  216. if(i > 3 && distance_tmp < fabsf(acc[i] - acc[i-4]))
  217. distance_tmp = fabsf(acc[i] - acc[i-4]);
  218. if(i > 4 && distance_tmp < fabsf(acc[i] - acc[i-5]))
  219. distance_tmp = fabsf(acc[i] - acc[i-5]);
  220. if(max_distance < distance_tmp)
  221. {
  222. max_distance = distance_tmp;
  223. }
  224. }
  225. max_val = acc[ACC_WINDOW_SIZE-5];
  226. min_val = acc[ACC_WINDOW_SIZE-5];
  227. for(int i = ACC_WINDOW_SIZE - 5; i< ACC_WINDOW_SIZE; i++)
  228. {
  229. if(max_val < acc[i])
  230. {
  231. max_val = acc[i];
  232. }
  233. if(min_val > acc[i])
  234. {
  235. min_val = acc[i];
  236. }
  237. }
  238. int16_t min_distance = max_val - min_val;
  239. if(max_distance > 2662 && min_distance < 615)
  240. {
  241. return 1;
  242. }
  243. return 0;
  244. }
  245. int32_t var_acc(int16_t *acc, int length)
  246. {
  247. if(length < 10)
  248. {
  249. return 0;
  250. }
  251. int32_t mean_x = 0;
  252. int32_t sum_x = 0;
  253. for(int i = length - 10; i < length; i++)
  254. {
  255. sum_x += acc[i];
  256. }
  257. mean_x = sum_x / 10;
  258. sum_x = 0;
  259. for(int i = length - 10; i < length; i++)
  260. {
  261. sum_x += ((acc[i]- mean_x) * (acc[i]- mean_x));
  262. }
  263. return sum_x / 10 ;
  264. }
  265. //寻找窗口的最小值
  266. int16_t min_window(int16_t *acc, int length)
  267. {
  268. int start_index = ACC_WINDOW_SIZE - length;
  269. int16_t min_val = acc[start_index];
  270. for(int i = 0; i < ACC_WINDOW_SIZE; i++)
  271. {
  272. if(acc[i] < min_val)
  273. {
  274. min_val = acc[i];
  275. }
  276. }
  277. return min_val;
  278. }
  279. //寻找窗口的最大值
  280. int16_t max_window(int16_t *acc, int length)
  281. {
  282. int start_index = ACC_WINDOW_SIZE - length;
  283. int16_t max_val = acc[start_index];
  284. for(int i = 0; i < ACC_WINDOW_SIZE; i++)
  285. {
  286. if(acc[i] > max_val)
  287. {
  288. max_val = acc[i];
  289. }
  290. }
  291. return max_val;
  292. }
  293. //三轴稳定判断
  294. int station_window_xyz(int32_t *acc)
  295. {
  296. int32_t max_val = acc[0];
  297. int32_t min_val = acc[0];
  298. for(int i = 0; i < ACC_WINDOW_SIZE; i++)
  299. {
  300. if(acc[i] > max_val)
  301. {
  302. max_val = acc[i];
  303. }
  304. if(acc[i] < min_val)
  305. {
  306. min_val = acc[i];
  307. }
  308. }
  309. if(max_val - min_val < 419430)
  310. {
  311. return 1;
  312. }
  313. return 0;
  314. }
  315. void detect_step_by_acc(int16_t *acc)
  316. {
  317. //缓存加速度的滑动窗口
  318. static uint32_t time_stamp;
  319. memcpy(acc_x_buff, acc_x_buff + 1, (ACC_WINDOW_SIZE - 1) * sizeof(int16_t));
  320. acc_x_buff[(ACC_WINDOW_SIZE - 1)] = acc[0];
  321. memcpy(acc_y_buff, acc_y_buff + 1, (ACC_WINDOW_SIZE - 1) * sizeof(int16_t));
  322. acc_y_buff[(ACC_WINDOW_SIZE - 1)] = acc[1];
  323. memcpy(acc_z_buff, acc_z_buff + 1, (ACC_WINDOW_SIZE - 1) * sizeof(int16_t));
  324. acc_z_buff[(ACC_WINDOW_SIZE - 1)] = acc[2];
  325. memcpy(acc_xyz_buff, acc_xyz_buff + 1, (ACC_WINDOW_SIZE - 1) * sizeof(int32_t));
  326. acc_xyz_buff[(ACC_WINDOW_SIZE - 1)] = acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2];
  327. //检测拐点
  328. //detect_raised_hollow(float *acc, int length, float max_val_thresh, float min_val_thresh, float distance, int *raised, int *hollow)
  329. detect_raised_hollow(acc_x_buff, ACC_WINDOW_SIZE, 1434, -1434, 1024, &x_raised, &x_hollow);
  330. detect_raised_hollow(acc_y_buff, ACC_WINDOW_SIZE, 1434, -1434, 1024, &y_raised, &y_hollow);
  331. detect_raised_hollow(acc_z_buff, ACC_WINDOW_SIZE, 2458, 1638, 820, &z_raised, &z_hollow);
  332. if(x_raised == 1 && x_hollow == 1 && zero_x_wait == 0)
  333. {
  334. zero_x_wait = 30;
  335. }
  336. if(y_raised == 1 && y_hollow == 1 && zero_y_wait == 0)
  337. {
  338. zero_y_wait = 30;
  339. }
  340. if(z_raised == 1 && z_hollow == 1 && zero_z_wait == 0)
  341. {
  342. zero_z_wait = 30;
  343. }
  344. acc_x_status = 0;
  345. acc_y_status = 0;
  346. acc_z_status = 0;
  347. if((zero_x_wait > 0 || acc_x_status == 1) && detect_turn_line(acc_x_buff, 10, 0))
  348. {
  349. acc_x_status = 1;
  350. }
  351. if((zero_y_wait > 0 || acc_y_status == 1) && detect_turn_line(acc_y_buff, 10, 0))
  352. {
  353. acc_y_status = 1;
  354. }
  355. if((zero_z_wait > 0 || acc_z_status == 1) && detect_turn_line(acc_z_buff, 10, 1))
  356. {
  357. acc_z_status = 1;
  358. }
  359. //剧烈信号探测拐点
  360. if(severe_turn_point(acc_x_buff, ACC_WINDOW_SIZE))
  361. {
  362. acc_x_status = 1;
  363. }
  364. if(severe_turn_point(acc_y_buff, ACC_WINDOW_SIZE))
  365. {
  366. acc_y_status = 1;
  367. }
  368. if(severe_turn_point_z(acc_z_buff, ACC_WINDOW_SIZE))
  369. {
  370. acc_z_status = 1;
  371. }
  372. //标志垫着脚跑的变量
  373. int special_zupt = 0;
  374. if(var_acc(acc_z_buff, ACC_WINDOW_SIZE) > 2097152 && max_window(acc_z_buff, 10) > 2048 && acc[2] > 1434)
  375. {
  376. acc_x_status = 1;
  377. acc_y_status = 1;
  378. acc_z_status = 3;
  379. special_zupt = 1;
  380. }
  381. //当上次信号大于0的时候, 判断下滑曲线
  382. if(last_acc_x_status && station_signal(acc_x_buff, 5))
  383. {
  384. acc_x_status = 2;
  385. }
  386. if(last_acc_y_status && station_signal(acc_y_buff, 5))
  387. {
  388. acc_y_status = 2;
  389. }
  390. if(last_acc_z_status && station_signal(acc_z_buff, 5))
  391. {
  392. acc_z_status = 2;
  393. }
  394. if((acc_x_status || acc_y_status) && abs(acc[2] - 2048) < 410 && station_signal(acc_z_buff, 10))
  395. {
  396. acc_z_status = 2;
  397. }
  398. if(acc_z_status == 0 && last_acc_z_status == 3 && max_window(acc_z_buff, 10) - acc[2] > 2048 && acc[2] > 1434 && acc[2] < 3072)
  399. {
  400. acc_z_status = 3;
  401. }
  402. //因为会有断开的现象,所以大概估计到200ms内出现平缓信号,视为在地上
  403. if(time_stamp - last_time_stamp < 20)
  404. {
  405. //if(max_window(acc_xyz_buff, 10) - min_window(acc_xyz_buff, 10) < 205)
  406. if(station_window_xyz(acc_xyz_buff))
  407. {
  408. acc_x_status = 1;
  409. acc_y_status = 1;
  410. acc_z_status = 1;
  411. }
  412. }
  413. //利用奇异值来去掉误判信号
  414. if(special_zupt == 0 && (acc[2] < 1638 || abs(acc[0]) > 1024 || abs(acc[1]) > 1024))
  415. {
  416. acc_x_status = 0;
  417. acc_y_status = 0;
  418. acc_z_status = 0;
  419. }
  420. //凹凸信号都检测信号,需要延时等待
  421. if(zero_x_wait > 0)
  422. {
  423. zero_x_wait --;
  424. if(zero_x_wait == 0)
  425. {
  426. x_raised = 0;
  427. x_hollow = 0;
  428. }
  429. }
  430. if(zero_y_wait > 0)
  431. {
  432. zero_y_wait --;
  433. if(zero_y_wait == 0)
  434. {
  435. y_raised = 0;
  436. y_hollow = 0;
  437. }
  438. }
  439. if(zero_z_wait > 0)
  440. {
  441. zero_z_wait --;
  442. if(zero_z_wait == 0)
  443. {
  444. z_raised = 0;
  445. z_hollow = 0;
  446. }
  447. }
  448. last_acc_x_status = acc_x_status;
  449. last_acc_y_status = acc_y_status;
  450. last_acc_z_status = acc_z_status;
  451. if(time_stamp - last_time_stamp < 15)
  452. {
  453. if(acc[2] > max_z_unzero)
  454. {
  455. max_z_unzero = acc[2];
  456. }
  457. if(acc[2] < min_z_unzero)
  458. {
  459. min_z_unzero = acc[2];
  460. }
  461. }
  462. else
  463. {
  464. max_z_unzero = 2048;
  465. min_z_unzero = 2048;
  466. }
  467. //记录zupt
  468. if( (acc_z_status > 0 || (acc_x_status > 0 && acc_y_status > 0)) )
  469. {
  470. // *zupt = 1;
  471. if(time_stamp - last_time_stamp > 15)
  472. {
  473. //PDR_step_count ++;
  474. mFlash.mStep.stepCur[0]++;
  475. }
  476. else if(min_z_unzero < 0 && max_z_unzero > 4096 && time_stamp - last_time_stamp > 5)
  477. {
  478. mFlash.mStep.stepCur[0]++;
  479. max_z_unzero = 2048;
  480. min_z_unzero = 2048;
  481. }
  482. // SEGGER_RTT_printf(0,"bushu:%d\n",mFlash.mStep.stepCur[0]);
  483. last_time_stamp = time_stamp;
  484. }
  485. // else
  486. // {
  487. // *zupt = 0;
  488. // }
  489. // *x_zero = 0;
  490. // *y_zero = 0;
  491. // *z_zero = acc_z_status;
  492. time_stamp ++;
  493. }