35 #define SMALLQ0 1E-4F                           // limit of quaternion scalar component requiring special algorithm    36 #define CORRUPTQUAT 0.001F      // threshold for deciding rotation quaternion is corrupt    37 #define SMALLMODULUS 0.01F      // limit where rounding errors may appear    39 #if F_USING_ACCEL  // Need tilt conversion routines    41 #if (THISCOORDSYSTEM == NED) || (THISCOORDSYSTEM == ANDROID)    55                 fmodGxyz = fmodGyz + fGc[
CHX] * fGc[
CHX];
    83                 fmodGyz = sqrtf(fmodGyz);
    84                 fmodGxyz = sqrtf(fmodGxyz);
    85                 frecipmodGxyz = 1.0F / fmodGxyz;
    86                 ftmp = fmodGxyz / fmodGyz;
    89                 for (i = 
CHX; i <= 
CHZ; i++)
    91                                 fR[i][
CHZ] = fGc[i] * frecipmodGxyz;
    95                 fR[
CHX][
CHX] = fmodGyz * frecipmodGxyz;
   106 #endif // #if THISCOORDSYSTEM == NED   109 #if THISCOORDSYSTEM == ANDROID   117 #endif // #if THISCOORDSYSTEM == ANDROID   120 #if (THISCOORDSYSTEM == WIN8) || (THISCOORDSYSTEM == ANDROID)   134                 fmodGxyz = fmodGxz + fGc[
CHY] * fGc[
CHY];
   137                 if (fmodGxyz == 0.0F)
   148                                 if (fGc[
CHY] >= 0.0F)
   162                 fmodGxz = sqrtf(fmodGxz);
   163                 fmodGxyz = sqrtf(fmodGxyz);
   164                 frecipmodGxyz = 1.0F / fmodGxyz;
   165                 ftmp = fmodGxyz / fmodGxz;
   172                 for (i = 
CHX; i <= 
CHZ; i++)
   174                                 fR[i][
CHZ] = -fGc[i] * frecipmodGxyz;
   184                 fR[
CHY][
CHY] = -fmodGxz * frecipmodGxyz;
   193 #endif // #if (THISCOORDSYSTEM == WIN8)   194 #endif // #if F_USING_ACCEL  // Need tilt conversion routines   196 #if F_USING_MAG // Need eCompass conversion routines   198 #if THISCOORDSYSTEM == NED   205                 fmodBxy = sqrtf(fBc[
CHX] * fBc[
CHX] + fBc[
CHY] * fBc[
CHY]);
   225 #endif // #if THISCOORDSYSTEM == NED   228 #if (THISCOORDSYSTEM == ANDROID) || (THISCOORDSYSTEM == WIN8)   235                 fmodBxy = sqrtf(fBc[
CHX] * fBc[
CHX] + fBc[
CHY] * fBc[
CHY]);
   255 #endif // #if THISCOORDSYSTEM == ANDROID   258 #if (THISCOORDSYSTEM == WIN8)   266 #endif // #if (THISCOORDSYSTEM == WIN8)   269 #if THISCOORDSYSTEM == NED   270 void feCompassNED(
float fR[][3], 
float *pfDelta, 
float *pfsinDelta, 
float *pfcosDelta, 
float fBc[], 
float fGc[], 
float *pfmodBc, 
float *pfmodGc)
   279                 *pfDelta = *pfsinDelta = 0.0F;
   283                 for (i = 
CHX; i <= 
CHZ; i++)
   305                 if (!((fmod[CHX] == 0.0F) || (fmod[CHY] == 0.0F) || (fmod[CHZ] == 0.0F)))
   308                                 for (j = CHX; j <= 
CHZ; j++)
   310                                                 ftmp = 1.0F / fmod[j];
   312                                                 for (i = CHX; i <= 
CHZ; i++)
   327                 *pfmodGc = fmod[
CHZ];
   328                 *pfmodBc = sqrtf(fBc[CHX] * fBc[CHX] + fBc[CHY] * fBc[CHY] + fBc[CHZ] * fBc[CHZ]);
   330                 if (!((*pfmodGc == 0.0F) || (*pfmodBc == 0.0F)))
   332                                 *pfsinDelta = fGcdotBc / (*pfmodGc * *pfmodBc);
   333                                 *pfcosDelta = sqrtf(1.0F - *pfsinDelta * *pfsinDelta);
   339 #endif // #if THISCOORDSYSTEM == NED   342 #if THISCOORDSYSTEM == ANDROID   343 void feCompassAndroid(
