all.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
  5. /* Before C99, float variants of math functions are not avaliable. */
  6. static float _sqrtf(float x)
  7. {
  8. return (float)sqrt(x);
  9. }
  10. #define sqrtf _sqrtf
  11. static float _fmodf(float x, float y)
  12. {
  13. return (float)fmod(x, y);
  14. }
  15. #define fmodf _fmodf
  16. /* Before C99, INFINITY may be unavaliable. */
  17. #ifndef INFINITY
  18. #if defined __GNUC__ && (__GNUC__ > 3 || \
  19. (__GNUC__ == 3 && __GNUC_MINOR >= 3))
  20. #define INFINITY (__builtin_inff())
  21. #else
  22. #define INFINITY 1e10000f
  23. #endif
  24. #endif /* INFINITY */
  25. #endif /* __STDC_VERSION__ < 199901L */
  26. static FILE *data_recorder = NULL;
  27. static const char *column_names =
  28. "gx,gy,gz,ax,ay,az,cy,cy_fixed,"
  29. "g,a,g_std,a_std,g_up,a_up,is_out,valley";
  30. struct schmidt
  31. {
  32. float high;
  33. float low;
  34. int value;
  35. };
  36. extern int schmidt_init(struct schmidt *schmidt, float low, float high);
  37. extern int schmidt_trig(struct schmidt *schmidt, float level);
  38. extern int schmidt_get(struct schmidt *schmidt);
  39. #define RINGBUF_MAX_SIZE 100
  40. struct ringbuf
  41. {
  42. float buf[RINGBUF_MAX_SIZE];
  43. float sum;
  44. float sum2;
  45. int cap;
  46. int p;
  47. int full;
  48. };
  49. extern int ringbuf_init(struct ringbuf *ringbuf, int cap);
  50. extern void ringbuf_push(struct ringbuf *ringbuf, float value);
  51. extern int ringbuf_size(struct ringbuf *ringbuf);
  52. extern float ringbuf_mean(struct ringbuf *ringbuf);
  53. extern float ringbuf_variance(struct ringbuf *ringbuf);
  54. extern float ringbuf_stdev(struct ringbuf *ringbuf);
  55. #define MONOTONIC_QUEUE_CAP 80
  56. typedef int (*monotonic_queue_cmp)(float, float);
  57. struct monotonic_queue
  58. {
  59. monotonic_queue_cmp cmp;
  60. float buf[MONOTONIC_QUEUE_CAP];
  61. int h, h_min, t;
  62. int len;
  63. };
  64. extern void monotonic_queue_init(struct monotonic_queue *mq,
  65. monotonic_queue_cmp cmp);
  66. extern int monotonic_queue_push(struct monotonic_queue *mq, float value);
  67. extern int monotonic_queue_pop(struct monotonic_queue *mq);
  68. extern int monotonic_queue_get_min(struct monotonic_queue *mq, float *dest);
  69. extern int monotonic_queue_get_len(struct monotonic_queue *mq);
  70. typedef int (*jump_rope_count_valley_cmp)(float valley, float prev_valley);
  71. struct jump_rope_count_config
  72. {
  73. float lg, hg, la, ha, lgz, hgz, a_g_window;
  74. int cy_window, cy_crit, cy_suppress_time, wait_time, dead_zone_time;
  75. int record_valley_time, prev_valley_lifetime;
  76. jump_rope_count_valley_cmp valley_cmp;
  77. };
  78. struct jump_rope_count_device
  79. {
  80. struct schmidt trig_g, trig_a, trig_gz;
  81. struct ringbuf rbuf_g, rbuf_a;
  82. struct monotonic_queue mq_min_cy, mq_max_cy;
  83. int cy_window, cy_crit, cy_suppress_time, wait_time, dead_zone_time;
  84. int record_valley_time, prev_valley_lifetime;
  85. jump_rope_count_valley_cmp valley_cmp;
  86. int cy_suppress, wait_remain_time, dead_zone_remain_time;
  87. int recording_valley, has_prev_valley;
  88. float last_cy, last_cy_fixed;
  89. float valley, prev_valley;
  90. };
  91. struct sensor_packet
  92. {
  93. float ax, ay, az, gx, gy, gz, cy;
  94. };
  95. enum jump_rope_count_result
  96. {
  97. RESULT_INACTIVE = -1,
  98. RESULT_NONE = 0,
  99. RESULT_TRIGGERED = 1
  100. };
  101. extern int jump_rope_count_device_init(struct jump_rope_count_device *dev,
  102. struct jump_rope_count_config *cfg);
  103. extern int process_packet(struct jump_rope_count_device *dev,
  104. struct sensor_packet *packet,
  105. enum jump_rope_count_result *result);
  106. static int less(float a, float b)
  107. {
  108. return a < b;
  109. }
  110. static int greater(float a, float b)
  111. {
  112. return a > b;
  113. }
  114. int jump_rope_count_device_init(struct jump_rope_count_device *dev,
  115. struct jump_rope_count_config *cfg)
  116. {
  117. int ret;
  118. ret = schmidt_init(&dev->trig_g, cfg->lg, cfg->hg);
  119. if (ret != 0)
  120. return ret;
  121. ret = schmidt_init(&dev->trig_a, cfg->la, cfg->ha);
  122. if (ret != 0)
  123. return ret;
  124. ret = schmidt_init(&dev->trig_gz, cfg->lgz, cfg->hgz);
  125. if (ret != 0)
  126. return ret;
  127. ret = ringbuf_init(&dev->rbuf_a, cfg->a_g_window);
  128. if (ret != 0)
  129. return ret;
  130. ret = ringbuf_init(&dev->rbuf_g, cfg->a_g_window);
  131. if (ret != 0)
  132. return ret;
  133. monotonic_queue_init(&dev->mq_min_cy, less);
  134. monotonic_queue_init(&dev->mq_max_cy, greater);
  135. dev->cy_window = cfg->cy_window;
  136. dev->cy_crit = cfg->cy_crit;
  137. dev->cy_suppress_time = cfg->cy_suppress_time;
  138. dev->wait_time = cfg->wait_time;
  139. dev->dead_zone_time = cfg->dead_zone_time;
  140. dev->cy_suppress = 0;
  141. dev->last_cy = dev->last_cy_fixed = 0;
  142. dev->wait_remain_time = dev->dead_zone_remain_time = 0;
  143. dev->record_valley_time = cfg->record_valley_time;
  144. dev->prev_valley_lifetime = cfg->prev_valley_lifetime;
  145. dev->valley_cmp = cfg->valley_cmp;
  146. if (dev->record_valley_time < 0)
  147. dev->record_valley_time = 1;
  148. dev->has_prev_valley = 0;
  149. /* an initial value only used for data recording */
  150. dev->valley = cfg->lgz;
  151. return 0;
  152. }
  153. static float hypot3f(float x, float y, float z)
  154. {
  155. return sqrtf(x*x + y*y + z*z);
  156. }
  157. static float angle_change(float old, float new)
  158. {
  159. float ret = fmodf(new - old, 360.0);
  160. if (ret < -180.0)
  161. ret += 360.0;
  162. if (ret > 180.0)
  163. ret -= 360.0;
  164. return ret;
  165. }
  166. int process_packet(struct jump_rope_count_device *dev,
  167. struct sensor_packet *packet,
  168. enum jump_rope_count_result *result)
  169. {
  170. int ret = 0;
  171. float min, max;
  172. float g = hypot3f(packet->gx, packet->gy, packet->gz);
  173. float a = hypot3f(packet->ax, packet->ay, packet->az);
  174. float gz = packet->gz;
  175. float cy = dev->last_cy_fixed + angle_change(dev->last_cy,
  176. packet->cy);
  177. float std_g, std_a;
  178. dev->last_cy_fixed = cy;
  179. dev->last_cy = packet->cy;
  180. ringbuf_push(&dev->rbuf_g, g);
  181. ringbuf_push(&dev->rbuf_a, a);
  182. std_g = ringbuf_stdev(&dev->rbuf_g);
  183. std_a = ringbuf_stdev(&dev->rbuf_a);
  184. schmidt_trig(&dev->trig_g, std_g);
  185. schmidt_trig(&dev->trig_a, std_a);
  186. ret = monotonic_queue_push(&dev->mq_min_cy, cy);
  187. if (ret != 0)
  188. return ret;
  189. if (monotonic_queue_get_len(&dev->mq_min_cy) > dev->cy_window)
  190. ret = monotonic_queue_pop(&dev->mq_min_cy);
  191. if (ret != 0)
  192. return ret;
  193. ret = monotonic_queue_push(&dev->mq_max_cy, cy);
  194. if (ret != 0)
  195. return ret;
  196. if (monotonic_queue_get_len(&dev->mq_max_cy) > dev->cy_window)
  197. ret = monotonic_queue_pop(&dev->mq_max_cy);
  198. if (ret != 0)
  199. return ret;
  200. if (dev->has_prev_valley > 0)
  201. dev->has_prev_valley--;
  202. if (dev->recording_valley) {
  203. if (--dev->recording_valley == 0 &&
  204. (!dev->has_prev_valley ||
  205. dev->valley_cmp(dev->valley, dev->prev_valley))) {
  206. dev->has_prev_valley = dev->prev_valley_lifetime;
  207. dev->prev_valley = dev->valley;
  208. *result = RESULT_TRIGGERED;
  209. goto out;
  210. }
  211. if (dev->recording_valley) {
  212. if (dev->valley > gz)
  213. dev->valley = gz;
  214. *result = RESULT_NONE;
  215. goto out;
  216. }
  217. }
  218. ret = monotonic_queue_get_min(&dev->mq_min_cy, &min);
  219. if (ret != 0)
  220. return ret;
  221. ret = monotonic_queue_get_min(&dev->mq_max_cy, &max);
  222. if (ret != 0)
  223. return ret;
  224. if (max - min > dev->cy_crit)
  225. dev->cy_suppress = dev->cy_suppress_time;
  226. if (schmidt_get(&dev->trig_g) == 0 ||
  227. schmidt_get(&dev->trig_a) == 0 ||
  228. dev->cy_suppress > 0)
  229. {
  230. schmidt_trig(&dev->trig_gz, -INFINITY);
  231. *result = RESULT_INACTIVE;
  232. goto out;
  233. }
  234. if (schmidt_trig(&dev->trig_gz, gz) == 1 &&
  235. schmidt_get(&dev->trig_gz) == 0 &&
  236. dev->cy_suppress == 0 &&
  237. dev->dead_zone_remain_time == 0)
  238. {
  239. dev->wait_remain_time = dev->wait_time;
  240. dev->dead_zone_remain_time = dev->dead_zone_time;
  241. dev->recording_valley = dev->record_valley_time;
  242. dev->valley = gz;
  243. *result = RESULT_NONE;
  244. goto out;
  245. }
  246. *result = (dev->wait_remain_time > 0 ? RESULT_NONE :
  247. RESULT_INACTIVE);
  248. out:
  249. if (dev->wait_remain_time)
  250. dev->wait_remain_time--;
  251. if (dev->dead_zone_remain_time)
  252. dev->dead_zone_remain_time--;
  253. if (dev->cy_suppress > 0)
  254. dev->cy_suppress--;
  255. if (data_recorder == NULL)
  256. return 0;
  257. /* column names:
  258. "gx,gy,gz,ax,ay,az,cy,cy_fixed,"
  259. "g,a,g_std,a_std,g_up,a_up,is_out,valley" */
  260. fprintf(data_recorder, "%.7f,%.7f,%.7f,",
  261. packet->gx, packet->gy, packet->gz);
  262. fprintf(data_recorder, "%.7f,%.7f,%.7f,",
  263. packet->ax, packet->ay, packet->az);
  264. fprintf(data_recorder, "%.7f,%.7f,",
  265. dev->last_cy, dev->last_cy_fixed);
  266. fprintf(data_recorder, "%.7f,%.7f,%.7f,%.7f,",
  267. g, a, std_g, std_a);
  268. fprintf(data_recorder, "%d,%d,%d,%.7f\n",
  269. schmidt_get(&dev->trig_g),
  270. schmidt_get(&dev->trig_a),
  271. *result == RESULT_TRIGGERED,
  272. dev->valley);
  273. return 0;
  274. }
  275. void monotonic_queue_init(struct monotonic_queue *mq,
  276. monotonic_queue_cmp cmp)
  277. {
  278. mq->h = mq->h_min = mq->t = mq->len = 0;
  279. mq->cmp = cmp;
  280. }
  281. int monotonic_queue_push(struct monotonic_queue *mq, float value)
  282. {
  283. int t1;
  284. while (mq->h_min != mq->t && mq->cmp(value, mq->buf[mq->h_min]))
  285. mq->h_min = (mq->h_min + 1) % MONOTONIC_QUEUE_CAP;
  286. t1 = (mq->t + 1) % MONOTONIC_QUEUE_CAP;
  287. if (t1 == mq->h)
  288. /* over flow */
  289. return -1;
  290. mq->len++;
  291. mq->buf[mq->t] = value;
  292. mq->t = t1;
  293. return 0;
  294. }
  295. int monotonic_queue_pop(struct monotonic_queue *mq)
  296. {
  297. if (mq->h == mq->t)
  298. /* empty */
  299. return -1;
  300. mq->len--;
  301. if (mq->h == mq->h_min)
  302. mq->h_min = (mq->h_min + 1) % MONOTONIC_QUEUE_CAP;
  303. mq->h = (mq->h + 1) % MONOTONIC_QUEUE_CAP;
  304. return 0;
  305. }
  306. int monotonic_queue_get_min(struct monotonic_queue *mq, float *dest)
  307. {
  308. if (mq->h == mq->t)
  309. /* empty */
  310. return -1;
  311. *dest = mq->buf[mq->h_min];
  312. return 0;
  313. }
  314. int monotonic_queue_get_len(struct monotonic_queue *mq)
  315. {
  316. return mq->len;
  317. }
  318. int ringbuf_init(struct ringbuf *ringbuf, int cap)
  319. {
  320. if (cap > RINGBUF_MAX_SIZE)
  321. return -1;
  322. ringbuf->p = 0;
  323. ringbuf->full = 0;
  324. ringbuf->sum = ringbuf->sum2 = 0.0;
  325. ringbuf->cap = cap;
  326. return 0;
  327. }
  328. void ringbuf_push(struct ringbuf *ringbuf, float value)
  329. {
  330. if (ringbuf->full) {
  331. float old = ringbuf->buf[ringbuf->p];
  332. ringbuf->sum -= old;
  333. ringbuf->sum2 -= old * old;
  334. }
  335. ringbuf->sum += value;
  336. ringbuf->sum2 += value * value;
  337. ringbuf->buf[ringbuf->p++] = value;
  338. if (ringbuf->p == ringbuf->cap) {
  339. ringbuf->p = 0;
  340. ringbuf->full = 1;
  341. }
  342. }
  343. int ringbuf_size(struct ringbuf *ringbuf)
  344. {
  345. return ringbuf->full ? ringbuf->cap : ringbuf->p;
  346. }
  347. float ringbuf_mean(struct ringbuf *ringbuf)
  348. {
  349. int sz = ringbuf_size(ringbuf);
  350. if (sz == 0)
  351. return 0;
  352. return ringbuf->sum / sz;
  353. }
  354. float ringbuf_variance(struct ringbuf *ringbuf)
  355. {
  356. float mean;
  357. int sz = ringbuf_size(ringbuf);
  358. if (sz == 0)
  359. return 0;
  360. mean = ringbuf_mean(ringbuf);
  361. return ringbuf->sum2 / sz - mean * mean;
  362. }
  363. float ringbuf_stdev(struct ringbuf *ringbuf)
  364. {
  365. return sqrt(ringbuf_variance(ringbuf));
  366. }
  367. int schmidt_init(struct schmidt *schmidt, float low, float high)
  368. {
  369. if (low > high)
  370. return -1;
  371. schmidt->high = high;
  372. schmidt->low = low;
  373. schmidt->value = 0;
  374. return 0;
  375. }
  376. int schmidt_trig(struct schmidt *schmidt, float level)
  377. {
  378. if ((schmidt->value == 1 && level <= schmidt->low) ||
  379. (schmidt->value == 0 && level >= schmidt->high)) {
  380. schmidt->value ^= 1;
  381. return 1;
  382. }
  383. return 0;
  384. }
  385. int schmidt_get(struct schmidt *schmidt)
  386. {
  387. return schmidt->value;
  388. }
  389. const int fs = 50;
  390. int valley_cmp_naive(float valley, float prev_valley)
  391. {
  392. return prev_valley + 2.0 > valley;
  393. }
  394. int main()
  395. {
  396. struct jump_rope_count_config cfg;
  397. struct jump_rope_count_device dev;
  398. struct sensor_packet packet;
  399. int count = 0, ret;
  400. enum jump_rope_count_result result;
  401. data_recorder = fopen("data_record.csv", "w");
  402. if (data_recorder == NULL)
  403. fprintf(stderr, "can not open data_record.csv\n");
  404. else
  405. fprintf(data_recorder, "%s\n", column_names);
  406. cfg.lg = 0.5;
  407. cfg.hg = 1.5;
  408. cfg.la = 4.0;
  409. cfg.ha = 6.0;
  410. cfg.lgz = -1.5;
  411. cfg.hgz = 2;
  412. cfg.a_g_window = 100;
  413. cfg.cy_window = fs * 0.1;
  414. cfg.cy_crit = 200;
  415. cfg.cy_suppress_time = fs * 0.2;
  416. cfg.wait_time = fs * 1;
  417. cfg.dead_zone_time = fs * 0.2;
  418. cfg.record_valley_time = fs * 0.1;
  419. cfg.prev_valley_lifetime = fs * 0.5;
  420. cfg.valley_cmp = &valley_cmp_naive;
  421. if (jump_rope_count_device_init(&dev, &cfg) != 0)
  422. abort();
  423. while (scanf("%f%f%f%f%f%f%f",
  424. &packet.gx, &packet.gy, &packet.gz,
  425. &packet.ax, &packet.ay, &packet.az,
  426. &packet.cy) == 7) {
  427. ret = process_packet(&dev, &packet, &result);
  428. if (ret != 0)
  429. abort();
  430. if (result == RESULT_INACTIVE) {
  431. if (count > 1)
  432. printf("%d\n", count - 1);
  433. count = 0;
  434. } else if (result == RESULT_TRIGGERED)
  435. count += 1;
  436. }
  437. if (count > 1)
  438. printf("%d\n", count - 1);
  439. return 0;
  440. }
  441. /* vim: set ts=8 sw=8 sts=8 noet: */