1 /* 2 $License: 3 Copyright 2011 InvenSense, Inc. 4 5 Licensed under the Apache License, Version 2.0 (the "License"); 6 you may not use this file except in compliance with the License. 7 You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11 Unless required by applicable law or agreed to in writing, software 12 distributed under the License is distributed on an "AS IS" BASIS, 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 See the License for the specific language governing permissions and 15 limitations under the License. 16 $ 17 */ 18 #include "mlmath.h" 19 #include "mlMathFunc.h" 20 #include "mlinclude.h" 21 22 /** 23 * Performs one iteration of the filter, generating a new y(0) 24 * 1 / N / N \\ 25 * y(0) = ---- * |SUM b(k) * x(k) - | SUM a(k) * y(k)|| for N = length 26 * a(0) \k=0 \ k=1 // 27 * 28 * The filters A and B should be (sizeof(long) * state->length). 29 * The state variables x and y should be (sizeof(long) * (state->length - 1)) 30 * 31 * The state variables x and y should be initialized prior to the first call 32 * 33 * @param state Contains the length of the filter, filter coefficients and 34 * filter state variables x and y. 35 * @param x New input into the filter. 36 */ 37 void inv_filter_long(struct filter_long *state, long x) 38 { 39 const long *b = state->b; 40 const long *a = state->a; 41 long length = state->length; 42 long long tmp; 43 int ii; 44 45 /* filter */ 46 tmp = (long long)x *(b[0]); 47 for (ii = 0; ii < length - 1; ii++) { 48 tmp += ((long long)state->x[ii] * (long long)(b[ii + 1])); 49 } 50 for (ii = 0; ii < length - 1; ii++) { 51 tmp -= ((long long)state->y[ii] * (long long)(a[ii + 1])); 52 } 53 tmp /= (long long)a[0]; 54 55 /* Delay */ 56 for (ii = length - 2; ii > 0; ii--) { 57 state->y[ii] = state->y[ii - 1]; 58 state->x[ii] = state->x[ii - 1]; 59 } 60 /* New values */ 61 state->y[0] = (long)tmp; 62 state->x[0] = x; 63 } 64 65 /** Performs a multiply and shift by 29. These are good functions to write in assembly on 66 * with devices with small memory where you want to get rid of the long long which some 67 * assemblers don't handle well 68 * @param[in] a 69 * @param[in] b 70 * @return ((long long)a*b)>>29 71 */ 72 long inv_q29_mult(long a, long b) 73 { 74 long long temp; 75 long result; 76 temp = (long long)a *b; 77 result = (long)(temp >> 29); 78 return result; 79 } 80 81 /** Performs a multiply and shift by 30. These are good functions to write in assembly on 82 * with devices with small memory where you want to get rid of the long long which some 83 * assemblers don't handle well 84 * @param[in] a 85 * @param[in] b 86 * @return ((long long)a*b)>>30 87 */ 88 long inv_q30_mult(long a, long b) 89 { 90 long long temp; 91 long result; 92 temp = (long long)a *b; 93 result = (long)(temp >> 30); 94 return result; 95 } 96 97 void inv_q_mult(const long *q1, const long *q2, long *qProd) 98 { 99 INVENSENSE_FUNC_START; 100 qProd[0] = (long)(((long long)q1[0] * q2[0] - (long long)q1[1] * q2[1] - 101 (long long)q1[2] * q2[2] - 102 (long long)q1[3] * q2[3]) >> 30); 103 qProd[1] = 104 (int)(((long long)q1[0] * q2[1] + (long long)q1[1] * q2[0] + 105 (long long)q1[2] * q2[3] - (long long)q1[3] * q2[2]) >> 30); 106 qProd[2] = 107 (long)(((long long)q1[0] * q2[2] - (long long)q1[1] * q2[3] + 108 (long long)q1[2] * q2[0] + (long long)q1[3] * q2[1]) >> 30); 109 qProd[3] = 110 (long)(((long long)q1[0] * q2[3] + (long long)q1[1] * q2[2] - 111 (long long)q1[2] * q2[1] + (long long)q1[3] * q2[0]) >> 30); 112 } 113 114 void inv_q_add(long *q1, long *q2, long *qSum) 115 { 116 INVENSENSE_FUNC_START; 117 qSum[0] = q1[0] + q2[0]; 118 qSum[1] = q1[1] + q2[1]; 119 qSum[2] = q1[2] + q2[2]; 120 qSum[3] = q1[3] + q2[3]; 121 } 122 123 void inv_q_normalize(long *q) 124 { 125 INVENSENSE_FUNC_START; 126 double normSF = 0; 127 int i; 128 for (i = 0; i < 4; i++) { 129 normSF += ((double)q[i]) / 1073741824L * ((double)q[i]) / 1073741824L; 130 } 131 if (normSF > 0) { 132 normSF = 1 / sqrt(normSF); 133 for (i = 0; i < 4; i++) { 134 q[i] = (int)((double)q[i] * normSF); 135 } 136 } else { 137 q[0] = 1073741824L; 138 q[1] = 0; 139 q[2] = 0; 140 q[3] = 0; 141 } 142 } 143 144 void inv_q_invert(const long *q, long *qInverted) 145 { 146 INVENSENSE_FUNC_START; 147 qInverted[0] = q[0]; 148 qInverted[1] = -q[1]; 149 qInverted[2] = -q[2]; 150 qInverted[3] = -q[3]; 151 } 152 153 void inv_q_multf(const float *q1, const float *q2, float *qProd) 154 { 155 INVENSENSE_FUNC_START; 156 qProd[0] = (q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3]); 157 qProd[1] = (q1[0] * q2[1] + q1[1] * q2[0] + q1[2] * q2[3] - q1[3] * q2[2]); 158 qProd[2] = (q1[0] * q2[2] - q1[1] * q2[3] + q1[2] * q2[0] + q1[3] * q2[1]); 159 qProd[3] = (q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1] + q1[3] * q2[0]); 160 } 161 162 void inv_q_addf(float *q1, float *q2, float *qSum) 163 { 164 INVENSENSE_FUNC_START; 165 qSum[0] = q1[0] + q2[0]; 166 qSum[1] = q1[1] + q2[1]; 167 qSum[2] = q1[2] + q2[2]; 168 qSum[3] = q1[3] + q2[3]; 169 } 170 171 void inv_q_normalizef(float *q) 172 { 173 INVENSENSE_FUNC_START; 174 float normSF = 0; 175 float xHalf = 0; 176 normSF = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); 177 if (normSF < 2) { 178 xHalf = 0.5f * normSF; 179 normSF = normSF * (1.5f - xHalf * normSF * normSF); 180 normSF = normSF * (1.5f - xHalf * normSF * normSF); 181 normSF = normSF * (1.5f - xHalf * normSF * normSF); 182 normSF = normSF * (1.5f - xHalf * normSF * normSF); 183 q[0] *= normSF; 184 q[1] *= normSF; 185 q[2] *= normSF; 186 q[3] *= normSF; 187 } else { 188 q[0] = 1.0; 189 q[1] = 0.0; 190 q[2] = 0.0; 191 q[3] = 0.0; 192 } 193 normSF = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); 194 } 195 196 /** Performs a length 4 vector normalization with a square root. 197 * @param[in,out] vector to normalize. Returns [1,0,0,0] is magnitude is zero. 198 */ 199 void inv_q_norm4(float *q) 200 { 201 float mag; 202 mag = sqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); 203 if (mag) { 204 q[0] /= mag; 205 q[1] /= mag; 206 q[2] /= mag; 207 q[3] /= mag; 208 } else { 209 q[0] = 1.f; 210 q[1] = 0.f; 211 q[2] = 0.f; 212 q[3] = 0.f; 213 } 214 } 215 216 void inv_q_invertf(const float *q, float *qInverted) 217 { 218 INVENSENSE_FUNC_START; 219 qInverted[0] = q[0]; 220 qInverted[1] = -q[1]; 221 qInverted[2] = -q[2]; 222 qInverted[3] = -q[3]; 223 } 224 225 /** 226 * Converts a quaternion to a rotation matrix. 227 * @param[in] quat 4-element quaternion in fixed point. One is 2^30. 228 * @param[out] rot Rotation matrix in fixed point. One is 2^30. The 229 * First 3 elements of the rotation matrix, represent 230 * the first row of the matrix. Rotation matrix multiplied 231 * by a 3 element column vector transform a vector from Body 232 * to World. 233 */ 234 void inv_quaternion_to_rotation(const long *quat, long *rot) 235 { 236 rot[0] = 237 inv_q29_mult(quat[1], quat[1]) + inv_q29_mult(quat[0], 238 quat[0]) - 1073741824L; 239 rot[1] = inv_q29_mult(quat[1], quat[2]) - inv_q29_mult(quat[3], quat[0]); 240 rot[2] = inv_q29_mult(quat[1], quat[3]) + inv_q29_mult(quat[2], quat[0]); 241 rot[3] = inv_q29_mult(quat[1], quat[2]) + inv_q29_mult(quat[3], quat[0]); 242 rot[4] = 243 inv_q29_mult(quat[2], quat[2]) + inv_q29_mult(quat[0], 244 quat[0]) - 1073741824L; 245 rot[5] = inv_q29_mult(quat[2], quat[3]) - inv_q29_mult(quat[1], quat[0]); 246 rot[6] = inv_q29_mult(quat[1], quat[3]) - inv_q29_mult(quat[2], quat[0]); 247 rot[7] = inv_q29_mult(quat[2], quat[3]) + inv_q29_mult(quat[1], quat[0]); 248 rot[8] = 249 inv_q29_mult(quat[3], quat[3]) + inv_q29_mult(quat[0], 250 quat[0]) - 1073741824L; 251 } 252 253 /** Converts a 32-bit long to a big endian byte stream */ 254 unsigned char *inv_int32_to_big8(long x, unsigned char *big8) 255 { 256 big8[0] = (unsigned char)((x >> 24) & 0xff); 257 big8[1] = (unsigned char)((x >> 16) & 0xff); 258 big8[2] = (unsigned char)((x >> 8) & 0xff); 259 big8[3] = (unsigned char)(x & 0xff); 260 return big8; 261 } 262 263 /** Converts a big endian byte stream into a 32-bit long */ 264 long inv_big8_to_int32(const unsigned char *big8) 265 { 266 long x; 267 x = ((long)big8[0] << 24) | ((long)big8[1] << 16) | ((long)big8[2] << 8) | 268 ((long)big8[3]); 269 return x; 270 } 271 272 /** Converts a 16-bit short to a big endian byte stream */ 273 unsigned char *inv_int16_to_big8(short x, unsigned char *big8) 274 { 275 big8[0] = (unsigned char)((x >> 8) & 0xff); 276 big8[1] = (unsigned char)(x & 0xff); 277 return big8; 278 } 279 280 void inv_matrix_det_inc(float *a, float *b, int *n, int x, int y) 281 { 282 int k, l, i, j; 283 for (i = 0, k = 0; i < *n; i++, k++) { 284 for (j = 0, l = 0; j < *n; j++, l++) { 285 if (i == x) 286 i++; 287 if (j == y) 288 j++; 289 *(b + 10 * k + l) = *(a + 10 * i + j); 290 } 291 } 292 *n = *n - 1; 293 } 294 295 void inv_matrix_det_incd(double *a, double *b, int *n, int x, int y) 296 { 297 int k, l, i, j; 298 for (i = 0, k = 0; i < *n; i++, k++) { 299 for (j = 0, l = 0; j < *n; j++, l++) { 300 if (i == x) 301 i++; 302 if (j == y) 303 j++; 304 *(b + 10 * k + l) = *(a + 10 * i + j); 305 } 306 } 307 *n = *n - 1; 308 } 309 310 float inv_matrix_det(float *p, int *n) 311 { 312 float d[10][10], sum = 0; 313 int i, j, m; 314 m = *n; 315 if (*n == 2) 316 return (*p ** (p + 11) - *(p + 1) ** (p + 10)); 317 for (i = 0, j = 0; j < m; j++) { 318 *n = m; 319 inv_matrix_det_inc(p, &d[0][0], n, i, j); 320 sum = 321 sum + *(p + 10 * i + j) * SIGNM(i + j) * inv_matrix_det(&d[0][0], 322 n); 323 } 324 325 return (sum); 326 } 327 328 double inv_matrix_detd(double *p, int *n) 329 { 330 double d[10][10], sum = 0; 331 int i, j, m; 332 m = *n; 333 if (*n == 2) 334 return (*p ** (p + 11) - *(p + 1) ** (p + 10)); 335 for (i = 0, j = 0; j < m; j++) { 336 *n = m; 337 inv_matrix_det_incd(p, &d[0][0], n, i, j); 338 sum = 339 sum + *(p + 10 * i + j) * SIGNM(i + j) * inv_matrix_detd(&d[0][0], 340 n); 341 } 342 343 return (sum); 344 } 345 346 /** Wraps angle from (-M_PI,M_PI] 347 * @param[in] ang Angle in radians to wrap 348 * @return Wrapped angle from (-M_PI,M_PI] 349 */ 350 float inv_wrap_angle(float ang) 351 { 352 if (ang > M_PI) 353 return ang - 2 * (float)M_PI; 354 else if (ang <= -(float)M_PI) 355 return ang + 2 * (float)M_PI; 356 else 357 return ang; 358 } 359 360 /** Finds the minimum angle difference ang1-ang2 such that difference 361 * is between [-M_PI,M_PI] 362 * @param[in] ang1 363 * @param[in] ang2 364 * @return angle difference ang1-ang2 365 */ 366 float inv_angle_diff(float ang1, float ang2) 367 { 368 float d; 369 ang1 = inv_wrap_angle(ang1); 370 ang2 = inv_wrap_angle(ang2); 371 d = ang1 - ang2; 372 if (d > M_PI) 373 d -= 2 * (float)M_PI; 374 else if (d < -(float)M_PI) 375 d += 2 * (float)M_PI; 376 return d; 377 } 378