float fR[][3], 
float *pfDelta, 
float *pfsinDelta, 
float *pfcosDelta, 
float fBc[], 
float fGc[],
   344                                 float *pfmodBc, 
float *pfmodGc)
   353                 *pfDelta = *pfsinDelta = 0.0F;
   357                 for (i = 
CHX; i <= 
CHZ; i++)
   379                 if (!((fmod[CHX] == 0.0F) || (fmod[CHY] == 0.0F) || (fmod[CHZ] == 0.0F)))
   382                                 for (j = CHX; j <= 
CHZ; j++)
   384                                                 ftmp = 1.0F / fmod[j];
   386                                                 for (i = CHX; i <= 
CHZ; i++)
   401                 *pfmodGc = fmod[
CHZ];
   402                 *pfmodBc = sqrtf(fBc[CHX] * fBc[CHX] + fBc[CHY] * fBc[CHY] + fBc[CHZ] * fBc[CHZ]);
   404                 if (!((*pfmodGc == 0.0F) || (*pfmodBc == 0.0F)))
   406                                 *pfsinDelta = -fGcdotBc / (*pfmodGc * *pfmodBc);
   407                                 *pfcosDelta = sqrtf(1.0F - *pfsinDelta * *pfsinDelta);
   413 #endif // #if THISCOORDSYSTEM == ANDROID   416 #if (THISCOORDSYSTEM == WIN8)   417 void feCompassWin8(
float fR[][3], 
float *pfDelta, 
float *pfsinDelta, 
float *pfcosDelta, 
float fBc[], 
float fGc[],
   418                                 float *pfmodBc, 
float *pfmodGc)
   427                 *pfDelta = *pfsinDelta = 0.0F;
   431                 for (i = 
CHX; i <= 
CHZ; i++)
   433                                 fR[i][
CHZ] = -fGc[i];
   453                 if (!((fmod[CHX] == 0.0F) || (fmod[CHY] == 0.0F) || (fmod[CHZ] == 0.0F)))
   456                                 for (j = CHX; j <= 
CHZ; j++)
   458                                                 ftmp = 1.0F / fmod[j];
   460                                                 for (i = CHX; i <= 
CHZ; i++)
   475                 *pfmodGc = fmod[
CHZ];
   476                 *pfmodBc = sqrtf(fBc[CHX] * fBc[CHX] + fBc[CHY] * fBc[CHY] + fBc[CHZ] * fBc[CHZ]);
   478                 if (!((*pfmodGc == 0.0F) || (*pfmodBc == 0.0F)))
   480                                 *pfsinDelta = fGcdotBc / (*pfmodGc * *pfmodBc);
   481                                 *pfcosDelta = sqrtf(1.0F - *pfsinDelta * *pfsinDelta);
   487 #endif // #if (THISCOORDSYSTEM == WIN8)   488 #endif // #if F_USING_MAG // Need eCompass conversion routines   491 #if THISCOORDSYSTEM == NED   493                                 float *pfRhoDeg, 
float *pfChiDeg)
   502                 if (*pfPhiDeg == 180.0F)
   508                 if (*pfTheDeg == 90.0F)
   511                                 *pfPsiDeg = 
fatan2_deg(R[CHZ][
CHY], R[CHY][CHY]) + *pfPhiDeg;
   513                 else if (*pfTheDeg == -90.0F)
   516                                 *pfPsiDeg = 
fatan2_deg(-R[CHZ][
CHY], R[CHY][CHY]) - *pfPhiDeg;
   525                 if (*pfPsiDeg < 0.0F)
   531                 if (*pfPsiDeg >= 360.0F)
   537                 *pfRhoDeg = *pfPsiDeg;
   544 #endif // #if THISCOORDSYSTEM == NED   547 #if THISCOORDSYSTEM == ANDROID   549                                 float *pfRhoDeg, 
float *pfChiDeg)
   558                 if (*pfTheDeg == 180.0F)
   564                 if (*pfPhiDeg == 90.0F)
   569                 else if (*pfPhiDeg == -90.0F)
   581                 if (*pfPsiDeg < 0.0F)
   587                 if (*pfPsiDeg >= 360.0F)
   594                 *pfRhoDeg = *pfPsiDeg;
   601 #endif // #if THISCOORDSYSTEM == ANDROID   604 #if (THISCOORDSYSTEM == WIN8)   606                                 float *pfRhoDeg, 
