PageRenderTime 31ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/EDVSBoardOS/MotionDriver/mllite/results_holder.c

https://bitbucket.org/rui_araujo/edvsboardos
C | 522 lines | 297 code | 48 blank | 177 comment | 34 complexity | dfc22d3408bd138686bcfb3aee34b2d4 MD5 | raw file
  1. /*
  2. $License:
  3. Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
  4. See included License.txt for License information.
  5. $
  6. */
  7. /**
  8. * @defgroup Results_Holder results_holder
  9. * @brief Motion Library - Results Holder
  10. * Holds the data for MPL
  11. *
  12. * @{
  13. * @file results_holder.c
  14. * @brief Results Holder for HAL.
  15. */
  16. #include <string.h>
  17. #include "results_holder.h"
  18. #include "ml_math_func.h"
  19. #include "mlmath.h"
  20. #include "start_manager.h"
  21. #include "data_builder.h"
  22. #include "message_layer.h"
  23. #include "log.h"
  24. // These 2 status bits are used to control when the 9 axis quaternion is updated
  25. #define INV_COMPASS_CORRECTION_SET 1
  26. #define INV_6_AXIS_QUAT_SET 2
  27. struct results_t {
  28. long nav_quat[4];
  29. long gam_quat[4];
  30. inv_time_t nav_timestamp;
  31. inv_time_t gam_timestamp;
  32. long local_field[3]; /**< local earth's magnetic field */
  33. long mag_scale[3]; /**< scale factor to apply to magnetic field reading */
  34. long compass_correction[4]; /**< quaternion going from gyro,accel quaternion to 9 axis */
  35. int acc_state; /**< Describes accel state */
  36. int got_accel_bias; /**< Flag describing if accel bias is known */
  37. long compass_bias_error[3]; /**< Error Squared */
  38. unsigned char motion_state;
  39. unsigned int motion_state_counter; /**< Incremented for each no motion event in a row */
  40. long compass_count; /**< compass state internal counter */
  41. int got_compass_bias; /**< Flag describing if compass bias is known */
  42. int large_mag_field; /**< Flag describing if there is a large magnetic field */
  43. int compass_state; /**< Internal compass state */
  44. long status;
  45. struct inv_sensor_cal_t *sensor;
  46. float quat_confidence_interval;
  47. };
  48. static struct results_t rh;
  49. /** @internal
  50. * Store a quaternion more suitable for gaming. This quaternion is often determined
  51. * using only gyro and accel.
  52. * @param[in] quat Length 4, Quaternion scaled by 2^30
  53. */
  54. void inv_store_gaming_quaternion(const long *quat, inv_time_t timestamp)
  55. {
  56. rh.status |= INV_6_AXIS_QUAT_SET;
  57. memcpy(&rh.gam_quat, quat, sizeof(rh.gam_quat));
  58. rh.gam_timestamp = timestamp;
  59. }
  60. /** @internal
  61. * Sets the quaternion adjustment from 6 axis (accel, gyro) to 9 axis quaternion.
  62. * @param[in] data Quaternion Adjustment
  63. * @param[in] timestamp Timestamp of when this is valid
  64. */
  65. void inv_set_compass_correction(const long *data, inv_time_t timestamp)
  66. {
  67. rh.status |= INV_COMPASS_CORRECTION_SET;
  68. memcpy(rh.compass_correction, data, sizeof(rh.compass_correction));
  69. rh.nav_timestamp = timestamp;
  70. }
  71. /** @internal
  72. * Gets the quaternion adjustment from 6 axis (accel, gyro) to 9 axis quaternion.
  73. * @param[out] data Quaternion Adjustment
  74. * @param[out] timestamp Timestamp of when this is valid
  75. */
  76. void inv_get_compass_correction(long *data, inv_time_t *timestamp)
  77. {
  78. memcpy(data, rh.compass_correction, sizeof(rh.compass_correction));
  79. *timestamp = rh.nav_timestamp;
  80. }
  81. /** Returns non-zero if there is a large magnetic field. See inv_set_large_mag_field() for setting this variable.
  82. * @return Returns non-zero if there is a large magnetic field.
  83. */
  84. int inv_get_large_mag_field()
  85. {
  86. return rh.large_mag_field;
  87. }
  88. /** Set to non-zero if there as a large magnetic field. See inv_get_large_mag_field() for getting this variable.
  89. * @param[in] state value to set for magnetic field strength. Should be non-zero if it is large.
  90. */
  91. void inv_set_large_mag_field(int state)
  92. {
  93. rh.large_mag_field = state;
  94. }
  95. /** Gets the accel state set by inv_set_acc_state()
  96. * @return accel state.
  97. */
  98. int inv_get_acc_state()
  99. {
  100. return rh.acc_state;
  101. }
  102. /** Sets the accel state. See inv_get_acc_state() to get the value.
  103. * @param[in] state value to set accel state to.
  104. */
  105. void inv_set_acc_state(int state)
  106. {
  107. rh.acc_state = state;
  108. return;
  109. }
  110. /** Returns the motion state
  111. * @param[out] cntr Number of previous times a no motion event has occured in a row.
  112. * @return Returns INV_SUCCESS if successful or an error code if not.
  113. */
  114. int inv_get_motion_state(unsigned int *cntr)
  115. {
  116. *cntr = rh.motion_state_counter;
  117. return rh.motion_state;
  118. }
  119. /** Sets the motion state
  120. * @param[in] state motion state where INV_NO_MOTION is not moving
  121. * and INV_MOTION is moving.
  122. */
  123. void inv_set_motion_state(unsigned char state)
  124. {
  125. long set;
  126. if (state == rh.motion_state) {
  127. if (state == INV_NO_MOTION) {
  128. rh.motion_state_counter++;
  129. } else {
  130. rh.motion_state_counter = 0;
  131. }
  132. return;
  133. }
  134. rh.motion_state_counter = 0;
  135. rh.motion_state = state;
  136. /* Equivalent to set = state, but #define's may change. */
  137. if (state == INV_MOTION)
  138. set = INV_MSG_MOTION_EVENT;
  139. else
  140. set = INV_MSG_NO_MOTION_EVENT;
  141. inv_set_message(set, (INV_MSG_MOTION_EVENT | INV_MSG_NO_MOTION_EVENT), 0);
  142. }
  143. /** Sets the local earth's magnetic field
  144. * @param[in] data Local earth's magnetic field in uT scaled by 2^16.
  145. * Length = 3. Y typically points north, Z typically points down in
  146. * northern hemisphere and up in southern hemisphere.
  147. */
  148. void inv_set_local_field(const long *data)
  149. {
  150. memcpy(rh.local_field, data, sizeof(rh.local_field));
  151. }
  152. /** Gets the local earth's magnetic field
  153. * @param[out] data Local earth's magnetic field in uT scaled by 2^16.
  154. * Length = 3. Y typically points north, Z typically points down in
  155. * northern hemisphere and up in southern hemisphere.
  156. */
  157. void inv_get_local_field(long *data)
  158. {
  159. memcpy(data, rh.local_field, sizeof(rh.local_field));
  160. }
  161. /** Sets the compass sensitivity
  162. * @param[in] data Length 3, sensitivity for each compass axis
  163. * scaled such that 1.0 = 2^30.
  164. */
  165. void inv_set_mag_scale(const long *data)
  166. {
  167. memcpy(rh.mag_scale, data, sizeof(rh.mag_scale));
  168. }
  169. /** Gets the compass sensitivity
  170. * @param[out] data Length 3, sensitivity for each compass axis
  171. * scaled such that 1.0 = 2^30.
  172. */
  173. void inv_get_mag_scale(long *data)
  174. {
  175. memcpy(data, rh.mag_scale, sizeof(rh.mag_scale));
  176. }
  177. /** Gets gravity vector
  178. * @param[out] data gravity vector in body frame scaled such that 1.0 = 2^30.
  179. * @return Returns INV_SUCCESS if successful or an error code if not.
  180. */
  181. inv_error_t inv_get_gravity(long *data)
  182. {
  183. data[0] =
  184. inv_q29_mult(rh.nav_quat[1], rh.nav_quat[3]) - inv_q29_mult(rh.nav_quat[2], rh.nav_quat[0]);
  185. data[1] =
  186. inv_q29_mult(rh.nav_quat[2], rh.nav_quat[3]) + inv_q29_mult(rh.nav_quat[1], rh.nav_quat[0]);
  187. data[2] =
  188. (inv_q29_mult(rh.nav_quat[3], rh.nav_quat[3]) + inv_q29_mult(rh.nav_quat[0], rh.nav_quat[0])) -
  189. 1073741824L;
  190. return INV_SUCCESS;
  191. }
  192. /** Returns a quaternion based only on gyro and accel.
  193. * @param[out] data 6-axis gyro and accel quaternion scaled such that 1.0 = 2^30.
  194. * @return Returns INV_SUCCESS if successful or an error code if not.
  195. */
  196. inv_error_t inv_get_6axis_quaternion(long *data)
  197. {
  198. memcpy(data, rh.gam_quat, sizeof(rh.gam_quat));
  199. return INV_SUCCESS;
  200. }
  201. /** Returns a quaternion.
  202. * @param[out] data 9-axis quaternion scaled such that 1.0 = 2^30.
  203. * @return Returns INV_SUCCESS if successful or an error code if not.
  204. */
  205. inv_error_t inv_get_quaternion(long *data)
  206. {
  207. if (rh.status & (INV_COMPASS_CORRECTION_SET | INV_6_AXIS_QUAT_SET)) {
  208. inv_q_mult(rh.compass_correction, rh.gam_quat, rh.nav_quat);
  209. rh.status &= ~(INV_COMPASS_CORRECTION_SET | INV_6_AXIS_QUAT_SET);
  210. }
  211. memcpy(data, rh.nav_quat, sizeof(rh.nav_quat));
  212. return INV_SUCCESS;
  213. }
  214. /** Returns a quaternion.
  215. * @param[out] data 9-axis quaternion.
  216. * @return Returns INV_SUCCESS if successful or an error code if not.
  217. */
  218. inv_error_t inv_get_quaternion_float(float *data)
  219. {
  220. long ldata[4];
  221. inv_error_t result = inv_get_quaternion(ldata);
  222. data[0] = inv_q30_to_float(ldata[0]);
  223. data[1] = inv_q30_to_float(ldata[1]);
  224. data[2] = inv_q30_to_float(ldata[2]);
  225. data[3] = inv_q30_to_float(ldata[3]);
  226. return result;
  227. }
  228. /** Returns a quaternion with accuracy and timestamp.
  229. * @param[out] data 9-axis quaternion scaled such that 1.0 = 2^30.
  230. * @param[out] accuracy Accuracy of quaternion, 0-3, where 3 is most accurate.
  231. * @param[out] timestamp Timestamp of this quaternion in nanoseconds
  232. */
  233. void inv_get_quaternion_set(long *data, int *accuracy, inv_time_t *timestamp)
  234. {
  235. inv_get_quaternion(data);
  236. *timestamp = inv_get_last_timestamp();
  237. if (inv_get_compass_on()) {
  238. *accuracy = inv_get_mag_accuracy();
  239. } else if (inv_get_gyro_on()) {
  240. *accuracy = inv_get_gyro_accuracy();
  241. }else if (inv_get_accel_on()) {
  242. *accuracy = inv_get_accel_accuracy();
  243. } else {
  244. *accuracy = 0;
  245. }
  246. }
  247. /** Callback that gets called everytime there is new data. It is
  248. * registered by inv_start_results_holder().
  249. * @param[in] sensor_cal New sensor data to process.
  250. * @return Returns INV_SUCCESS if successful or an error code if not.
  251. */
  252. inv_error_t inv_generate_results(struct inv_sensor_cal_t *sensor_cal)
  253. {
  254. rh.sensor = sensor_cal;
  255. return INV_SUCCESS;
  256. }
  257. /** Function to turn on this module. This is automatically called by
  258. * inv_enable_results_holder(). Typically not called by users.
  259. * @return Returns INV_SUCCESS if successful or an error code if not.
  260. */
  261. inv_error_t inv_start_results_holder(void)
  262. {
  263. inv_register_data_cb(inv_generate_results, INV_PRIORITY_RESULTS_HOLDER,
  264. INV_GYRO_NEW | INV_ACCEL_NEW | INV_MAG_NEW);
  265. return INV_SUCCESS;
  266. }
  267. /** Initializes results holder. This is called automatically by the
  268. * enable function inv_enable_results_holder(). It may be called any time the feature is enabled, but
  269. * is typically not needed to be called by outside callers.
  270. * @return Returns INV_SUCCESS if successful or an error code if not.
  271. */
  272. inv_error_t inv_init_results_holder(void)
  273. {
  274. memset(&rh, 0, sizeof(rh));
  275. rh.mag_scale[0] = 1L<<30;
  276. rh.mag_scale[1] = 1L<<30;
  277. rh.mag_scale[2] = 1L<<30;
  278. rh.compass_correction[0] = 1L<<30;
  279. rh.gam_quat[0] = 1L<<30;
  280. rh.nav_quat[0] = 1L<<30;
  281. rh.quat_confidence_interval = (float)M_PI;
  282. return INV_SUCCESS;
  283. }
  284. /** Turns on storage of results.
  285. */
  286. inv_error_t inv_enable_results_holder()
  287. {
  288. inv_error_t result;
  289. result = inv_init_results_holder();
  290. if ( result ) {
  291. return result;
  292. }
  293. result = inv_register_mpl_start_notification(inv_start_results_holder);
  294. return result;
  295. }
  296. /** Sets state of if we know the accel bias.
  297. * @return return 1 if we know the accel bias, 0 if not.
  298. * it is set with inv_set_accel_bias_found()
  299. */
  300. int inv_got_accel_bias()
  301. {
  302. return rh.got_accel_bias;
  303. }
  304. /** Sets whether we know the accel bias
  305. * @param[in] state Set to 1 if we know the accel bias.
  306. * Can be retrieved with inv_got_accel_bias()
  307. */
  308. void inv_set_accel_bias_found(int state)
  309. {
  310. rh.got_accel_bias = state;
  311. }
  312. /** Sets state of if we know the compass bias.
  313. * @return return 1 if we know the compass bias, 0 if not.
  314. * it is set with inv_set_compass_bias_found()
  315. */
  316. int inv_got_compass_bias()
  317. {
  318. return rh.got_compass_bias;
  319. }
  320. /** Sets whether we know the compass bias
  321. * @param[in] state Set to 1 if we know the compass bias.
  322. * Can be retrieved with inv_got_compass_bias()
  323. */
  324. void inv_set_compass_bias_found(int state)
  325. {
  326. rh.got_compass_bias = state;
  327. }
  328. /** Sets the compass state.
  329. * @param[in] state Compass state. It can be retrieved with inv_get_compass_state().
  330. */
  331. void inv_set_compass_state(int state)
  332. {
  333. rh.compass_state = state;
  334. }
  335. /** Get's the compass state
  336. * @return the compass state that was set with inv_set_compass_state()
  337. */
  338. int inv_get_compass_state()
  339. {
  340. return rh.compass_state;
  341. }
  342. /** Set compass bias error. See inv_get_compass_bias_error()
  343. * @param[in] bias_error Set's how accurate we know the compass bias. It is the
  344. * error squared.
  345. */
  346. void inv_set_compass_bias_error(const long *bias_error)
  347. {
  348. memcpy(rh.compass_bias_error, bias_error, sizeof(rh.compass_bias_error));
  349. }
  350. /** Get's compass bias error. See inv_set_compass_bias_error() for setting.
  351. * @param[out] bias_error Accuracy as to how well the compass bias is known. It is the error squared.
  352. */
  353. void inv_get_compass_bias_error(long *bias_error)
  354. {
  355. memcpy(bias_error, rh.compass_bias_error, sizeof(rh.compass_bias_error));
  356. }
  357. /**
  358. * @brief Returns 3-element vector of accelerometer data in body frame
  359. * with gravity removed
  360. * @param[out] data 3-element vector of accelerometer data in body frame
  361. * with gravity removed
  362. * @return INV_SUCCESS if successful
  363. * INV_ERROR_INVALID_PARAMETER if invalid input pointer
  364. */
  365. inv_error_t inv_get_linear_accel(long *data)
  366. {
  367. long gravity[3];
  368. if (data != NULL)
  369. {
  370. inv_get_accel_set(data, NULL, NULL);
  371. inv_get_gravity(gravity);
  372. data[0] -= gravity[0] >> 14;
  373. data[1] -= gravity[1] >> 14;
  374. data[2] -= gravity[2] >> 14;
  375. return INV_SUCCESS;
  376. }
  377. else {
  378. return INV_ERROR_INVALID_PARAMETER;
  379. }
  380. }
  381. /**
  382. * @brief Returns 3-element vector of accelerometer data in body frame
  383. * @param[out] data 3-element vector of accelerometer data in body frame
  384. * @return INV_SUCCESS if successful
  385. * INV_ERROR_INVALID_PARAMETER if invalid input pointer
  386. */
  387. inv_error_t inv_get_accel(long *data)
  388. {
  389. if (data != NULL) {
  390. inv_get_accel_set(data, NULL, NULL);
  391. return INV_SUCCESS;
  392. }
  393. else {
  394. return INV_ERROR_INVALID_PARAMETER;
  395. }
  396. }
  397. /**
  398. * @brief Returns 3-element vector of accelerometer float data
  399. * @param[out] data 3-element vector of accelerometer float data
  400. * @return INV_SUCCESS if successful
  401. * INV_ERROR_INVALID_PARAMETER if invalid input pointer
  402. */
  403. inv_error_t inv_get_accel_float(float *data)
  404. {
  405. long tdata[3];
  406. unsigned char i;
  407. if (data != NULL && !inv_get_accel(tdata)) {
  408. for (i = 0; i < 3; ++i) {
  409. data[i] = ((float)tdata[i] / (1L << 16));
  410. }
  411. return INV_SUCCESS;
  412. }
  413. else {
  414. return INV_ERROR_INVALID_PARAMETER;
  415. }
  416. }
  417. /**
  418. * @brief Returns 3-element vector of gyro float data
  419. * @param[out] data 3-element vector of gyro float data
  420. * @return INV_SUCCESS if successful
  421. * INV_ERROR_INVALID_PARAMETER if invalid input pointer
  422. */
  423. inv_error_t inv_get_gyro_float(float *data)
  424. {
  425. long tdata[3];
  426. unsigned char i;
  427. if (data != NULL) {
  428. inv_get_gyro_set(tdata, NULL, NULL);
  429. for (i = 0; i < 3; ++i) {
  430. data[i] = ((float)tdata[i] / (1L << 16));
  431. }
  432. return INV_SUCCESS;
  433. }
  434. else {
  435. return INV_ERROR_INVALID_PARAMETER;
  436. }
  437. }
  438. /** Set 9 axis 95% heading confidence interval for quaternion
  439. * @param[in] ci Confidence interval in radians.
  440. */
  441. void inv_set_heading_confidence_interval(float ci)
  442. {
  443. rh.quat_confidence_interval = ci;
  444. }
  445. /** Get 9 axis 95% heading confidence interval for quaternion
  446. * @return Confidence interval in radians.
  447. */
  448. float inv_get_heading_confidence_interval(void)
  449. {
  450. return rh.quat_confidence_interval;
  451. }
  452. /**
  453. * @brief Returns 3-element vector of linear accel float data
  454. * @param[out] data 3-element vector of linear aceel float data
  455. * @return INV_SUCCESS if successful
  456. * INV_ERROR_INVALID_PARAMETER if invalid input pointer
  457. */
  458. inv_error_t inv_get_linear_accel_float(float *data)
  459. {
  460. long tdata[3];
  461. unsigned char i;
  462. if (data != NULL && !inv_get_linear_accel(tdata)) {
  463. for (i = 0; i < 3; ++i) {
  464. data[i] = ((float)tdata[i] / (1L << 16));
  465. }
  466. return INV_SUCCESS;
  467. }
  468. else {
  469. return INV_ERROR_INVALID_PARAMETER;
  470. }
  471. }
  472. /**
  473. * @}
  474. */