| 434 | |
| 435 | |
| 436 | bool SF::initQuat(float ax, float ay, float az, float mx, float my, float mz){ |
| 437 | // Compute feedback only if accelerometer measurement valid |
| 438 | // (avoids NaN in accelerometer normalisation) |
| 439 | if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) { |
| 440 | float recipNorm; |
| 441 | float N[3], D[3], E[3]; //Global vectors North, Down, East relative to sensor |
| 442 | |
| 443 | // Down is negative accelerometer measurement |
| 444 | recipNorm = invSqrt(ax * ax + ay * ay + az * az); |
| 445 | D[0] = - ax * recipNorm; |
| 446 | D[1] = - ay * recipNorm; |
| 447 | D[2] = - az * recipNorm; |
| 448 | |
| 449 | // Magnetometer is not exatly perpendicular to Down, therefor not exatly North |
| 450 | // we will calculate North later |
| 451 | float m[3]; |
| 452 | recipNorm = invSqrt(mx * mx + my * my + mz * mz); |
| 453 | m[0] = mx * recipNorm; |
| 454 | m[1] = mx * recipNorm; |
| 455 | m[2] = mx * recipNorm; |
| 456 | |
| 457 | // Calculate East |
| 458 | vectorCross(m, D, E); |
| 459 | recipNorm = invSqrt(E[0] * E[0] + E[1] * E[1] + E[2] * E[2]); |
| 460 | E[0] *= recipNorm; |
| 461 | E[1] *= recipNorm; |
| 462 | E[2] *= recipNorm; |
| 463 | |
| 464 | // Calculate North |
| 465 | vectorCross(D, E, N); |
| 466 | |
| 467 | // Calculate Euler Parameter (quaternion) from the rotation matrix A=(N|D|E). |
| 468 | // Using Shepperd algorithm (Woernle 2011) |
| 469 | float Trace = N[0] + D[1] + E[2]; |
| 470 | float a[4] = {Trace, N[0], D[1], E[2]}; |
| 471 | float e[4]; |
| 472 | |
| 473 | //find index of Largest Euler parameter |
| 474 | int k=0; |
| 475 | for (int i=1; i<4; i++){ |
| 476 | if (a[i] > a[k]) |
| 477 | k = i; |
| 478 | } |
| 479 | //calculate that parameter |
| 480 | e[k] = sqrt(1 + 2 * a[k] - Trace)/2; |
| 481 | |
| 482 | switch (k){ |
| 483 | case 0: |
| 484 | e[1] = (D[2] - E[1]) / (4 * e[0]); |
| 485 | e[2] = (E[0] - N[2]) / (4 * e[0]); |
| 486 | e[3] = (N[1] - D[0]) / (4 * e[0]); |
| 487 | break; |
| 488 | case 1: |
| 489 | e[0] = (D[2] - E[1]) / (4 * e[1]); |
| 490 | e[2] = (D[0] + N[1]) / (4 * e[1]); |
| 491 | e[3] = (E[0] + N[2]) / (4 * e[1]); |
| 492 | break; |
| 493 | case 2: |
nothing calls this directly
no outgoing calls
no test coverage detected