float *pfChiDeg)
   633                 if (R[CHZ][CHZ] < 0.0F)
   636                                 *pfTheDeg = 180.0F - *pfTheDeg;
   640                 if (*pfTheDeg >= 180.0F)
   646                 if (*pfTheDeg == 90.0F)
   651                 else if (*pfTheDeg == -90.0F)
   662                                 if (fabsf(*pfTheDeg) >= 90.0F)
   669                 if (*pfPsiDeg < 0.0F)
   675                 if (*pfPsiDeg >= 360.0F)
   681                 *pfRhoDeg = 360.0F - *pfPsiDeg;
   684                 if (*pfRhoDeg >= 360.0F)
   694 #endif // #if (THISCOORDSYSTEM == WIN8)   708                 fetadeg = fscaling * sqrtf(rvecdeg[
CHX] * rvecdeg[
CHX] + rvecdeg[
CHY] * rvecdeg[
CHY] + rvecdeg[
CHZ] * rvecdeg[
CHZ]);
   710                 fetarad2 = fetarad * fetarad;
   714                 if (fetarad2 <= 0.02F)
   717                                 sinhalfeta = fetarad * (0.5F - 
ONEOVER48 * fetarad2);
   719                 else if (fetarad2 <= 0.06F)
   723                                 fetarad4 = fetarad2 * fetarad2;
   729                                 sinhalfeta = (float)sinf(0.5F * fetarad);
   736                                 ftmp = fscaling * sinhalfeta / fetadeg;
   737                                 pq->
q1 = rvecdeg[
CHX] * ftmp;                   
   738                                 pq->
q2 = rvecdeg[
CHY] * ftmp;                   
   739                                 pq->
q3 = rvecdeg[
CHZ] * ftmp;                   
   744                                 pq->
q1 = pq->
q2 = pq->
q3 = 0.0F;
   749                 fvecsq = pq->
q1 * pq->
q1 + pq->
q2 * pq->
q2 + pq->
q3 * pq->
q3;
   753                                 pq->
q0 = sqrtf(1.0F - fvecsq);
   772                 pq->
q0 = sqrtf(fabsf(fq0sq));
   778                                 recip4q0 = 0.25F / pq->
q0;
   788                                 pq->
q1 = sqrtf(fabsf(0.5F + 0.5F * R[
CHX][
CHX] - fq0sq));
   789                                 pq->
q2 = sqrtf(fabsf(0.5F + 0.5F * R[
CHY][
CHY] - fq0sq));
   790                                 pq->
q3 = sqrtf(fabsf(0.5F + 0.5F * R[
CHZ][
CHZ] - fq0sq));
   795                                 if ((R[
CHX][CHY] - R[CHY][
CHX]) < 0.0F) pq->
q3 = -pq->
q3;
   809                 float f2q0q0, f2q0q1, f2q0q2, f2q0q3;
   810                 float f2q1q1, f2q1q2, f2q1q3;
   811                 float f2q2q2, f2q2q3;
   816                 f2q0q0 = f2q * pq->
q0;
   817                 f2q0q1 = f2q * pq->
q1;
   818                 f2q0q2 = f2q * pq->
q2;
   819                 f2q0q3 = f2q * pq->
q3;
   822                 f2q1q1 = f2q * pq->
q1;
   823                 f2q1q2 = f2q * pq->
q2;
   824                 f2q1q3 = f2q * pq->
q3;
   827                 f2q2q2 = f2q * pq->
q2;
   828                 f2q2q3 = f2q * pq->
q3;
   829                 f2q3q3 = 2.0F * pq->
q3 * pq->
q3;
   832                 R[
CHX][
CHX] = f2q0q0 + f2q1q1 - 1.0F;
   833                 R[
CHX][
CHY] = f2q1q2 + f2q0q3;
   834                 R[
CHX][
CHZ] = f2q1q3 - f2q0q2;
   835                 R[
CHY][
CHX] = f2q1q2 - f2q0q3;
   836                 R[
CHY][
CHY] = f2q0q0 + f2q2q2 - 1.0F;
   837                 R[
CHY][
CHZ] = f2q2q3 + f2q0q1;
   838                 R[
CHZ][
CHX] = f2q1q3 + f2q0q2;
   839                 R[
CHZ][
CHY] = f2q2q3 - f2q0q1;
   840                 R[
CHZ][
CHZ] = f2q0q0 + f2q3q3 - 1.0F;
   854                 if ((pq->
q0 >= 1.0F) || (pq->
q0 <= -1.0F))
   863                                 fetarad = 2.0F * acosf(pq->
q0);
   868                 if (fetadeg >= 180.0F)
   875                 sinhalfeta = (float)sinf(0.5F * fetarad);
   878                 if (sinhalfeta == 0.0F)
   881                                 rvecdeg[
CHX] = rvecdeg[
CHY] = rvecdeg[
CHZ] = 0.0F;
   886                                 ftmp = fetadeg / sinhalfeta;
   887                                 rvecdeg[
CHX] = pq->
q1 * ftmp;
   888                                 rvecdeg[
CHY] = pq->
q2 * ftmp;
   889                                 rvecdeg[
CHZ] = pq->
q3 * ftmp;
   905                 if (fdeltaq.
q0 < 0.0F)
   907                                 fdeltaq.
