PageRenderTime 90ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/EDVSBoardOS/MotionDriver/mllite/ml_math_func.c

https://bitbucket.org/rui_araujo/edvsboardos
C | 780 lines | 525 code | 83 blank | 172 comment | 57 complexity | 97859dbbdb292a49ac1e4e65d0a275e2 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. *
  9. * $Id:$
  10. *
  11. ******************************************************************************/
  12. /**
  13. * @defgroup ML_MATH_FUNC ml_math_func
  14. * @brief Motion Library - Math Functions
  15. * Common math functions the Motion Library
  16. *
  17. * @{
  18. * @file ml_math_func.c
  19. * @brief Math Functions.
  20. */
  21. #include "mlmath.h"
  22. #include "ml_math_func.h"
  23. #include "mlinclude.h"
  24. #include <string.h>
  25. #ifdef EMPL
  26. #define TABLE_SIZE (256)
  27. /* TODO: If memory becomes a big issue, we can just store the data for a single
  28. * quadrant and transform the inputs and outputs of the lookup functions.
  29. */
  30. const float sin_lookup[TABLE_SIZE] = {
  31. 0.000000f, 0.024541f, 0.049068f, 0.073565f, 0.098017f, 0.122411f, 0.146730f, 0.170962f,
  32. 0.195090f, 0.219101f, 0.242980f, 0.266713f, 0.290285f, 0.313682f, 0.336890f, 0.359895f,
  33. 0.382683f, 0.405241f, 0.427555f, 0.449611f, 0.471397f, 0.492898f, 0.514103f, 0.534998f,
  34. 0.555570f, 0.575808f, 0.595699f, 0.615232f, 0.634393f, 0.653173f, 0.671559f, 0.689541f,
  35. 0.707107f, 0.724247f, 0.740951f, 0.757209f, 0.773010f, 0.788346f, 0.803208f, 0.817585f,
  36. 0.831470f, 0.844854f, 0.857729f, 0.870087f, 0.881921f, 0.893224f, 0.903989f, 0.914210f,
  37. 0.923880f, 0.932993f, 0.941544f, 0.949528f, 0.956940f, 0.963776f, 0.970031f, 0.975702f,
  38. 0.980785f, 0.985278f, 0.989177f, 0.992480f, 0.995185f, 0.997290f, 0.998795f, 0.999699f,
  39. 1.000000f, 0.999699f, 0.998795f, 0.997290f, 0.995185f, 0.992480f, 0.989177f, 0.985278f,
  40. 0.980785f, 0.975702f, 0.970031f, 0.963776f, 0.956940f, 0.949528f, 0.941544f, 0.932993f,
  41. 0.923880f, 0.914210f, 0.903989f, 0.893224f, 0.881921f, 0.870087f, 0.857729f, 0.844854f,
  42. 0.831470f, 0.817585f, 0.803208f, 0.788346f, 0.773010f, 0.757209f, 0.740951f, 0.724247f,
  43. 0.707107f, 0.689541f, 0.671559f, 0.653173f, 0.634393f, 0.615232f, 0.595699f, 0.575808f,
  44. 0.555570f, 0.534998f, 0.514103f, 0.492898f, 0.471397f, 0.449611f, 0.427555f, 0.405241f,
  45. 0.382683f, 0.359895f, 0.336890f, 0.313682f, 0.290285f, 0.266713f, 0.242980f, 0.219101f,
  46. 0.195091f, 0.170962f, 0.146731f, 0.122411f, 0.098017f, 0.073565f, 0.049068f, 0.024541f,
  47. 0.000000f, -0.024541f, -0.049067f, -0.073564f, -0.098017f, -0.122411f, -0.146730f, -0.170962f,
  48. -0.195090f, -0.219101f, -0.242980f, -0.266713f, -0.290284f, -0.313682f, -0.336890f, -0.359895f,
  49. -0.382683f, -0.405241f, -0.427555f, -0.449611f, -0.471397f, -0.492898f, -0.514103f, -0.534997f,
  50. -0.555570f, -0.575808f, -0.595699f, -0.615231f, -0.634393f, -0.653173f, -0.671559f, -0.689540f,
  51. -0.707107f, -0.724247f, -0.740951f, -0.757209f, -0.773010f, -0.788346f, -0.803207f, -0.817585f,
  52. -0.831469f, -0.844853f, -0.857729f, -0.870087f, -0.881921f, -0.893224f, -0.903989f, -0.914210f,
  53. -0.923880f, -0.932993f, -0.941544f, -0.949528f, -0.956940f, -0.963776f, -0.970031f, -0.975702f,
  54. -0.980785f, -0.985278f, -0.989176f, -0.992480f, -0.995185f, -0.997290f, -0.998795f, -0.999699f,
  55. -1.000000f, -0.999699f, -0.998795f, -0.997290f, -0.995185f, -0.992480f, -0.989177f, -0.985278f,
  56. -0.980785f, -0.975702f, -0.970031f, -0.963776f, -0.956940f, -0.949528f, -0.941544f, -0.932993f,
  57. -0.923880f, -0.914210f, -0.903989f, -0.893224f, -0.881921f, -0.870087f, -0.857729f, -0.844854f,
  58. -0.831470f, -0.817585f, -0.803208f, -0.788347f, -0.773011f, -0.757209f, -0.740951f, -0.724247f,
  59. -0.707107f, -0.689541f, -0.671559f, -0.653173f, -0.634394f, -0.615232f, -0.595699f, -0.575808f,
  60. -0.555570f, -0.534998f, -0.514103f, -0.492898f, -0.471397f, -0.449612f, -0.427555f, -0.405241f,
  61. -0.382684f, -0.359895f, -0.336890f, -0.313682f, -0.290285f, -0.266713f, -0.242981f, -0.219102f,
  62. -0.195091f, -0.170962f, -0.146731f, -0.122411f, -0.098017f, -0.073565f, -0.049068f, -0.024542f
  63. };
  64. float inv_sinf(float x)
  65. {
  66. int index = (unsigned int)((x * (TABLE_SIZE>>1)) / 3.14159f) % TABLE_SIZE;
  67. return sin_lookup[index];
  68. }
  69. float inv_cosf(float x)
  70. {
  71. int index = ((unsigned int)((x * (TABLE_SIZE>>1)) / 3.14159f) + (TABLE_SIZE>>2)) % TABLE_SIZE;
  72. return sin_lookup[index];
  73. }
  74. #endif
  75. /** @internal
  76. * Does the cross product of compass by gravity, then converts that
  77. * to the world frame using the quaternion, then computes the angle that
  78. * is made.
  79. *
  80. * @param[in] compass Compass Vector (Body Frame), length 3
  81. * @param[in] grav Gravity Vector (Body Frame), length 3
  82. * @param[in] quat Quaternion, Length 4
  83. * @return Angle Cross Product makes after quaternion rotation.
  84. */
  85. float inv_compass_angle(const long *compass, const long *grav, const long *quat)
  86. {
  87. long cgcross[4], q1[4], q2[4], qi[4];
  88. float angW;
  89. // Compass cross Gravity
  90. cgcross[0] = 0L;
  91. cgcross[1] = inv_q30_mult(compass[1], grav[2]) - inv_q30_mult(compass[2], grav[1]);
  92. cgcross[2] = inv_q30_mult(compass[2], grav[0]) - inv_q30_mult(compass[0], grav[2]);
  93. cgcross[3] = inv_q30_mult(compass[0], grav[1]) - inv_q30_mult(compass[1], grav[0]);
  94. // Now convert cross product into world frame
  95. inv_q_mult(quat, cgcross, q1);
  96. inv_q_invert(quat, qi);
  97. inv_q_mult(q1, qi, q2);
  98. // Protect against atan2 of 0,0
  99. if ((q2[2] == 0L) && (q2[1] == 0L))
  100. return 0.f;
  101. // This is the unfiltered heading correction
  102. angW = -atan2f(inv_q30_to_float(q2[2]), inv_q30_to_float(q2[1]));
  103. return angW;
  104. }
  105. /**
  106. * @brief The gyro data magnitude squared :
  107. * (1 degree per second)^2 = 2^6 = 2^GYRO_MAG_SQR_SHIFT.
  108. * @param[in] gyro Gyro data scaled with 1 dps = 2^16
  109. * @return the computed magnitude squared output of the gyroscope.
  110. */
  111. unsigned long inv_get_gyro_sum_of_sqr(const long *gyro)
  112. {
  113. unsigned long gmag = 0;
  114. long temp;
  115. int kk;
  116. for (kk = 0; kk < 3; ++kk) {
  117. temp = gyro[kk] >> (16 - (GYRO_MAG_SQR_SHIFT / 2));
  118. gmag += temp * temp;
  119. }
  120. return gmag;
  121. }
  122. /** Performs a multiply and shift by 29. These are good functions to write in assembly on
  123. * with devices with small memory where you want to get rid of the long long which some
  124. * assemblers don't handle well
  125. * @param[in] a
  126. * @param[in] b
  127. * @return ((long long)a*b)>>29
  128. */
  129. long inv_q29_mult(long a, long b)
  130. {
  131. #ifdef EMPL_NO_64BIT
  132. long result;
  133. result = (long)((float)a * b / (1L << 29));
  134. return result;
  135. #else
  136. long long temp;
  137. long result;
  138. temp = (long long)a * b;
  139. result = (long)(temp >> 29);
  140. return result;
  141. #endif
  142. }
  143. /** Performs a multiply and shift by 30. These are good functions to write in assembly on
  144. * with devices with small memory where you want to get rid of the long long which some
  145. * assemblers don't handle well
  146. * @param[in] a
  147. * @param[in] b
  148. * @return ((long long)a*b)>>30
  149. */
  150. long inv_q30_mult(long a, long b)
  151. {
  152. #ifdef EMPL_NO_64BIT
  153. long result;
  154. result = (long)((float)a * b / (1L << 30));
  155. return result;
  156. #else
  157. long long temp;
  158. long result;
  159. temp = (long long)a * b;
  160. result = (long)(temp >> 30);
  161. return result;
  162. #endif
  163. }
  164. #ifndef EMPL_NO_64BIT
  165. long inv_q30_div(long a, long b)
  166. {
  167. long long temp;
  168. long result;
  169. temp = (((long long)a) << 30) / b;
  170. result = (long)temp;
  171. return result;
  172. }
  173. #endif
  174. /** Performs a multiply and shift by shift. These are good functions to write
  175. * in assembly on with devices with small memory where you want to get rid of
  176. * the long long which some assemblers don't handle well
  177. * @param[in] a First multicand
  178. * @param[in] b Second multicand
  179. * @param[in] shift Shift amount after multiplying
  180. * @return ((long long)a*b)<<shift
  181. */
  182. #ifndef EMPL_NO_64BIT
  183. long inv_q_shift_mult(long a, long b, int shift)
  184. {
  185. long result;
  186. result = (long)(((long long)a * b) >> shift);
  187. return result;
  188. }
  189. #endif
  190. /** Performs a fixed point quaternion multiply.
  191. * @param[in] q1 First Quaternion Multicand, length 4. 1.0 scaled
  192. * to 2^30
  193. * @param[in] q2 Second Quaternion Multicand, length 4. 1.0 scaled
  194. * to 2^30
  195. * @param[out] qProd Product after quaternion multiply. Length 4.
  196. * 1.0 scaled to 2^30.
  197. */
  198. void inv_q_mult(const long *q1, const long *q2, long *qProd)
  199. {
  200. INVENSENSE_FUNC_START;
  201. qProd[0] = inv_q30_mult(q1[0], q2[0]) - inv_q30_mult(q1[1], q2[1]) -
  202. inv_q30_mult(q1[2], q2[2]) - inv_q30_mult(q1[3], q2[3]);
  203. qProd[1] = inv_q30_mult(q1[0], q2[1]) + inv_q30_mult(q1[1], q2[0]) +
  204. inv_q30_mult(q1[2], q2[3]) - inv_q30_mult(q1[3], q2[2]);
  205. qProd[2] = inv_q30_mult(q1[0], q2[2]) - inv_q30_mult(q1[1], q2[3]) +
  206. inv_q30_mult(q1[2], q2[0]) + inv_q30_mult(q1[3], q2[1]);
  207. qProd[3] = inv_q30_mult(q1[0], q2[3]) + inv_q30_mult(q1[1], q2[2]) -
  208. inv_q30_mult(q1[2], q2[1]) + inv_q30_mult(q1[3], q2[0]);
  209. }
  210. /** Performs a fixed point quaternion addition.
  211. * @param[in] q1 First Quaternion term, length 4. 1.0 scaled
  212. * to 2^30
  213. * @param[in] q2 Second Quaternion term, length 4. 1.0 scaled
  214. * to 2^30
  215. * @param[out] qSum Sum after quaternion summation. Length 4.
  216. * 1.0 scaled to 2^30.
  217. */
  218. void inv_q_add(long *q1, long *q2, long *qSum)
  219. {
  220. INVENSENSE_FUNC_START;
  221. qSum[0] = q1[0] + q2[0];
  222. qSum[1] = q1[1] + q2[1];
  223. qSum[2] = q1[2] + q2[2];
  224. qSum[3] = q1[3] + q2[3];
  225. }
  226. void inv_vector_normalize(long *vec, int length)
  227. {
  228. INVENSENSE_FUNC_START;
  229. double normSF = 0;
  230. int ii;
  231. for (ii = 0; ii < length; ii++) {
  232. normSF +=
  233. inv_q30_to_double(vec[ii]) * inv_q30_to_double(vec[ii]);
  234. }
  235. if (normSF > 0) {
  236. normSF = 1 / sqrt(normSF);
  237. for (ii = 0; ii < length; ii++) {
  238. vec[ii] = (int)((double)vec[ii] * normSF);
  239. }
  240. } else {
  241. vec[0] = 1073741824L;
  242. for (ii = 1; ii < length; ii++) {
  243. vec[ii] = 0;
  244. }
  245. }
  246. }
  247. void inv_q_normalize(long *q)
  248. {
  249. INVENSENSE_FUNC_START;
  250. inv_vector_normalize(q, 4);
  251. }
  252. void inv_q_invert(const long *q, long *qInverted)
  253. {
  254. INVENSENSE_FUNC_START;
  255. qInverted[0] = q[0];
  256. qInverted[1] = -q[1];
  257. qInverted[2] = -q[2];
  258. qInverted[3] = -q[3];
  259. }
  260. double quaternion_to_rotation_angle(const long *quat) {
  261. double quat0 = (double )quat[0] / 1073741824;
  262. if (quat0 > 1.0f) {
  263. quat0 = 1.0;
  264. } else if (quat0 < -1.0f) {
  265. quat0 = -1.0;
  266. }
  267. return acos(quat0)*2*180/M_PI;
  268. }
  269. /** Rotates a 3-element vector by Rotation defined by Q
  270. */
  271. void inv_q_rotate(const long *q, const long *in, long *out)
  272. {
  273. long q_temp1[4], q_temp2[4];
  274. long in4[4], out4[4];
  275. // Fixme optimize
  276. in4[0] = 0;
  277. memcpy(&in4[1], in, 3 * sizeof(long));
  278. inv_q_mult(q, in4, q_temp1);
  279. inv_q_invert(q, q_temp2);
  280. inv_q_mult(q_temp1, q_temp2, out4);
  281. memcpy(out, &out4[1], 3 * sizeof(long));
  282. }
  283. void inv_q_multf(const float *q1, const float *q2, float *qProd)
  284. {
  285. INVENSENSE_FUNC_START;
  286. qProd[0] =
  287. (q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3]);
  288. qProd[1] =
  289. (q1[0] * q2[1] + q1[1] * q2[0] + q1[2] * q2[3] - q1[3] * q2[2]);
  290. qProd[2] =
  291. (q1[0] * q2[2] - q1[1] * q2[3] + q1[2] * q2[0] + q1[3] * q2[1]);
  292. qProd[3] =
  293. (q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1] + q1[3] * q2[0]);
  294. }
  295. void inv_q_addf(const float *q1, const float *q2, float *qSum)
  296. {
  297. INVENSENSE_FUNC_START;
  298. qSum[0] = q1[0] + q2[0];
  299. qSum[1] = q1[1] + q2[1];
  300. qSum[2] = q1[2] + q2[2];
  301. qSum[3] = q1[3] + q2[3];
  302. }
  303. void inv_q_normalizef(float *q)
  304. {
  305. INVENSENSE_FUNC_START;
  306. float normSF = 0;
  307. float xHalf = 0;
  308. normSF = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
  309. if (normSF < 2) {
  310. xHalf = 0.5f * normSF;
  311. normSF = normSF * (1.5f - xHalf * normSF * normSF);
  312. normSF = normSF * (1.5f - xHalf * normSF * normSF);
  313. normSF = normSF * (1.5f - xHalf * normSF * normSF);
  314. normSF = normSF * (1.5f - xHalf * normSF * normSF);
  315. q[0] *= normSF;
  316. q[1] *= normSF;
  317. q[2] *= normSF;
  318. q[3] *= normSF;
  319. } else {
  320. q[0] = 1.0;
  321. q[1] = 0.0;
  322. q[2] = 0.0;
  323. q[3] = 0.0;
  324. }
  325. normSF = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
  326. }
  327. /** Performs a length 4 vector normalization with a square root.
  328. * @param[in,out] q vector to normalize. Returns [1,0,0,0] is magnitude is zero.
  329. */
  330. void inv_q_norm4(float *q)
  331. {
  332. float mag;
  333. mag = sqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
  334. if (mag) {
  335. q[0] /= mag;
  336. q[1] /= mag;
  337. q[2] /= mag;
  338. q[3] /= mag;
  339. } else {
  340. q[0] = 1.f;
  341. q[1] = 0.f;
  342. q[2] = 0.f;
  343. q[3] = 0.f;
  344. }
  345. }
  346. void inv_q_invertf(const float *q, float *qInverted)
  347. {
  348. INVENSENSE_FUNC_START;
  349. qInverted[0] = q[0];
  350. qInverted[1] = -q[1];
  351. qInverted[2] = -q[2];
  352. qInverted[3] = -q[3];
  353. }
  354. /**
  355. * Converts a quaternion to a rotation matrix.
  356. * @param[in] quat 4-element quaternion in fixed point. One is 2^30.
  357. * @param[out] rot Rotation matrix in fixed point. One is 2^30. The
  358. * First 3 elements of the rotation matrix, represent
  359. * the first row of the matrix. Rotation matrix multiplied
  360. * by a 3 element column vector transform a vector from Body
  361. * to World.
  362. */
  363. void inv_quaternion_to_rotation(const long *quat, long *rot)
  364. {
  365. rot[0] =
  366. inv_q29_mult(quat[1], quat[1]) + inv_q29_mult(quat[0],
  367. quat[0]) -
  368. 1073741824L;
  369. rot[1] =
  370. inv_q29_mult(quat[1], quat[2]) - inv_q29_mult(quat[3], quat[0]);
  371. rot[2] =
  372. inv_q29_mult(quat[1], quat[3]) + inv_q29_mult(quat[2], quat[0]);
  373. rot[3] =
  374. inv_q29_mult(quat[1], quat[2]) + inv_q29_mult(quat[3], quat[0]);
  375. rot[4] =
  376. inv_q29_mult(quat[2], quat[2]) + inv_q29_mult(quat[0],
  377. quat[0]) -
  378. 1073741824L;
  379. rot[5] =
  380. inv_q29_mult(quat[2], quat[3]) - inv_q29_mult(quat[1], quat[0]);
  381. rot[6] =
  382. inv_q29_mult(quat[1], quat[3]) - inv_q29_mult(quat[2], quat[0]);
  383. rot[7] =
  384. inv_q29_mult(quat[2], quat[3]) + inv_q29_mult(quat[1], quat[0]);
  385. rot[8] =
  386. inv_q29_mult(quat[3], quat[3]) + inv_q29_mult(quat[0],
  387. quat[0]) -
  388. 1073741824L;
  389. }
  390. /**
  391. * Converts a quaternion to a rotation vector. A rotation vector is
  392. * a method to represent a 4-element quaternion vector in 3-elements.
  393. * To get the quaternion from the 3-elements, The last 3-elements of
  394. * the quaternion will be the given rotation vector. The first element
  395. * of the quaternion will be the positive value that will be required
  396. * to make the magnitude of the quaternion 1.0 or 2^30 in fixed point units.
  397. * @param[in] quat 4-element quaternion in fixed point. One is 2^30.
  398. * @param[out] rot Rotation vector in fixed point. One is 2^30.
  399. */
  400. void inv_quaternion_to_rotation_vector(const long *quat, long *rot)
  401. {
  402. rot[0] = quat[1];
  403. rot[1] = quat[2];
  404. rot[2] = quat[3];
  405. if (quat[0] < 0.0) {
  406. rot[0] = -rot[0];
  407. rot[1] = -rot[1];
  408. rot[2] = -rot[2];
  409. }
  410. }
  411. /** Converts a 32-bit long to a big endian byte stream */
  412. unsigned char *inv_int32_to_big8(long x, unsigned char *big8)
  413. {
  414. big8[0] = (unsigned char)((x >> 24) & 0xff);
  415. big8[1] = (unsigned char)((x >> 16) & 0xff);
  416. big8[2] = (unsigned char)((x >> 8) & 0xff);
  417. big8[3] = (unsigned char)(x & 0xff);
  418. return big8;
  419. }
  420. /** Converts a big endian byte stream into a 32-bit long */
  421. long inv_big8_to_int32(const unsigned char *big8)
  422. {
  423. long x;
  424. x = ((long)big8[0] << 24) | ((long)big8[1] << 16) | ((long)big8[2] << 8)
  425. | ((long)big8[3]);
  426. return x;
  427. }
  428. /** Converts a big endian byte stream into a 16-bit integer (short) */
  429. short inv_big8_to_int16(const unsigned char *big8)
  430. {
  431. short x;
  432. x = ((short)big8[0] << 8) | ((short)big8[1]);
  433. return x;
  434. }
  435. /** Converts a little endian byte stream into a 16-bit integer (short) */
  436. short inv_little8_to_int16(const unsigned char *little8)
  437. {
  438. short x;
  439. x = ((short)little8[1] << 8) | ((short)little8[0]);
  440. return x;
  441. }
  442. /** Converts a 16-bit short to a big endian byte stream */
  443. unsigned char *inv_int16_to_big8(short x, unsigned char *big8)
  444. {
  445. big8[0] = (unsigned char)((x >> 8) & 0xff);
  446. big8[1] = (unsigned char)(x & 0xff);
  447. return big8;
  448. }
  449. void inv_matrix_det_inc(float *a, float *b, int *n, int x, int y)
  450. {
  451. int k, l, i, j;
  452. for (i = 0, k = 0; i < *n; i++, k++) {
  453. for (j = 0, l = 0; j < *n; j++, l++) {
  454. if (i == x)
  455. i++;
  456. if (j == y)
  457. j++;
  458. *(b + 6 * k + l) = *(a + 6 * i + j);
  459. }
  460. }
  461. *n = *n - 1;
  462. }
  463. void inv_matrix_det_incd(double *a, double *b, int *n, int x, int y)
  464. {
  465. int k, l, i, j;
  466. for (i = 0, k = 0; i < *n; i++, k++) {
  467. for (j = 0, l = 0; j < *n; j++, l++) {
  468. if (i == x)
  469. i++;
  470. if (j == y)
  471. j++;
  472. *(b + 6 * k + l) = *(a + 6 * i + j);
  473. }
  474. }
  475. *n = *n - 1;
  476. }
  477. float inv_matrix_det(float *p, int *n)
  478. {
  479. float d[6][6], sum = 0;
  480. int i, j, m;
  481. m = *n;
  482. if (*n == 2)
  483. return (*p ** (p + 7) - *(p + 1) ** (p + 6));
  484. for (i = 0, j = 0; j < m; j++) {
  485. *n = m;
  486. inv_matrix_det_inc(p, &d[0][0], n, i, j);
  487. sum =
  488. sum + *(p + 6 * i + j) * SIGNM(i +
  489. j) *
  490. inv_matrix_det(&d[0][0], n);
  491. }
  492. return (sum);
  493. }
  494. double inv_matrix_detd(double *p, int *n)
  495. {
  496. double d[6][6], sum = 0;
  497. int i, j, m;
  498. m = *n;
  499. if (*n == 2)
  500. return (*p ** (p + 7) - *(p + 1) ** (p + 6));
  501. for (i = 0, j = 0; j < m; j++) {
  502. *n = m;
  503. inv_matrix_det_incd(p, &d[0][0], n, i, j);
  504. sum =
  505. sum + *(p + 6 * i + j) * SIGNM(i +
  506. j) *
  507. inv_matrix_detd(&d[0][0], n);
  508. }
  509. return (sum);
  510. }
  511. /** Wraps angle from (-M_PI,M_PI]
  512. * @param[in] ang Angle in radians to wrap
  513. * @return Wrapped angle from (-M_PI,M_PI]
  514. */
  515. float inv_wrap_angle(float ang)
  516. {
  517. if (ang > M_PI)
  518. return ang - 2 * (float)M_PI;
  519. else if (ang <= -(float)M_PI)
  520. return ang + 2 * (float)M_PI;
  521. else
  522. return ang;
  523. }
  524. /** Finds the minimum angle difference ang1-ang2 such that difference
  525. * is between [-M_PI,M_PI]
  526. * @param[in] ang1
  527. * @param[in] ang2
  528. * @return angle difference ang1-ang2
  529. */
  530. float inv_angle_diff(float ang1, float ang2)
  531. {
  532. float d;
  533. ang1 = inv_wrap_angle(ang1);
  534. ang2 = inv_wrap_angle(ang2);
  535. d = ang1 - ang2;
  536. if (d > M_PI)
  537. d -= 2 * (float)M_PI;
  538. else if (d < -(float)M_PI)
  539. d += 2 * (float)M_PI;
  540. return d;
  541. }
  542. /** bernstein hash, derived from public domain source */
  543. uint32_t inv_checksum(const unsigned char *str, int len)
  544. {
  545. uint32_t hash = 5381;
  546. int i, c;
  547. for (i = 0; i < len; i++) {
  548. c = *(str + i);
  549. hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
  550. }
  551. return hash;
  552. }
  553. static unsigned short inv_row_2_scale(const signed char *row)
  554. {
  555. unsigned short b;
  556. if (row[0] > 0)
  557. b = 0;
  558. else if (row[0] < 0)
  559. b = 4;
  560. else if (row[1] > 0)
  561. b = 1;
  562. else if (row[1] < 0)
  563. b = 5;
  564. else if (row[2] > 0)
  565. b = 2;
  566. else if (row[2] < 0)
  567. b = 6;
  568. else
  569. b = 7; // error
  570. return b;
  571. }
  572. /** Converts an orientation matrix made up of 0,+1,and -1 to a scalar representation.
  573. * @param[in] mtx Orientation matrix to convert to a scalar.
  574. * @return Description of orientation matrix. The lowest 2 bits (0 and 1) represent the column the one is on for the
  575. * first row, with the bit number 2 being the sign. The next 2 bits (3 and 4) represent
  576. * the column the one is on for the second row with bit number 5 being the sign.
  577. * The next 2 bits (6 and 7) represent the column the one is on for the third row with
  578. * bit number 8 being the sign. In binary the identity matrix would therefor be:
  579. * 010_001_000 or 0x88 in hex.
  580. */
  581. unsigned short inv_orientation_matrix_to_scalar(const signed char *mtx)
  582. {
  583. unsigned short scalar;
  584. /*
  585. XYZ 010_001_000 Identity Matrix
  586. XZY 001_010_000
  587. YXZ 010_000_001
  588. YZX 000_010_001
  589. ZXY 001_000_010
  590. ZYX 000_001_010
  591. */
  592. scalar = inv_row_2_scale(mtx);
  593. scalar |= inv_row_2_scale(mtx + 3) << 3;
  594. scalar |= inv_row_2_scale(mtx + 6) << 6;
  595. return scalar;
  596. }
  597. /** Uses the scalar orientation value to convert from chip frame to body frame
  598. * @param[in] orientation A scalar that represent how to go from chip to body frame
  599. * @param[in] input Input vector, length 3
  600. * @param[out] output Output vector, length 3
  601. */
  602. void inv_convert_to_body(unsigned short orientation, const long *input, long *output)
  603. {
  604. output[0] = input[orientation & 0x03] * SIGNSET(orientation & 0x004);
  605. output[1] = input[(orientation>>3) & 0x03] * SIGNSET(orientation & 0x020);
  606. output[2] = input[(orientation>>6) & 0x03] * SIGNSET(orientation & 0x100);
  607. }
  608. /** Uses the scalar orientation value to convert from body frame to chip frame
  609. * @param[in] orientation A scalar that represent how to go from chip to body frame
  610. * @param[in] input Input vector, length 3
  611. * @param[out] output Output vector, length 3
  612. */
  613. void inv_convert_to_chip(unsigned short orientation, const long *input, long *output)
  614. {
  615. output[orientation & 0x03] = input[0] * SIGNSET(orientation & 0x004);
  616. output[(orientation>>3) & 0x03] = input[1] * SIGNSET(orientation & 0x020);
  617. output[(orientation>>6) & 0x03] = input[2] * SIGNSET(orientation & 0x100);
  618. }
  619. /** Uses the scalar orientation value to convert from chip frame to body frame and
  620. * apply appropriate scaling.
  621. * @param[in] orientation A scalar that represent how to go from chip to body frame
  622. * @param[in] sensitivity Sensitivity scale
  623. * @param[in] input Input vector, length 3
  624. * @param[out] output Output vector, length 3
  625. */
  626. void inv_convert_to_body_with_scale(unsigned short orientation, long sensitivity, const long *input, long *output)
  627. {
  628. output[0] = inv_q30_mult(input[orientation & 0x03] *
  629. SIGNSET(orientation & 0x004), sensitivity);
  630. output[1] = inv_q30_mult(input[(orientation>>3) & 0x03] *
  631. SIGNSET(orientation & 0x020), sensitivity);
  632. output[2] = inv_q30_mult(input[(orientation>>6) & 0x03] *
  633. SIGNSET(orientation & 0x100), sensitivity);
  634. }
  635. /** find a norm for a vector
  636. * @param[in] a vector [3x1]
  637. * @param[out] output the norm of the input vector
  638. */
  639. double inv_vector_norm(const float *x)
  640. {
  641. return sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]);
  642. }
  643. void inv_init_biquad_filter(inv_biquad_filter_t *pFilter, float *pBiquadCoeff) {
  644. int i;
  645. // initial state to zero
  646. pFilter->state[0] = 0;
  647. pFilter->state[1] = 0;
  648. // set up coefficients
  649. for (i=0; i<5; i++) {
  650. pFilter->c[i] = pBiquadCoeff[i];
  651. }
  652. }
  653. void inv_calc_state_to_match_output(inv_biquad_filter_t *pFilter, float input)
  654. {
  655. pFilter->input = input;
  656. pFilter->output = input;
  657. pFilter->state[0] = input / (1 + pFilter->c[2] + pFilter->c[3]);
  658. pFilter->state[1] = pFilter->state[0];
  659. }
  660. float inv_biquad_filter_process(inv_biquad_filter_t *pFilter, float input) {
  661. float stateZero;
  662. pFilter->input = input;
  663. // calculate the new state;
  664. stateZero = pFilter->input - pFilter->c[2]*pFilter->state[0]
  665. - pFilter->c[3]*pFilter->state[1];
  666. pFilter->output = stateZero + pFilter->c[0]*pFilter->state[0]
  667. + pFilter->c[1]*pFilter->state[1];
  668. // update the output and state
  669. pFilter->output = pFilter->output * pFilter->c[4];
  670. pFilter->state[1] = pFilter->state[0];
  671. pFilter->state[0] = stateZero;
  672. return pFilter->output;
  673. }
  674. void inv_get_cross_product_vec(float *cgcross, float compass[3], float grav[3]) {
  675. cgcross[0] = (float)compass[1] * grav[2] - (float)compass[2] * grav[1];
  676. cgcross[1] = (float)compass[2] * grav[0] - (float)compass[0] * grav[2];
  677. cgcross[2] = (float)compass[0] * grav[1] - (float)compass[1] * grav[0];
  678. }
  679. void mlMatrixVectorMult(long matrix[9], const long vecIn[3], long *vecOut) {
  680. // matrix format
  681. // [ 0 3 6;
  682. // 1 4 7;
  683. // 2 5 8]
  684. // vector format: [0 1 2]^T;
  685. int i, j;
  686. long temp;
  687. for (i=0; i<3; i++) {
  688. temp = 0;
  689. for (j=0; j<3; j++) {
  690. temp += inv_q30_mult(matrix[i+j*3], vecIn[j]);
  691. }
  692. vecOut[i] = temp;
  693. }
  694. }
  695. /**
  696. * @}
  697. */