Icm20948Augmented.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * ________________________________________________________________________________________________________
  3. * Copyright © 2014-2015 InvenSense Inc. Portions Copyright © 2014-2015 Movea. All rights reserved.
  4. * This software, related documentation and any modifications thereto (collectively “Software”) is subject
  5. * to InvenSense and its licensors' intellectual property rights under U.S. and international copyright and
  6. * other intellectual property rights laws.
  7. * InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
  8. * and any use, reproduction, disclosure or distribution of the Software without an express license
  9. * agreement from InvenSense is strictly prohibited.
  10. * ________________________________________________________________________________________________________
  11. */
  12. #include "Icm20948.h"
  13. #include "Icm20948Augmented.h"
  14. #include "Icm20948DataConverter.h"
  15. #include "Icm20948DataBaseControl.h"
  16. // Determine the fastest ODR for all gravity-based sensors
  17. #define AUGMENTED_SENSOR_GET_6QUAT_MIN_ODR(s, newOdr) \
  18. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_GRAVITY)) \
  19. newOdr = MIN(s->sGravityOdrMs,newOdr); \
  20. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_GAME_ROTATION_VECTOR)) \
  21. newOdr = MIN(s->sGrvOdrMs,newOdr); \
  22. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_LINEAR_ACCELERATION)) \
  23. newOdr = MIN(s->sLinAccOdrMs,newOdr);
  24. #define AUGMENTED_SENSOR_GET_6QUATWU_MIN_ODR(s, newOdr) \
  25. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_WAKEUP_GRAVITY)) \
  26. newOdr = MIN(s->sGravityWuOdrMs,newOdr); \
  27. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_WAKEUP_GAME_ROTATION_VECTOR)) \
  28. newOdr = MIN(s->sGrvWuOdrMs,newOdr); \
  29. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_WAKEUP_LINEAR_ACCELERATION)) \
  30. newOdr = MIN(s->sLinAccWuOdrMs,newOdr);
  31. // Determine the fastest ODR for all rotation vector-based sensors
  32. #define AUGMENTED_SENSOR_GET_9QUAT_MIN_ODR(s, newOdr) \
  33. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_ORIENTATION)) \
  34. newOdr = MIN(s->sOriOdrMs,newOdr); \
  35. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_ROTATION_VECTOR)) \
  36. newOdr = MIN(s->sRvOdrMs,newOdr);
  37. #define AUGMENTED_SENSOR_GET_9QUATWU_MIN_ODR(s, newOdr) \
  38. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_WAKEUP_ORIENTATION)) \
  39. newOdr = MIN(s->sOriWuOdrMs,newOdr); \
  40. if (inv_icm20948_ctrl_androidSensor_enabled (s, ANDROID_SENSOR_WAKEUP_ROTATION_VECTOR)) \
  41. newOdr = MIN(s->sRvWuOdrMs,newOdr);
  42. int inv_icm20948_augmented_init(struct inv_icm20948 * s)
  43. {
  44. // ODR expected for gravity-based sensors
  45. s->sGravityOdrMs = 0xFFFF;
  46. s->sGrvOdrMs = 0xFFFF;
  47. s->sLinAccOdrMs = 0xFFFF;
  48. s->sGravityWuOdrMs = 0xFFFF;
  49. s->sGrvWuOdrMs = 0xFFFF;
  50. s->sLinAccWuOdrMs = 0xFFFF;
  51. // ODR expected for rotation vector-based sensors
  52. s->sRvOdrMs = 0xFFFF;
  53. s->sOriOdrMs = 0xFFFF;
  54. s->sRvWuOdrMs = 0xFFFF;
  55. s->sOriWuOdrMs = 0xFFFF;
  56. return 0;
  57. }
  58. int inv_icm20948_augmented_sensors_get_gravity(struct inv_icm20948 * s, long gravity[3], const long quat6axis_3e[3])
  59. {
  60. long quat6axis_4e[4];
  61. long quat6axis_4e_body_to_world[4];
  62. if(!gravity) return -1;
  63. if(!quat6axis_3e) return -1;
  64. // compute w element
  65. inv_icm20948_convert_compute_scalar_part_fxp(quat6axis_3e, quat6axis_4e);
  66. // apply mounting matrix
  67. inv_icm20948_q_mult_q_qi(quat6axis_4e, s->s_quat_chip_to_body, quat6axis_4e_body_to_world);
  68. gravity[0] = ( 2 * inv_icm20948_convert_mult_qfix_fxp(quat6axis_4e_body_to_world[1], quat6axis_4e_body_to_world[3], 30) -
  69. 2 * inv_icm20948_convert_mult_qfix_fxp(quat6axis_4e_body_to_world[0], quat6axis_4e_body_to_world[2], 30) ) >> (30 - 16);
  70. gravity[1] = ( 2 * inv_icm20948_convert_mult_qfix_fxp(quat6axis_4e_body_to_world[2], quat6axis_4e_body_to_world[3], 30) +
  71. 2 * inv_icm20948_convert_mult_qfix_fxp(quat6axis_4e_body_to_world[0], quat6axis_4e_body_to_world[1], 30) ) >> (30 - 16);
  72. gravity[2] = ( (1 << 30) - 2 * inv_icm20948_convert_mult_qfix_fxp(quat6axis_4e_body_to_world[1], quat6axis_4e_body_to_world[1], 30) -
  73. 2 * inv_icm20948_convert_mult_qfix_fxp(quat6axis_4e_body_to_world[2], quat6axis_4e_body_to_world[2], 30) ) >> (30 - 16);
  74. return MPU_SUCCESS;
  75. }
  76. int inv_icm20948_augmented_sensors_get_linearacceleration(long linacc[3], const long gravity[3], const long accel[3])
  77. {
  78. if(!linacc) return -1;
  79. if(!gravity) return -1;
  80. if(!accel) return -1;
  81. linacc[0] = accel[0] - gravity[0];
  82. linacc[1] = accel[1] - gravity[1];
  83. linacc[2] = accel[2] - gravity[2];
  84. return MPU_SUCCESS;
  85. }
  86. int inv_icm20948_augmented_sensors_get_orientation(long orientation[3], const long quat9axis_3e[4])
  87. {
  88. long lQuat9axis4e[4];
  89. long lMatrixQ30[9];
  90. long lMatrixQ30Square;
  91. long lRad2degQ16 = 0x394BB8; // (float)(180.0 / 3.14159265358979) in Q16
  92. if(!orientation) return -1;
  93. if(!quat9axis_3e) return -1;
  94. // compute w element
  95. inv_icm20948_convert_compute_scalar_part_fxp(quat9axis_3e, lQuat9axis4e);
  96. // quaternion to a rotation matrix, q30 to q30
  97. inv_icm20948_convert_quat_to_col_major_matrix_fxp((const long *)lQuat9axis4e, (long *)lMatrixQ30);
  98. // compute orientation in q16
  99. // orientationFlt[0] = atan2f(-matrixFlt[1][0], matrixFlt[0][0]) * rad2deg;
  100. orientation[0] = inv_icm20948_math_atan2_q15_fxp(-lMatrixQ30[3] >> 15, lMatrixQ30[0] >> 15) << 1;
  101. orientation[0] = inv_icm20948_convert_mult_qfix_fxp(orientation[0], lRad2degQ16, 16);
  102. // orientationFlt[1] = atan2f(-matrixFlt[2][1], matrixFlt[2][2]) * rad2deg;
  103. orientation[1] = inv_icm20948_math_atan2_q15_fxp(-lMatrixQ30[7] >> 15, lMatrixQ30[8] >> 15) << 1;
  104. orientation[1] = inv_icm20948_convert_mult_qfix_fxp(orientation[1], lRad2degQ16, 16);
  105. // orientationFlt[2] = asinf ( matrixFlt[2][0]) * rad2deg;
  106. // asin(x) = atan (x/sqrt(1-x²))
  107. // atan2(y,x) = atan(y/x)
  108. // asin(x) = atan2(x, sqrt(1-x²))
  109. lMatrixQ30Square = inv_icm20948_convert_mult_qfix_fxp(lMatrixQ30[6], lMatrixQ30[6], 30); // x²
  110. lMatrixQ30Square = (1UL << 30) - lMatrixQ30Square; // 1-x²
  111. lMatrixQ30Square = inv_icm20948_convert_fast_sqrt_fxp(lMatrixQ30Square); // sqrt(1-x²)
  112. orientation[2] = inv_icm20948_math_atan2_q15_fxp(lMatrixQ30[6] >> 15, lMatrixQ30Square >> 15) << 1; // atan2(x, sqrt(1-x²))
  113. orientation[2] = inv_icm20948_convert_mult_qfix_fxp(orientation[2], lRad2degQ16, 16); // * rad2deg
  114. if (orientation[0] < 0)
  115. orientation[0] += 360UL << 16;
  116. return MPU_SUCCESS;
  117. }
  118. unsigned short inv_icm20948_augmented_sensors_set_odr(struct inv_icm20948 * s, unsigned char androidSensor, unsigned short delayInMs)
  119. {
  120. switch(androidSensor)
  121. {
  122. case ANDROID_SENSOR_GRAVITY:
  123. s->sGravityOdrMs = delayInMs;
  124. AUGMENTED_SENSOR_GET_6QUAT_MIN_ODR(s, delayInMs);
  125. break;
  126. case ANDROID_SENSOR_GAME_ROTATION_VECTOR:
  127. s->sGrvOdrMs = delayInMs;
  128. AUGMENTED_SENSOR_GET_6QUAT_MIN_ODR(s, delayInMs);
  129. break;
  130. case ANDROID_SENSOR_LINEAR_ACCELERATION:
  131. s->sLinAccOdrMs = delayInMs;
  132. AUGMENTED_SENSOR_GET_6QUAT_MIN_ODR(s, delayInMs);
  133. break;
  134. case ANDROID_SENSOR_ORIENTATION:
  135. s->sOriOdrMs = delayInMs;
  136. AUGMENTED_SENSOR_GET_9QUAT_MIN_ODR(s, delayInMs);
  137. break;
  138. case ANDROID_SENSOR_ROTATION_VECTOR:
  139. s->sRvOdrMs = delayInMs;
  140. AUGMENTED_SENSOR_GET_9QUAT_MIN_ODR(s, delayInMs);
  141. break;
  142. case ANDROID_SENSOR_WAKEUP_GRAVITY:
  143. s->sGravityWuOdrMs = delayInMs;
  144. AUGMENTED_SENSOR_GET_6QUATWU_MIN_ODR(s, delayInMs);
  145. break;
  146. case ANDROID_SENSOR_WAKEUP_GAME_ROTATION_VECTOR:
  147. s->sGrvWuOdrMs = delayInMs;
  148. AUGMENTED_SENSOR_GET_6QUATWU_MIN_ODR(s, delayInMs);
  149. break;
  150. case ANDROID_SENSOR_WAKEUP_LINEAR_ACCELERATION:
  151. s->sLinAccWuOdrMs = delayInMs;
  152. AUGMENTED_SENSOR_GET_6QUATWU_MIN_ODR(s, delayInMs);
  153. break;
  154. case ANDROID_SENSOR_WAKEUP_ORIENTATION:
  155. s->sOriWuOdrMs = delayInMs;
  156. AUGMENTED_SENSOR_GET_9QUATWU_MIN_ODR(s, delayInMs);
  157. break;
  158. case ANDROID_SENSOR_WAKEUP_ROTATION_VECTOR:
  159. s->sRvWuOdrMs = delayInMs;
  160. AUGMENTED_SENSOR_GET_9QUATWU_MIN_ODR(s, delayInMs);
  161. break;
  162. default :
  163. break;
  164. }
  165. return delayInMs;
  166. }
  167. void inv_icm20948_augmented_sensors_update_odr(struct inv_icm20948 * s, unsigned char androidSensor, unsigned short * updatedDelayPtr)
  168. {
  169. unsigned short lDelayInMs = 0xFFFF; // max value of uint16_t, so that we can get min value of all enabled sensors
  170. switch(androidSensor)
  171. {
  172. case ANDROID_SENSOR_GRAVITY:
  173. case ANDROID_SENSOR_GAME_ROTATION_VECTOR:
  174. case ANDROID_SENSOR_LINEAR_ACCELERATION:
  175. AUGMENTED_SENSOR_GET_6QUAT_MIN_ODR(s, lDelayInMs);
  176. *updatedDelayPtr = lDelayInMs;
  177. break;
  178. case ANDROID_SENSOR_WAKEUP_GRAVITY:
  179. case ANDROID_SENSOR_WAKEUP_GAME_ROTATION_VECTOR:
  180. case ANDROID_SENSOR_WAKEUP_LINEAR_ACCELERATION:
  181. AUGMENTED_SENSOR_GET_6QUATWU_MIN_ODR(s, lDelayInMs);
  182. *updatedDelayPtr = lDelayInMs;
  183. break;
  184. case ANDROID_SENSOR_ORIENTATION:
  185. case ANDROID_SENSOR_ROTATION_VECTOR:
  186. AUGMENTED_SENSOR_GET_9QUAT_MIN_ODR(s, lDelayInMs);
  187. *updatedDelayPtr = lDelayInMs;
  188. break;
  189. case ANDROID_SENSOR_WAKEUP_ORIENTATION:
  190. case ANDROID_SENSOR_WAKEUP_ROTATION_VECTOR:
  191. AUGMENTED_SENSOR_GET_9QUATWU_MIN_ODR(s, lDelayInMs);
  192. *updatedDelayPtr = lDelayInMs;
  193. break;
  194. default :
  195. break;
  196. }
  197. }