q0 = -fdeltaq.
q0;
   908                                 fdeltaq.
q1 = -fdeltaq.
q1;
   909                                 fdeltaq.
q2 = -fdeltaq.
q2;
   910                                 fdeltaq.
q3 = -fdeltaq.
q3;
   915                 ftmp = flpf + (1.0F - flpf) * sqrtf(fabs(1.0F - fdeltaq.
q0 *  fdeltaq.
q0));
   922                 fdeltaq.
q0 = sqrtf(fabsf(1.0F - fdeltaq.
q1 * fdeltaq.
q1 - fdeltaq.
q2 * fdeltaq.
q2 - fdeltaq.
q3 * fdeltaq.
q3));
   926                 ftmp = 1.0F / fdeltat;
   927                 fOmega[
CHX] = rvecdeg[
CHX] * ftmp;
   928                 fOmega[
CHY] = rvecdeg[
CHY] * ftmp;
   929                 fOmega[
CHZ] = rvecdeg[
CHZ] * ftmp;
   944                 pqA->
q0 = pqB->
q0 * pqC->
q0 - pqB->
q1 * pqC->
q1 - pqB->
q2 * pqC->
q2 - pqB->
q3 * pqC->
q3;
   945                 pqA->
q1 = pqB->
q0 * pqC->
q1 + pqB->
q1 * pqC->
q0 + pqB->
q2 * pqC->
q3 - pqB->
q3 * pqC->
q2;
   946                 pqA->
q2 = pqB->
q0 * pqC->
q2 - pqB->
q1 * pqC->
q3 + pqB->
q2 * pqC->
q0 + pqB->
q3 * pqC->
q1;
   947                 pqA->
q3 = pqB->
q0 * pqC->
q3 + pqB->
q1 * pqC->
q2 - pqB->
q2 * pqC->
q1 + pqB->
q3 * pqC->
q0;
   958                 qProd.
q0 = pqA->
q0 * pqB->
q0 - pqA->
q1 * pqB->
q1 - pqA->
q2 * pqB->
q2 - pqA->
q3 * pqB->
q3;
   959                 qProd.
q1 = pqA->
q0 * pqB->
q1 + pqA->
q1 * pqB->
q0 + pqA->
q2 * pqB->
q3 - pqA->
q3 * pqB->
q2;
   960                 qProd.
q2 = pqA->
q0 * pqB->
q2 - pqA->
q1 * pqB->
q3 + pqA->
q2 * pqB->
q0 + pqA->
q3 * pqB->
q1;
   961                 qProd.
q3 = pqA->
q0 * pqB->
q3 + pqA->
q1 * pqB->
q2 - pqA->
q2 * pqB->
q1 + pqA->
q3 * pqB->
q0;
   974                 qProd.
q0 = pqA->
q0 * pqB->
q0 + pqA->
q1 * pqB->
q1 + pqA->
q2 * pqB->
q2 + pqA->
q3 * pqB->
q3;
   975                 qProd.
q1 = pqA->
q0 * pqB->
q1 - pqA->
q1 * pqB->
q0 - pqA->
q2 * pqB->
q3 + pqA->
q3 * pqB->
q2;
   976                 qProd.
q2 = pqA->
q0 * pqB->
q2 + pqA->
q1 * pqB->
q3 - pqA->
q2 * pqB->
q0 - pqA->
q3 * pqB->
q1;
   977                 qProd.
q3 = pqA->
q0 * pqB->
q3 - pqA->
q1 * pqB->
q2 + pqA->
q2 * pqB->
q1 - pqA->
q3 * pqB->
q0;
   988                 fNorm = sqrtf(pqA->
q0 * pqA->
q0 + pqA->
q1 * pqA->
q1 + pqA->
q2 * pqA->
q2 + pqA->
q3 * pqA->
q3);
   992                                 fNorm = 1.0F / fNorm;
  1002                                 pqA->
q1 = pqA->
q2 = pqA->
q3 = 0.0F;
  1021                 pqA->
q1 = pqA->
q2 = pqA->
q3 = 0.0F;
  1031                 float fsqrt1plusudotv;                          
  1035                 fsqrt1plusudotv = sqrtf(fabsf(1.0F + fu[
CHX] * fv[
CHX] + fu[
CHY] * fv[
CHY] + fu[
CHZ] * fv[
CHZ]));
  1044                 if (fsqrt1plusudotv != 0.0F)
  1048                                 pfq->
