PageRenderTime 35ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/EDVSBoardOS/MotionDriver/mllite/hal_outputs.c

https://bitbucket.org/rui_araujo/edvsboardos
C | 490 lines | 288 code | 54 blank | 148 comment | 31 complexity | e9a8792738c2eb62e00ef74d723ce5a7 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 HAL_Outputs hal_outputs
  9. * @brief Motion Library - HAL Outputs
  10. * Sets up common outputs for HAL
  11. *
  12. * @{
  13. * @file hal_outputs.c
  14. * @brief HAL Outputs.
  15. */
  16. #include <string.h>
  17. #include "hal_outputs.h"
  18. #include "log.h"
  19. #include "ml_math_func.h"
  20. #include "mlmath.h"
  21. #include "start_manager.h"
  22. #include "data_builder.h"
  23. #include "results_holder.h"
  24. struct hal_output_t {
  25. int accuracy_mag; /**< Compass accuracy */
  26. // int accuracy_gyro; /**< Gyro Accuracy */
  27. // int accuracy_accel; /**< Accel Accuracy */
  28. int accuracy_quat; /**< quat Accuracy */
  29. inv_time_t nav_timestamp;
  30. inv_time_t gam_timestamp;
  31. // inv_time_t accel_timestamp;
  32. inv_time_t mag_timestamp;
  33. long nav_quat[4];
  34. int gyro_status;
  35. int accel_status;
  36. int compass_status;
  37. int nine_axis_status;
  38. inv_biquad_filter_t lp_filter[3];
  39. float compass_float[3];
  40. };
  41. static struct hal_output_t hal_out;
  42. /** Acceleration (m/s^2) in body frame.
  43. * @param[out] values Acceleration in m/s^2 includes gravity. So while not in motion, it
  44. * should return a vector of magnitude near 9.81 m/s^2
  45. * @param[out] accuracy Accuracy of the measurment, 0 is least accurate, while 3 is most accurate.
  46. * @param[out] timestamp The timestamp for this sensor. Derived from the timestamp sent to
  47. * inv_build_accel().
  48. * @return Returns 1 if the data was updated or 0 if it was not updated.
  49. */
  50. int inv_get_sensor_type_accelerometer(float *values, int8_t *accuracy,
  51. inv_time_t * timestamp)
  52. {
  53. int status;
  54. /* Converts fixed point to m/s^2. Fixed point has 1g = 2^16.
  55. * So this 9.80665 / 2^16 */
  56. #define ACCEL_CONVERSION 0.000149637603759766f
  57. long accel[3];
  58. inv_get_accel_set(accel, accuracy, timestamp);
  59. values[0] = accel[0] * ACCEL_CONVERSION;
  60. values[1] = accel[1] * ACCEL_CONVERSION;
  61. values[2] = accel[2] * ACCEL_CONVERSION;
  62. if (hal_out.accel_status & INV_NEW_DATA)
  63. status = 1;
  64. else
  65. status = 0;
  66. return status;
  67. }
  68. /** Linear Acceleration (m/s^2) in Body Frame.
  69. * @param[out] values Linear Acceleration in body frame, length 3, (m/s^2). May show
  70. * accel biases while at rest.
  71. * @param[out] accuracy Accuracy of the measurment, 0 is least accurate, while 3 is most accurate.
  72. * @param[out] timestamp The timestamp for this sensor. Derived from the timestamp sent to
  73. * inv_build_accel().
  74. * @return Returns 1 if the data was updated or 0 if it was not updated.
  75. */
  76. int inv_get_sensor_type_linear_acceleration(float *values, int8_t *accuracy,
  77. inv_time_t * timestamp)
  78. {
  79. long gravity[3], accel[3];
  80. inv_get_accel_set(accel, accuracy, timestamp);
  81. inv_get_gravity(gravity);
  82. accel[0] -= gravity[0] >> 14;
  83. accel[1] -= gravity[1] >> 14;
  84. accel[2] -= gravity[2] >> 14;
  85. values[0] = accel[0] * ACCEL_CONVERSION;
  86. values[1] = accel[1] * ACCEL_CONVERSION;
  87. values[2] = accel[2] * ACCEL_CONVERSION;
  88. return hal_out.nine_axis_status;
  89. }
  90. /** Gravity vector (m/s^2) in Body Frame.
  91. * @param[out] values Gravity vector in body frame, length 3, (m/s^2)
  92. * @param[out] accuracy Accuracy of the measurment, 0 is least accurate, while 3 is most accurate.
  93. * @param[out] timestamp The timestamp for this sensor. Derived from the timestamp sent to
  94. * inv_build_accel().
  95. * @return Returns 1 if the data was updated or 0 if it was not updated.
  96. */
  97. int inv_get_sensor_type_gravity(float *values, int8_t *accuracy,
  98. inv_time_t * timestamp)
  99. {
  100. long gravity[3];
  101. int status;
  102. *accuracy = (int8_t) hal_out.accuracy_quat;
  103. *timestamp = hal_out.nav_timestamp;
  104. inv_get_gravity(gravity);
  105. values[0] = (gravity[0] >> 14) * ACCEL_CONVERSION;
  106. values[1] = (gravity[1] >> 14) * ACCEL_CONVERSION;
  107. values[2] = (gravity[2] >> 14) * ACCEL_CONVERSION;
  108. if ((hal_out.accel_status & INV_NEW_DATA) || (hal_out.gyro_status & INV_NEW_DATA))
  109. status = 1;
  110. else
  111. status = 0;
  112. return status;
  113. }
  114. /* Converts fixed point to rad/sec. Fixed point has 1 dps = 2^16.
  115. * So this is: pi / 2^16 / 180 */
  116. #define GYRO_CONVERSION 2.66316109007924e-007f
  117. /** Gyroscope calibrated data (rad/s) in body frame.
  118. * @param[out] values Rotation Rate in rad/sec.
  119. * @param[out] accuracy Accuracy of the measurment, 0 is least accurate, while 3 is most accurate.
  120. * @param[out] timestamp The timestamp for this sensor. Derived from the timestamp sent to
  121. * inv_build_gyro().
  122. * @return Returns 1 if the data was updated or 0 if it was not updated.
  123. */
  124. int inv_get_sensor_type_gyroscope(float *values, int8_t *accuracy,
  125. inv_time_t * timestamp)
  126. {
  127. long gyro[3];
  128. int status;
  129. inv_get_gyro_set(gyro, accuracy, timestamp);
  130. values[0] = gyro[0] * GYRO_CONVERSION;
  131. values[1] = gyro[1] * GYRO_CONVERSION;
  132. values[2] = gyro[2] * GYRO_CONVERSION;
  133. if (hal_out.gyro_status & INV_NEW_DATA)
  134. status = 1;
  135. else
  136. status = 0;
  137. return status;
  138. }
  139. /** Gyroscope raw data (rad/s) in body frame.
  140. * @param[out] values Rotation Rate in rad/sec.
  141. * @param[out] accuracy Accuracy of the measurment, 0 is least accurate, while 3 is most accurate.
  142. * @param[out] timestamp The timestamp for this sensor. Derived from the timestamp sent to
  143. * inv_build_gyro().
  144. * @return Returns 1 if the data was updated or 0 if it was not updated.
  145. */
  146. int inv_get_sensor_type_gyroscope_raw(float *values, int8_t *accuracy,
  147. inv_time_t * timestamp)
  148. {
  149. long gyro[3];
  150. int status;
  151. inv_get_gyro_set_raw(gyro, accuracy, timestamp);
  152. values[0] = gyro[0] * GYRO_CONVERSION;
  153. values[1] = gyro[1] * GYRO_CONVERSION;
  154. values[2] = gyro[2] * GYRO_CONVERSION;
  155. if (hal_out.gyro_status & INV_NEW_DATA)
  156. status = 1;
  157. else
  158. status = 0;
  159. return status;
  160. }
  161. /**
  162. * This corresponds to Sensor.TYPE_ROTATION_VECTOR.
  163. * The rotation vector represents the orientation of the device as a combination
  164. * of an angle and an axis, in which the device has rotated through an angle @f$\theta@f$
  165. * around an axis {x, y, z}. <br>
  166. * The three elements of the rotation vector are
  167. * {x*sin(@f$\theta@f$/2), y*sin(@f$\theta@f$/2), z*sin(@f$\theta@f$/2)}, such that the magnitude of the rotation
  168. * vector is equal to sin(@f$\theta@f$/2), and the direction of the rotation vector is
  169. * equal to the direction of the axis of rotation.
  170. *
  171. * The three elements of the rotation vector are equal to the last three components of a unit quaternion
  172. * {x*sin(@f$\theta@f$/2), y*sin(@f$\theta@f$/2), z*sin(@f$\theta@f$/2)>. The 4th element is cos(@f$\theta@f$/2).
  173. *
  174. * Elements of the rotation vector are unitless. The x,y and z axis are defined in the same way as the acceleration sensor.
  175. * The reference coordinate system is defined as a direct orthonormal basis, where:
  176. -X is defined as the vector product Y.Z (It is tangential to the ground at the device's current location and roughly points East).
  177. -Y is tangential to the ground at the device's current location and points towards the magnetic North Pole.
  178. -Z points towards the sky and is perpendicular to the ground.
  179. * @param[out] values Length 4.
  180. * @param[out] accuracy Accuracy 0 to 3, 3 = most accurate
  181. * @param[out] timestamp Timestamp. In (ns) for Android.
  182. * @return Returns 1 if the data was updated or 0 if it was not updated.
  183. */
  184. int inv_get_sensor_type_rotation_vector(float *values, int8_t *accuracy,
  185. inv_time_t * timestamp)
  186. {
  187. *accuracy = (int8_t) hal_out.accuracy_quat;
  188. *timestamp = hal_out.nav_timestamp;
  189. if (hal_out.nav_quat[0] >= 0) {
  190. values[0] = hal_out.nav_quat[1] * INV_TWO_POWER_NEG_30;
  191. values[1] = hal_out.nav_quat[2] * INV_TWO_POWER_NEG_30;
  192. values[2] = hal_out.nav_quat[3] * INV_TWO_POWER_NEG_30;
  193. values[3] = hal_out.nav_quat[0] * INV_TWO_POWER_NEG_30;
  194. } else {
  195. values[0] = -hal_out.nav_quat[1] * INV_TWO_POWER_NEG_30;
  196. values[1] = -hal_out.nav_quat[2] * INV_TWO_POWER_NEG_30;
  197. values[2] = -hal_out.nav_quat[3] * INV_TWO_POWER_NEG_30;
  198. values[3] = -hal_out.nav_quat[0] * INV_TWO_POWER_NEG_30;
  199. }
  200. values[4] = inv_get_heading_confidence_interval();
  201. return hal_out.nine_axis_status;
  202. }
  203. /** Compass data (uT) in body frame.
  204. * @param[out] values Compass data in (uT), length 3. May be calibrated by having
  205. * biases removed and sensitivity adjusted
  206. * @param[out] accuracy Accuracy 0 to 3, 3 = most accurate
  207. * @param[out] timestamp Timestamp. In (ns) for Android.
  208. * @return Returns 1 if the data was updated or 0 if it was not updated.
  209. */
  210. int inv_get_sensor_type_magnetic_field(float *values, int8_t *accuracy,
  211. inv_time_t * timestamp)
  212. {
  213. int status;
  214. /* Converts fixed point to uT. Fixed point has 1 uT = 2^16.
  215. * So this is: 1 / 2^16*/
  216. //#define COMPASS_CONVERSION 1.52587890625e-005f
  217. int i;
  218. *timestamp = hal_out.mag_timestamp;
  219. *accuracy = (int8_t) hal_out.accuracy_mag;
  220. for (i=0; i<3; i++) {
  221. values[i] = hal_out.compass_float[i];
  222. }
  223. if (hal_out.compass_status & INV_NEW_DATA)
  224. status = 1;
  225. else
  226. status = 0;
  227. hal_out.compass_status = 0;
  228. return status;
  229. }
  230. static void inv_get_rotation(float r[3][3])
  231. {
  232. long rot[9];
  233. float conv = 1.f / (1L<<30);
  234. inv_quaternion_to_rotation(hal_out.nav_quat, rot);
  235. r[0][0] = rot[0]*conv;
  236. r[0][1] = rot[1]*conv;
  237. r[0][2] = rot[2]*conv;
  238. r[1][0] = rot[3]*conv;
  239. r[1][1] = rot[4]*conv;
  240. r[1][2] = rot[5]*conv;
  241. r[2][0] = rot[6]*conv;
  242. r[2][1] = rot[7]*conv;
  243. r[2][2] = rot[8]*conv;
  244. }
  245. static void google_orientation(float *g)
  246. {
  247. float rad2deg = (float)(180.0 / M_PI);
  248. float R[3][3];
  249. inv_get_rotation(R);
  250. g[0] = atan2f(-R[1][0], R[0][0]) * rad2deg;
  251. g[1] = atan2f(-R[2][1], R[2][2]) * rad2deg;
  252. g[2] = asinf ( R[2][0]) * rad2deg;
  253. if (g[0] < 0)
  254. g[0] += 360;
  255. }
  256. /** This corresponds to Sensor.TYPE_ORIENTATION. All values are angles in degrees.
  257. * @param[out] values Length 3, Degrees.<br>
  258. * - values[0]: Azimuth, angle between the magnetic north direction
  259. * and the y-axis, around the z-axis (0 to 359). 0=North, 90=East, 180=South, 270=West<br>
  260. * - values[1]: Pitch, rotation around x-axis (-180 to 180), with positive values
  261. * when the z-axis moves toward the y-axis.<br>
  262. * - values[2]: Roll, rotation around y-axis (-90 to 90), with positive
  263. * values when the x-axis moves toward the z-axis.<br>
  264. *
  265. * @note This definition is different from yaw, pitch and roll used in aviation
  266. * where the X axis is along the long side of the plane (tail to nose).
  267. * Note: This sensor type exists for legacy reasons, please use getRotationMatrix()
  268. * in conjunction with remapCoordinateSystem() and getOrientation() to compute
  269. * these values instead.
  270. * Important note: For historical reasons the roll angle is positive in the
  271. * clockwise direction (mathematically speaking, it should be positive in
  272. * the counter-clockwise direction).
  273. * @param[out] accuracy Accuracy of the measurment, 0 is least accurate, while 3 is most accurate.
  274. * @param[out] timestamp The timestamp for this sensor.
  275. * @return Returns 1 if the data was updated or 0 if it was not updated.
  276. */
  277. int inv_get_sensor_type_orientation(float *values, int8_t *accuracy,
  278. inv_time_t * timestamp)
  279. {
  280. *accuracy = (int8_t) hal_out.accuracy_quat;
  281. *timestamp = hal_out.nav_timestamp;
  282. google_orientation(values);
  283. return hal_out.nine_axis_status;
  284. }
  285. /** Main callback to generate HAL outputs. Typically not called by library users.
  286. * @param[in] sensor_cal Input variable to take sensor data whenever there is new
  287. * sensor data.
  288. * @return Returns INV_SUCCESS if successful or an error code if not.
  289. */
  290. inv_error_t inv_generate_hal_outputs(struct inv_sensor_cal_t *sensor_cal)
  291. {
  292. int use_sensor = 0;
  293. long sr = 1000;
  294. long compass[3];
  295. int8_t accuracy;
  296. int i;
  297. (void) sensor_cal;
  298. inv_get_quaternion_set(hal_out.nav_quat, &hal_out.accuracy_quat,
  299. &hal_out.nav_timestamp);
  300. hal_out.gyro_status = sensor_cal->gyro.status;
  301. hal_out.accel_status = sensor_cal->accel.status;
  302. hal_out.compass_status = sensor_cal->compass.status;
  303. // Find the highest sample rate and tie generating 9-axis to that one.
  304. if (sensor_cal->gyro.status & INV_SENSOR_ON) {
  305. sr = sensor_cal->gyro.sample_rate_ms;
  306. use_sensor = 0;
  307. }
  308. if ((sensor_cal->accel.status & INV_SENSOR_ON) && (sr > sensor_cal->accel.sample_rate_ms)) {
  309. sr = sensor_cal->accel.sample_rate_ms;
  310. use_sensor = 1;
  311. }
  312. if ((sensor_cal->compass.status & INV_SENSOR_ON) && (sr > sensor_cal->compass.sample_rate_ms)) {
  313. sr = sensor_cal->compass.sample_rate_ms;
  314. use_sensor = 2;
  315. }
  316. if ((sensor_cal->quat.status & INV_SENSOR_ON) && (sr > sensor_cal->quat.sample_rate_ms)) {
  317. sr = sensor_cal->quat.sample_rate_ms;
  318. use_sensor = 3;
  319. }
  320. // Only output 9-axis if all 9 sensors are on.
  321. if (sensor_cal->quat.status & INV_SENSOR_ON) {
  322. // If quaternion sensor is on, gyros are not required as quaternion already has that part
  323. if ((sensor_cal->accel.status & sensor_cal->compass.status & INV_SENSOR_ON) == 0) {
  324. use_sensor = -1;
  325. }
  326. } else {
  327. if ((sensor_cal->gyro.status & sensor_cal->accel.status & sensor_cal->compass.status & INV_SENSOR_ON) == 0) {
  328. use_sensor = -1;
  329. }
  330. }
  331. switch (use_sensor) {
  332. case 0:
  333. hal_out.nine_axis_status = (sensor_cal->gyro.status & INV_NEW_DATA) ? 1 : 0;
  334. hal_out.nav_timestamp = sensor_cal->gyro.timestamp;
  335. break;
  336. case 1:
  337. hal_out.nine_axis_status = (sensor_cal->accel.status & INV_NEW_DATA) ? 1 : 0;
  338. hal_out.nav_timestamp = sensor_cal->accel.timestamp;
  339. break;
  340. case 2:
  341. hal_out.nine_axis_status = (sensor_cal->compass.status & INV_NEW_DATA) ? 1 : 0;
  342. hal_out.nav_timestamp = sensor_cal->compass.timestamp;
  343. break;
  344. case 3:
  345. hal_out.nine_axis_status = (sensor_cal->quat.status & INV_NEW_DATA) ? 1 : 0;
  346. hal_out.nav_timestamp = sensor_cal->quat.timestamp;
  347. break;
  348. default:
  349. hal_out.nine_axis_status = 0; // Don't output quaternion related info
  350. break;
  351. }
  352. /* Converts fixed point to uT. Fixed point has 1 uT = 2^16.
  353. * So this is: 1 / 2^16*/
  354. #define COMPASS_CONVERSION 1.52587890625e-005f
  355. inv_get_compass_set(compass, &accuracy, &(hal_out.mag_timestamp) );
  356. hal_out.accuracy_mag = (int ) accuracy;
  357. for (i=0; i<3; i++) {
  358. if ((sensor_cal->compass.status & (INV_NEW_DATA | INV_CONTIGUOUS)) ==
  359. INV_NEW_DATA ) {
  360. // set the state variables to match output with input
  361. inv_calc_state_to_match_output(&hal_out.lp_filter[i], (float ) compass[i]);
  362. }
  363. if ((sensor_cal->compass.status & (INV_NEW_DATA | INV_RAW_DATA)) ==
  364. (INV_NEW_DATA | INV_RAW_DATA) ) {
  365. hal_out.compass_float[i] = inv_biquad_filter_process(&hal_out.lp_filter[i],
  366. (float ) compass[i]) * COMPASS_CONVERSION;
  367. } else if ((sensor_cal->compass.status & INV_NEW_DATA) == INV_NEW_DATA ) {
  368. hal_out.compass_float[i] = (float ) compass[i] * COMPASS_CONVERSION;
  369. }
  370. }
  371. return INV_SUCCESS;
  372. }
  373. /** Turns off generation of HAL outputs.
  374. * @return Returns INV_SUCCESS if successful or an error code if not.
  375. */
  376. inv_error_t inv_stop_hal_outputs(void)
  377. {
  378. inv_error_t result;
  379. result = inv_unregister_data_cb(inv_generate_hal_outputs);
  380. return result;
  381. }
  382. /** Turns on generation of HAL outputs. This should be called after inv_stop_hal_outputs()
  383. * to turn generation of HAL outputs back on. It is automatically called by inv_enable_hal_outputs().
  384. * @return Returns INV_SUCCESS if successful or an error code if not.
  385. */
  386. inv_error_t inv_start_hal_outputs(void)
  387. {
  388. inv_error_t result;
  389. result =
  390. inv_register_data_cb(inv_generate_hal_outputs,
  391. INV_PRIORITY_HAL_OUTPUTS,
  392. INV_GYRO_NEW | INV_ACCEL_NEW | INV_MAG_NEW);
  393. return result;
  394. }
  395. /* file name: lowPassFilterCoeff_1_6.c */
  396. float compass_low_pass_filter_coeff[5] =
  397. {+2.000000000000f, +1.000000000000f, -1.279632424998f, +0.477592250073f, +0.049489956269f};
  398. /** Initializes hal outputs class. This is called automatically by the
  399. * enable function. It may be called any time the feature is enabled, but
  400. * is typically not needed to be called by outside callers.
  401. * @return Returns INV_SUCCESS if successful or an error code if not.
  402. */
  403. inv_error_t inv_init_hal_outputs(void)
  404. {
  405. int i;
  406. memset(&hal_out, 0, sizeof(hal_out));
  407. for (i=0; i<3; i++) {
  408. inv_init_biquad_filter(&hal_out.lp_filter[i], compass_low_pass_filter_coeff);
  409. }
  410. return INV_SUCCESS;
  411. }
  412. /** Turns on creation and storage of HAL type results.
  413. * @return Returns INV_SUCCESS if successful or an error code if not.
  414. */
  415. inv_error_t inv_enable_hal_outputs(void)
  416. {
  417. inv_error_t result;
  418. // don't need to check the result for inv_init_hal_outputs
  419. // since it's always INV_SUCCESS
  420. inv_init_hal_outputs();
  421. result = inv_register_mpl_start_notification(inv_start_hal_outputs);
  422. return result;
  423. }
  424. /** Turns off creation and storage of HAL type results.
  425. */
  426. inv_error_t inv_disable_hal_outputs(void)
  427. {
  428. inv_error_t result;
  429. inv_stop_hal_outputs(); // Ignore error if we have already stopped this
  430. result = inv_unregister_mpl_start_notification(inv_start_hal_outputs);
  431. return result;
  432. }
  433. /**
  434. * @}
  435. */