q1 = -fuxv[
CHX] * ftmp;
  1049                                 pfq->
q2 = -fuxv[
CHY] * ftmp;
  1050                                 pfq->
q3 = -fuxv[
CHZ] * ftmp;
  1060                                 ftmp = sqrtf(fabsf(pfq->
q1 * pfq->
q1 + pfq->
q2 * pfq->
q2 + pfq->
q3 * pfq->
q3));
 float q2
y vector component 
 
#define ONEOVER3840
1 / 3840 
 
void f3DOFMagnetometerMatrixWin8(float fR[][3], float fBc[])
Windows 8 magnetometer 3DOF flat eCompass function, computing rotation matrix fR. ...
 
void f3x3matrixAeqScalar(float A[][3], float Scalar)
function sets every entry in the 3x3 matrix A to a constant scalar 
 
void f3DOFTiltAndroid(float fR[][3], float fGc[])
Android accelerometer 3DOF tilt function computing, rotation matrix fR. 
 
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix 
 
void fQuaternionFromRotationVectorDeg(Quaternion *pq, const float rvecdeg[], float fscaling)
computes normalized rotation quaternion from a rotation vector (deg) 
 
void fNEDAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the NED angles in degrees from the NED rotation matrix 
 
void feCompassNED(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
NED: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDelt...
 
void f3DOFTiltWin8(float fR[][3], float fGc[])
Windows 8 accelerometer 3DOF tilt function computing, rotation matrix fR. 
 
Math approximations file. 
 
#define CHZ
Used to access Z-channel entries in various data data structures. 
 
#define CHY
Used to access Y-channel entries in various data data structures. 
 
#define F180OVERPI
radians to degrees conversion = 180 / pi 
 
void feCompassWin8(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
Win8: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDel...
 
quaternion structure definition 
 
Functions to convert between various orientation representations. 
 
#define ONEOVERSQRT2
1/sqrt(2) 
 
float q3
z vector component 
 
void feCompassAndroid(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
Android: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle f...
 
void fRotationVectorDegFromQuaternion(Quaternion *pq, float rvecdeg[])
computes rotation vector (deg) from rotation quaternion 
 
Matrix manipulation functions. 
 
The sensor_fusion.h file implements the top level programming interface. 
 
float fatan2_deg(float y, float x)
 
void qAeqBxC(Quaternion *pqA, const Quaternion *pqB, const Quaternion *pqC)
function compute the quaternion product qB * qC 
 
void f3x3matrixAeqI(float A[][3])
function sets the 3x3 matrix A to the identity matrix 
 
void fRotationMatrixFromQuaternion(float R[][3], const Quaternion *pq)
compute the rotation matrix from an orientation quaternion 
 
void fLPFOrientationQuaternion(Quaternion *pq, Quaternion *pLPq, float flpf, float fdeltat, float fOmega[])
function low pass filters an orientation quaternion and computes virtual gyro rotation rate ...
 
void fWin8AnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Windows 8 angles in degrees from the Windows 8 rotation matrix 
 
void f3DOFTiltNED(float fR[][3], float fGc[])
Aerospace NED accelerometer 3DOF tilt function, computing rotation matrix fR. 
 
void fqAeqNormqA(Quaternion *pqA)
function normalizes a rotation quaternion and ensures q0 is non-negative 
 
void fveqconjgquq(Quaternion *pfq, float fu[], float fv[])
 
void fqAeq1(Quaternion *pqA)
set a quaternion to the unit quaternion 
 
void fAndroidAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Android angles in degrees from the Android rotation matrix 
 
float q1
x vector component 
 
#define CHX
Used to access X-channel entries in various data data structures. 
 
void f3DOFMagnetometerMatrixAndroid(float fR[][3], float fBc[])
Android magnetometer 3DOF flat eCompass function, computing rotation matrix fR. 
 
#define FPIOVER180
degrees to radians conversion = pi / 180 
 
void f3DOFMagnetometerMatrixNED(float fR[][3], float fBc[])
Aerospace NED magnetometer 3DOF flat eCompass function, computing rotation matrix fR...
 
void qAeqAxB(Quaternion *pqA, const Quaternion *pqB)
function compute the quaternion product qA = qA * qB 
 
Lower level sensor fusion interface. 
 
Quaternion qconjgAxB(const Quaternion *pqA, const Quaternion *pqB)
function compute the quaternion product conjg(qA) * qB