(Mostly) remove Hungarian notation
This commit is contained in:
parent
61cab7d7cd
commit
d41f607b20
8 changed files with 527 additions and 530 deletions
418
fusion.c
418
fusion.c
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2014, Freescale Semiconductor, Inc.
|
||||
// All rights reserved.
|
||||
// vim: set ts=4:
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
// * Neither the name of Freescale Semiconductor, Inc. nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
|
|
@ -61,10 +61,6 @@
|
|||
#define ONEOVER3840 0.0002604166667F // 1 / 3840
|
||||
|
||||
|
||||
#define SENSORFS 100
|
||||
#define OVERSAMPLE_RATIO 4
|
||||
|
||||
|
||||
|
||||
static void fqAeq1(Quaternion_t *pqA);
|
||||
static void feCompassNED(float fR[][3], float *pfDelta, const float fBc[], const float fGp[]);
|
||||
|
|
@ -86,68 +82,69 @@ static float fatan_15deg(float x);
|
|||
|
||||
|
||||
// function initializes the 9DOF Kalman filter
|
||||
void fInit_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV, int16_t iSensorFS, int16_t iOverSampleRatio)
|
||||
void fInit_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV)
|
||||
{
|
||||
int8_t i, j; // loop counters
|
||||
|
||||
// reset the flag denoting that a first 9DOF orientation lock has been achieved
|
||||
SV->iFirstOrientationLock = 0;
|
||||
SV->FirstOrientationLock = 0;
|
||||
|
||||
// compute and store useful product terms to save floating point calculations later
|
||||
SV->fFastdeltat = 1.0F / (float) iSensorFS;
|
||||
SV->fdeltat = (float) iOverSampleRatio * SV->fFastdeltat;
|
||||
SV->fdeltatsq = SV->fdeltat * SV->fdeltat;
|
||||
SV->fcasq = FCA_9DOF_GBY_KALMAN * FCA_9DOF_GBY_KALMAN;
|
||||
SV->fcdsq = FCD_9DOF_GBY_KALMAN * FCD_9DOF_GBY_KALMAN;
|
||||
SV->fQwbplusQvG = FQWB_9DOF_GBY_KALMAN + FQVG_9DOF_GBY_KALMAN;
|
||||
SV->Fastdeltat = 1.0F / (float)SENSORFS;
|
||||
SV->deltat = (float)OVERSAMPLE_RATIO * SV->Fastdeltat;
|
||||
SV->deltatsq = SV->deltat * SV->deltat;
|
||||
SV->casq = FCA_9DOF_GBY_KALMAN * FCA_9DOF_GBY_KALMAN;
|
||||
SV->cdsq = FCD_9DOF_GBY_KALMAN * FCD_9DOF_GBY_KALMAN;
|
||||
SV->QwbplusQvG = FQWB_9DOF_GBY_KALMAN + FQVG_9DOF_GBY_KALMAN;
|
||||
|
||||
// initialize the fixed entries in the measurement matrix C
|
||||
for (i = 0; i < 6; i++) {
|
||||
for (j = 0; j < 12; j++) {
|
||||
SV->fC6x12[i][j]= 0.0F;
|
||||
SV->C6x12[i][j]= 0.0F;
|
||||
}
|
||||
}
|
||||
SV->fC6x12[0][6] = SV->fC6x12[1][7] = SV->fC6x12[2][8] = 1.0F;
|
||||
SV->fC6x12[3][9] = SV->fC6x12[4][10] = SV->fC6x12[5][11] = -1.0F;
|
||||
SV->C6x12[0][6] = SV->C6x12[1][7] = SV->C6x12[2][8] = 1.0F;
|
||||
SV->C6x12[3][9] = SV->C6x12[4][10] = SV->C6x12[5][11] = -1.0F;
|
||||
|
||||
// zero a posteriori orientation, error vector xe+ (thetae+, be+, de+, ae+) and b+ and inertial
|
||||
f3x3matrixAeqI(SV->fRPl);
|
||||
fqAeq1(&(SV->fqPl));
|
||||
f3x3matrixAeqI(SV->RPl);
|
||||
fqAeq1(&(SV->qPl));
|
||||
for (i = X; i <= Z; i++) {
|
||||
SV->fThErrPl[i] = SV->fbErrPl[i] = SV->faErrSePl[i] = SV->fdErrSePl[i] = SV->fbPl[i] = 0.0F;
|
||||
SV->ThErrPl[i] = SV->bErrPl[i] = SV->aErrSePl[i] = SV->dErrSePl[i] = SV->bPl[i] = 0.0F;
|
||||
}
|
||||
|
||||
// initialize the reference geomagnetic vector (uT, global frame)
|
||||
SV->fDeltaPl = 0.0F;
|
||||
SV->DeltaPl = 0.0F;
|
||||
// initialize NED geomagnetic vector to zero degrees inclination
|
||||
SV->fmGl[X] = DEFAULTB;
|
||||
SV->fmGl[Y] = 0.0F;
|
||||
SV->fmGl[Z] = 0.0F;
|
||||
SV->mGl[X] = DEFAULTB;
|
||||
SV->mGl[Y] = 0.0F;
|
||||
SV->mGl[Z] = 0.0F;
|
||||
|
||||
// initialize noise variances for Qv and Qw matrix updates
|
||||
SV->fQvAA = FQVA_9DOF_GBY_KALMAN + FQWA_9DOF_GBY_KALMAN + FDEGTORAD * FDEGTORAD * SV->fdeltatsq * (FQWB_9DOF_GBY_KALMAN + FQVG_9DOF_GBY_KALMAN);
|
||||
SV->fQvMM = FQVM_9DOF_GBY_KALMAN + FQWD_9DOF_GBY_KALMAN + FDEGTORAD * FDEGTORAD * SV->fdeltatsq * DEFAULTB * DEFAULTB * (FQWB_9DOF_GBY_KALMAN + FQVG_9DOF_GBY_KALMAN);
|
||||
SV->QvAA = FQVA_9DOF_GBY_KALMAN + FQWA_9DOF_GBY_KALMAN + FDEGTORAD * FDEGTORAD * SV->deltatsq * (FQWB_9DOF_GBY_KALMAN + FQVG_9DOF_GBY_KALMAN);
|
||||
SV->QvMM = FQVM_9DOF_GBY_KALMAN + FQWD_9DOF_GBY_KALMAN + FDEGTORAD * FDEGTORAD * SV->deltatsq * DEFAULTB * DEFAULTB * (FQWB_9DOF_GBY_KALMAN + FQVG_9DOF_GBY_KALMAN);
|
||||
|
||||
// initialize the 12x12 noise covariance matrix Qw of the a priori error vector xe-
|
||||
// Qw is then recursively updated as P+ = (1 - K * C) * P- = (1 - K * C) * Qw and Qw updated from P+
|
||||
// Qw is then recursively updated as P+ = (1 - K * C) * P- = (1 - K * C) * Qw and Qw
|
||||
// updated from P+
|
||||
// zero the matrix Qw
|
||||
for (i = 0; i < 12; i++) {
|
||||
for (j = 0; j < 12; j++) {
|
||||
SV->fQw12x12[i][j] = 0.0F;
|
||||
SV->Qw12x12[i][j] = 0.0F;
|
||||
}
|
||||
}
|
||||
// loop over non-zero values
|
||||
for (i = 0; i < 3; i++) {
|
||||
// theta_e * theta_e terms
|
||||
SV->fQw12x12[i][i] = FQWINITTHTH_9DOF_GBY_KALMAN;
|
||||
SV->Qw12x12[i][i] = FQWINITTHTH_9DOF_GBY_KALMAN;
|
||||
// b_e * b_e terms
|
||||
SV->fQw12x12[i + 3][i + 3] = FQWINITBB_9DOF_GBY_KALMAN;
|
||||
SV->Qw12x12[i + 3][i + 3] = FQWINITBB_9DOF_GBY_KALMAN;
|
||||
// th_e * b_e terms
|
||||
SV->fQw12x12[i][i + 3] = SV->fQw12x12[i + 3][i] = FQWINITTHB_9DOF_GBY_KALMAN;
|
||||
SV->Qw12x12[i][i + 3] = SV->Qw12x12[i + 3][i] = FQWINITTHB_9DOF_GBY_KALMAN;
|
||||
// a_e * a_e terms
|
||||
SV->fQw12x12[i + 6][i + 6] = FQWINITAA_9DOF_GBY_KALMAN;
|
||||
SV->Qw12x12[i + 6][i + 6] = FQWINITAA_9DOF_GBY_KALMAN;
|
||||
// d_e * d_e terms
|
||||
SV->fQw12x12[i + 9][i + 9] = FQWINITDD_9DOF_GBY_KALMAN;
|
||||
SV->Qw12x12[i + 9][i + 9] = FQWINITDD_9DOF_GBY_KALMAN;
|
||||
}
|
||||
|
||||
// clear the reset flag
|
||||
|
|
@ -160,8 +157,8 @@ void fInit_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV, int16_t iSensorFS, int16_t
|
|||
// 9DOF orientation function implemented using a 12 element Kalman filter
|
||||
void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
||||
const AccelSensor_t *Accel, const MagSensor_t *Mag, const GyroSensor_t *Gyro,
|
||||
const MagCalibration_t *MagCal, int16_t iOverSampleRatio)
|
||||
{
|
||||
const MagCalibration_t *MagCal)
|
||||
{
|
||||
// local scalars and arrays
|
||||
float fopp, fadj, fhyp; // opposite, adjacent and hypoteneuse
|
||||
float fsindelta, fcosdelta; // sin and cos of inclination angle delta
|
||||
|
|
@ -193,7 +190,7 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
|
||||
// do a reset and return if requested
|
||||
if (SV->resetflag) {
|
||||
fInit_9DOF_GBY_KALMAN(SV, SENSORFS, OVERSAMPLE_RATIO);
|
||||
fInit_9DOF_GBY_KALMAN(SV);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -201,16 +198,16 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// initial orientation lock to accelerometer and magnetometer eCompass orientation
|
||||
// *********************************************************************************
|
||||
|
||||
// do a once-only orientation lock after the first valid magnetic calibration
|
||||
if (MagCal->iValidMagCal && !SV->iFirstOrientationLock) {
|
||||
// do a once-only orientation lock after the first valid magnetic calibration
|
||||
if (MagCal->ValidMagCal && !SV->FirstOrientationLock) {
|
||||
// get the 6DOF orientation matrix and initial inclination angle
|
||||
feCompassNED(SV->fRPl, &(SV->fDeltaPl), Mag->fBcFast, Accel->fGpFast);
|
||||
feCompassNED(SV->RPl, &(SV->DeltaPl), Mag->BcFast, Accel->GpFast);
|
||||
|
||||
// get the orientation quaternion from the orientation matrix
|
||||
fQuaternionFromRotationMatrix(SV->fRPl, &(SV->fqPl));
|
||||
fQuaternionFromRotationMatrix(SV->RPl, &(SV->qPl));
|
||||
|
||||
// set the orientation lock flag so this initial alignment is only performed once
|
||||
SV->iFirstOrientationLock = 1;
|
||||
SV->FirstOrientationLock = 1;
|
||||
}
|
||||
|
||||
// *********************************************************************************
|
||||
|
|
@ -219,31 +216,31 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
|
||||
// compute the angular velocity from the averaged high frequency gyro reading.
|
||||
// omega[k] = yG[k] - b-[k] = yG[k] - b+[k-1] (deg/s)
|
||||
SV->fOmega[X] = Gyro->fYp[X] - SV->fbPl[X];
|
||||
SV->fOmega[Y] = Gyro->fYp[Y] - SV->fbPl[Y];
|
||||
SV->fOmega[Z] = Gyro->fYp[Z] - SV->fbPl[Z];
|
||||
SV->Omega[X] = Gyro->Yp[X] - SV->bPl[X];
|
||||
SV->Omega[Y] = Gyro->Yp[Y] - SV->bPl[Y];
|
||||
SV->Omega[Z] = Gyro->Yp[Z] - SV->bPl[Z];
|
||||
|
||||
// initialize the a priori orientation quaternion to the previous a posteriori estimate
|
||||
SV->fqMi = SV->fqPl;
|
||||
SV->qMi = SV->qPl;
|
||||
|
||||
// integrate the buffered high frequency (typically 200Hz) gyro readings
|
||||
for (j = 0; j < iOverSampleRatio; j++) {
|
||||
for (j = 0; j < OVERSAMPLE_RATIO; j++) {
|
||||
// compute the incremental fast (typically 200Hz) rotation vector rvec (deg)
|
||||
for (i = X; i <= Z; i++) {
|
||||
rvec[i] = (((float)Gyro->iYpFast[j][i] * DEG_PER_SEC_PER_COUNT) - SV->fbPl[i])
|
||||
* SV->fFastdeltat;
|
||||
rvec[i] = (((float)Gyro->YpFast[j][i] * DEG_PER_SEC_PER_COUNT) - SV->bPl[i])
|
||||
* SV->Fastdeltat;
|
||||
}
|
||||
|
||||
// compute the incremental quaternion fDeltaq from the rotation vector
|
||||
fQuaternionFromRotationVectorDeg(&(SV->fDeltaq), rvec, 1.0F);
|
||||
fQuaternionFromRotationVectorDeg(&(SV->Deltaq), rvec, 1.0F);
|
||||
|
||||
// incrementally rotate the a priori orientation quaternion fqMi
|
||||
// the a posteriori quaternion fqPl is re-normalized later so this update is stable
|
||||
qAeqAxB(&(SV->fqMi), &(SV->fDeltaq));
|
||||
qAeqAxB(&(SV->qMi), &(SV->Deltaq));
|
||||
}
|
||||
|
||||
// get the a priori rotation matrix from the a priori quaternion
|
||||
fRotationMatrixFromQuaternion(SV->fRMi, &(SV->fqMi));
|
||||
fRotationMatrixFromQuaternion(SV->RMi, &(SV->qMi));
|
||||
|
||||
// *********************************************************************************
|
||||
// calculate a priori gyro, accelerometer and magnetometer estimates
|
||||
|
|
@ -255,22 +252,25 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// compute the a priori gyro estimate of the gravitational vector (g, sensor frame)
|
||||
// using an absolute rotation of the global frame gravity vector (with magnitude 1g)
|
||||
// NED gravity is along positive z axis
|
||||
SV->fgSeGyMi[i] = SV->fRMi[i][Z];
|
||||
SV->gSeGyMi[i] = SV->RMi[i][Z];
|
||||
|
||||
// compute a priori acceleration (a-) (g, sensor frame) from decayed a posteriori estimate (g, sensor frame)
|
||||
SV->faSeMi[i] = FCA_9DOF_GBY_KALMAN * SV->faSePl[i];
|
||||
// compute a priori acceleration (a-) (g, sensor frame) from decayed a
|
||||
// posteriori estimate (g, sensor frame)
|
||||
SV->aSeMi[i] = FCA_9DOF_GBY_KALMAN * SV->aSePl[i];
|
||||
|
||||
// compute the a priori gravity error vector (accelerometer minus gyro estimates) (g, sensor frame)
|
||||
// compute the a priori gravity error vector (accelerometer minus gyro estimates)
|
||||
// (g, sensor frame)
|
||||
// NED and Windows 8 have positive sign for gravity: y = g - a and g = y + a
|
||||
SV->fgErrSeMi[i] = Accel->fGpFast[i] + SV->faSeMi[i] - SV->fgSeGyMi[i];
|
||||
SV->gErrSeMi[i] = Accel->GpFast[i] + SV->aSeMi[i] - SV->gSeGyMi[i];
|
||||
|
||||
// compute the a priori gyro estimate of the geomagnetic vector (uT, sensor frame)
|
||||
// using an absolute rotation of the global frame geomagnetic vector (with magnitude B uT)
|
||||
// NED y component of geomagnetic vector in global frame is zero
|
||||
SV->fmSeGyMi[i] = SV->fRMi[i][X] * SV->fmGl[X] + SV->fRMi[i][Z] * SV->fmGl[Z];
|
||||
SV->mSeGyMi[i] = SV->RMi[i][X] * SV->mGl[X] + SV->RMi[i][Z] * SV->mGl[Z];
|
||||
|
||||
// compute the a priori geomagnetic error vector (magnetometer minus gyro estimates) (g, sensor frame)
|
||||
SV->fmErrSeMi[i] = Mag->fBcFast[i] - SV->fmSeGyMi[i];
|
||||
// compute the a priori geomagnetic error vector (magnetometer minus gyro estimates)
|
||||
// (g, sensor frame)
|
||||
SV->mErrSeMi[i] = Mag->BcFast[i] - SV->mSeGyMi[i];
|
||||
}
|
||||
|
||||
// *********************************************************************************
|
||||
|
|
@ -278,30 +278,30 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// *********************************************************************************
|
||||
|
||||
// update measurement matrix C with -alpha(g-)x and -alpha(m-)x from gyro (g, uT, sensor frame)
|
||||
SV->fC6x12[0][1] = FDEGTORAD * SV->fgSeGyMi[Z];
|
||||
SV->fC6x12[0][2] = -FDEGTORAD * SV->fgSeGyMi[Y];
|
||||
SV->fC6x12[1][2] = FDEGTORAD * SV->fgSeGyMi[X];
|
||||
SV->fC6x12[1][0] = -SV->fC6x12[0][1];
|
||||
SV->fC6x12[2][0] = -SV->fC6x12[0][2];
|
||||
SV->fC6x12[2][1] = -SV->fC6x12[1][2];
|
||||
SV->fC6x12[3][1] = FDEGTORAD * SV->fmSeGyMi[Z];
|
||||
SV->fC6x12[3][2] = -FDEGTORAD * SV->fmSeGyMi[Y];
|
||||
SV->fC6x12[4][2] = FDEGTORAD * SV->fmSeGyMi[X];
|
||||
SV->fC6x12[4][0] = -SV->fC6x12[3][1];
|
||||
SV->fC6x12[5][0] = -SV->fC6x12[3][2];
|
||||
SV->fC6x12[5][1] = -SV->fC6x12[4][2];
|
||||
SV->fC6x12[0][4] = -SV->fdeltat * SV->fC6x12[0][1];
|
||||
SV->fC6x12[0][5] = -SV->fdeltat * SV->fC6x12[0][2];
|
||||
SV->fC6x12[1][5] = -SV->fdeltat * SV->fC6x12[1][2];
|
||||
SV->fC6x12[1][3]= -SV->fC6x12[0][4];
|
||||
SV->fC6x12[2][3]= -SV->fC6x12[0][5];
|
||||
SV->fC6x12[2][4]= -SV->fC6x12[1][5];
|
||||
SV->fC6x12[3][4] = -SV->fdeltat * SV->fC6x12[3][1];
|
||||
SV->fC6x12[3][5] = -SV->fdeltat * SV->fC6x12[3][2];
|
||||
SV->fC6x12[4][5] = -SV->fdeltat * SV->fC6x12[4][2];
|
||||
SV->fC6x12[4][3] = -SV->fC6x12[3][4];
|
||||
SV->fC6x12[5][3] = -SV->fC6x12[3][5];
|
||||
SV->fC6x12[5][4] = -SV->fC6x12[4][5];
|
||||
SV->C6x12[0][1] = FDEGTORAD * SV->gSeGyMi[Z];
|
||||
SV->C6x12[0][2] = -FDEGTORAD * SV->gSeGyMi[Y];
|
||||
SV->C6x12[1][2] = FDEGTORAD * SV->gSeGyMi[X];
|
||||
SV->C6x12[1][0] = -SV->C6x12[0][1];
|
||||
SV->C6x12[2][0] = -SV->C6x12[0][2];
|
||||
SV->C6x12[2][1] = -SV->C6x12[1][2];
|
||||
SV->C6x12[3][1] = FDEGTORAD * SV->mSeGyMi[Z];
|
||||
SV->C6x12[3][2] = -FDEGTORAD * SV->mSeGyMi[Y];
|
||||
SV->C6x12[4][2] = FDEGTORAD * SV->mSeGyMi[X];
|
||||
SV->C6x12[4][0] = -SV->C6x12[3][1];
|
||||
SV->C6x12[5][0] = -SV->C6x12[3][2];
|
||||
SV->C6x12[5][1] = -SV->C6x12[4][2];
|
||||
SV->C6x12[0][4] = -SV->deltat * SV->C6x12[0][1];
|
||||
SV->C6x12[0][5] = -SV->deltat * SV->C6x12[0][2];
|
||||
SV->C6x12[1][5] = -SV->deltat * SV->C6x12[1][2];
|
||||
SV->C6x12[1][3]= -SV->C6x12[0][4];
|
||||
SV->C6x12[2][3]= -SV->C6x12[0][5];
|
||||
SV->C6x12[2][4]= -SV->C6x12[1][5];
|
||||
SV->C6x12[3][4] = -SV->deltat * SV->C6x12[3][1];
|
||||
SV->C6x12[3][5] = -SV->deltat * SV->C6x12[3][2];
|
||||
SV->C6x12[4][5] = -SV->deltat * SV->C6x12[4][2];
|
||||
SV->C6x12[4][3] = -SV->C6x12[3][4];
|
||||
SV->C6x12[5][3] = -SV->C6x12[3][5];
|
||||
SV->C6x12[5][4] = -SV->C6x12[4][5];
|
||||
|
||||
// *********************************************************************************
|
||||
// calculate the Kalman gain matrix K
|
||||
|
|
@ -322,10 +322,10 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
*pftmpA12x6ij = 0.0F;
|
||||
|
||||
// initialize pfC6x12jk for current j, k=0
|
||||
pfC6x12jk = SV->fC6x12[j];
|
||||
pfC6x12jk = SV->C6x12[j];
|
||||
|
||||
// initialize pfQw12x12ik for current i, k=0
|
||||
pfQw12x12ik = SV->fQw12x12[i];
|
||||
pfQw12x12ik = SV->Qw12x12[i];
|
||||
|
||||
// sum matrix products over inner loop over k
|
||||
for (k = 0; k < 12; k++) {
|
||||
|
|
@ -342,27 +342,27 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
pfC6x12jk++;
|
||||
pfQw12x12ik++;
|
||||
|
||||
} // end of loop over k
|
||||
}
|
||||
|
||||
// increment pftmpA12x6ij for next iteration of j
|
||||
pftmpA12x6ij++;
|
||||
|
||||
} // end of loop over j
|
||||
} // end of loop over i
|
||||
}
|
||||
}
|
||||
|
||||
// set symmetric P+ (6x6 scratch sub-matrix) to C * P- * C^T + Qv
|
||||
// = C * (Qw * C^T) + Qv = C * ftmpA12x6 + Qv
|
||||
// both C and ftmpA12x6 are sparse but not symmetric
|
||||
for (i = 0; i < 6; i++) { // loop over rows of P+
|
||||
// initialize pfPPlus12x12ij for current i, j=i
|
||||
pfPPlus12x12ij = SV->fPPlus12x12[i] + i;
|
||||
pfPPlus12x12ij = SV->PPlus12x12[i] + i;
|
||||
|
||||
for (j = i; j < 6; j++) { // loop over above diagonal columns of P+
|
||||
// zero P+[i][j]
|
||||
// zero P+[i][j]
|
||||
*pfPPlus12x12ij = 0.0F;
|
||||
|
||||
// initialize pfC6x12ik for current i, k=0
|
||||
pfC6x12ik = SV->fC6x12[i];
|
||||
pfC6x12ik = SV->C6x12[i];
|
||||
|
||||
// initialize pftmpA12x6kj for current j, k=0
|
||||
pftmpA12x6kj = *ftmpA12x6 + j;
|
||||
|
|
@ -379,33 +379,33 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
}
|
||||
|
||||
// update pfC6x12ik and pftmpA12x6kj for next iteration of k
|
||||
pfC6x12ik++;
|
||||
pfC6x12ik++;
|
||||
pftmpA12x6kj += 6;
|
||||
|
||||
} // end of loop over k
|
||||
}
|
||||
|
||||
// increment pfPPlus12x12ij for next iteration of j
|
||||
pfPPlus12x12ij++;
|
||||
|
||||
} // end of loop over j
|
||||
} // end of loop over i
|
||||
}
|
||||
}
|
||||
|
||||
// add in noise covariance terms to the diagonal
|
||||
SV->fPPlus12x12[0][0] += SV->fQvAA;
|
||||
SV->fPPlus12x12[1][1] += SV->fQvAA;
|
||||
SV->fPPlus12x12[2][2] += SV->fQvAA;
|
||||
SV->fPPlus12x12[3][3] += SV->fQvMM;
|
||||
SV->fPPlus12x12[4][4] += SV->fQvMM;
|
||||
SV->fPPlus12x12[5][5] += SV->fQvMM;
|
||||
SV->PPlus12x12[0][0] += SV->QvAA;
|
||||
SV->PPlus12x12[1][1] += SV->QvAA;
|
||||
SV->PPlus12x12[2][2] += SV->QvAA;
|
||||
SV->PPlus12x12[3][3] += SV->QvMM;
|
||||
SV->PPlus12x12[4][4] += SV->QvMM;
|
||||
SV->PPlus12x12[5][5] += SV->QvMM;
|
||||
|
||||
// copy above diagonal elements of P+ (6x6 scratch sub-matrix) to below diagonal
|
||||
for (i = 1; i < 6; i++)
|
||||
for (j = 0; j < i; j++)
|
||||
SV->fPPlus12x12[i][j] = SV->fPPlus12x12[j][i];
|
||||
for (i = 1; i < 6; i++)
|
||||
for (j = 0; j < i; j++)
|
||||
SV->PPlus12x12[i][j] = SV->PPlus12x12[j][i];
|
||||
|
||||
// calculate inverse of P+ (6x6 scratch sub-matrix) = inv(C * P- * C^T + Qv) = inv(C * Qw * C^T + Qv)
|
||||
for (i = 0; i < 6; i++) {
|
||||
pfRows[i] = SV->fPPlus12x12[i];
|
||||
pfRows[i] = SV->PPlus12x12[i];
|
||||
}
|
||||
fmatrixAeqInvA(pfRows, iColInd, iRowInd, iPivot, 3);
|
||||
|
||||
|
|
@ -415,7 +415,7 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// K is not symmetric because C is not symmetric
|
||||
for (i = 0; i < 12; i++) { // loop over rows of K12x6
|
||||
// initialize pfK12x6ij for current i, j=0
|
||||
pfK12x6ij = SV->fK12x6[i];
|
||||
pfK12x6ij = SV->K12x6[i];
|
||||
|
||||
for (j = 0; j < 6; j++) { // loop over columns of K12x6
|
||||
// zero the matrix element fK12x6[i][j]
|
||||
|
|
@ -425,7 +425,7 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
pftmpA12x6ik = ftmpA12x6[i];
|
||||
|
||||
// initialize pfPPlus12x12kj for current j, k=0
|
||||
pfPPlus12x12kj = *SV->fPPlus12x12 + j;
|
||||
pfPPlus12x12kj = *SV->PPlus12x12 + j;
|
||||
|
||||
// sum matrix products over inner loop over k
|
||||
for (k = 0; k < 6; k++) {
|
||||
|
|
@ -437,13 +437,13 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
pftmpA12x6ik++;
|
||||
pfPPlus12x12kj += 12;
|
||||
|
||||
} // end of loop over k
|
||||
}
|
||||
|
||||
// increment pfK12x6ij for the next iteration of j
|
||||
pfK12x6ij++;
|
||||
|
||||
} // end of loop over j
|
||||
} // end of loop over i
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************************************************************
|
||||
// calculate a posteriori error estimate: xe+ = K * ze-
|
||||
|
|
@ -452,40 +452,40 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// first calculate all four error vector components using accelerometer error component only
|
||||
// for fThErrPl, fbErrPl, faErrSePl but also magnetometer for fdErrSePl
|
||||
for (i = X; i <= Z; i++) {
|
||||
SV->fThErrPl[i] = SV->fK12x6[i][0] * SV->fgErrSeMi[X] +
|
||||
SV->fK12x6[i][1] * SV->fgErrSeMi[Y] +
|
||||
SV->fK12x6[i][2] * SV->fgErrSeMi[Z];
|
||||
SV->fbErrPl[i] = SV->fK12x6[i + 3][0] * SV->fgErrSeMi[X] +
|
||||
SV->fK12x6[i + 3][1] * SV->fgErrSeMi[Y] +
|
||||
SV->fK12x6[i + 3][2] * SV->fgErrSeMi[Z];
|
||||
SV->faErrSePl[i] = SV->fK12x6[i + 6][0] * SV->fgErrSeMi[X] +
|
||||
SV->fK12x6[i + 6][1] * SV->fgErrSeMi[Y] +
|
||||
SV->fK12x6[i + 6][2] * SV->fgErrSeMi[Z];
|
||||
SV->fdErrSePl[i] = SV->fK12x6[i + 9][0] * SV->fgErrSeMi[X] +
|
||||
SV->fK12x6[i + 9][1] * SV->fgErrSeMi[Y] +
|
||||
SV->fK12x6[i + 9][2] * SV->fgErrSeMi[Z] +
|
||||
SV->fK12x6[i + 9][3] * SV->fmErrSeMi[X] +
|
||||
SV->fK12x6[i + 9][4] * SV->fmErrSeMi[Y] +
|
||||
SV->fK12x6[i + 9][5] * SV->fmErrSeMi[Z];
|
||||
SV->ThErrPl[i] = SV->K12x6[i][0] * SV->gErrSeMi[X] +
|
||||
SV->K12x6[i][1] * SV->gErrSeMi[Y] +
|
||||
SV->K12x6[i][2] * SV->gErrSeMi[Z];
|
||||
SV->bErrPl[i] = SV->K12x6[i + 3][0] * SV->gErrSeMi[X] +
|
||||
SV->K12x6[i + 3][1] * SV->gErrSeMi[Y] +
|
||||
SV->K12x6[i + 3][2] * SV->gErrSeMi[Z];
|
||||
SV->aErrSePl[i] = SV->K12x6[i + 6][0] * SV->gErrSeMi[X] +
|
||||
SV->K12x6[i + 6][1] * SV->gErrSeMi[Y] +
|
||||
SV->K12x6[i + 6][2] * SV->gErrSeMi[Z];
|
||||
SV->dErrSePl[i] = SV->K12x6[i + 9][0] * SV->gErrSeMi[X] +
|
||||
SV->K12x6[i + 9][1] * SV->gErrSeMi[Y] +
|
||||
SV->K12x6[i + 9][2] * SV->gErrSeMi[Z] +
|
||||
SV->K12x6[i + 9][3] * SV->mErrSeMi[X] +
|
||||
SV->K12x6[i + 9][4] * SV->mErrSeMi[Y] +
|
||||
SV->K12x6[i + 9][5] * SV->mErrSeMi[Z];
|
||||
}
|
||||
|
||||
// set the magnetic jamming flag if there is a significant magnetic error power after calibration
|
||||
ftmp = SV->fdErrSePl[X] * SV->fdErrSePl[X] + SV->fdErrSePl[Y] * SV->fdErrSePl[Y] +
|
||||
SV->fdErrSePl[Z] * SV->fdErrSePl[Z];
|
||||
iMagJamming = (MagCal->iValidMagCal) && (ftmp > MagCal->fFourBsq);
|
||||
ftmp = SV->dErrSePl[X] * SV->dErrSePl[X] + SV->dErrSePl[Y] * SV->dErrSePl[Y] +
|
||||
SV->dErrSePl[Z] * SV->dErrSePl[Z];
|
||||
iMagJamming = (MagCal->ValidMagCal) && (ftmp > MagCal->FourBsq);
|
||||
|
||||
// add the remaining magnetic error terms if there is calibration and no magnetic jamming
|
||||
if (MagCal->iValidMagCal && !iMagJamming) {
|
||||
if (MagCal->ValidMagCal && !iMagJamming) {
|
||||
for (i = X; i <= Z; i++) {
|
||||
SV->fThErrPl[i] += SV->fK12x6[i][3] * SV->fmErrSeMi[X] +
|
||||
SV->fK12x6[i][4] * SV->fmErrSeMi[Y] +
|
||||
SV->fK12x6[i][5] * SV->fmErrSeMi[Z];
|
||||
SV->fbErrPl[i] += SV->fK12x6[i + 3][3] * SV->fmErrSeMi[X] +
|
||||
SV->fK12x6[i + 3][4] * SV->fmErrSeMi[Y] +
|
||||
SV->fK12x6[i + 3][5] * SV->fmErrSeMi[Z];
|
||||
SV->faErrSePl[i] += SV->fK12x6[i + 6][3] * SV->fmErrSeMi[X] +
|
||||
SV->fK12x6[i + 6][4] * SV->fmErrSeMi[Y] +
|
||||
SV->fK12x6[i + 6][5] * SV->fmErrSeMi[Z];
|
||||
SV->ThErrPl[i] += SV->K12x6[i][3] * SV->mErrSeMi[X] +
|
||||
SV->K12x6[i][4] * SV->mErrSeMi[Y] +
|
||||
SV->K12x6[i][5] * SV->mErrSeMi[Z];
|
||||
SV->bErrPl[i] += SV->K12x6[i + 3][3] * SV->mErrSeMi[X] +
|
||||
SV->K12x6[i + 3][4] * SV->mErrSeMi[Y] +
|
||||
SV->K12x6[i + 3][5] * SV->mErrSeMi[Z];
|
||||
SV->aErrSePl[i] += SV->K12x6[i + 6][3] * SV->mErrSeMi[X] +
|
||||
SV->K12x6[i + 6][4] * SV->mErrSeMi[Y] +
|
||||
SV->K12x6[i + 6][5] * SV->mErrSeMi[Z];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -494,61 +494,61 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// *********************************************************************************
|
||||
|
||||
// get the a posteriori delta quaternion
|
||||
fQuaternionFromRotationVectorDeg(&(SV->fDeltaq), SV->fThErrPl, -1.0F);
|
||||
fQuaternionFromRotationVectorDeg(&(SV->Deltaq), SV->ThErrPl, -1.0F);
|
||||
|
||||
// compute the a posteriori orientation quaternion fqPl = fqMi * Deltaq(-thetae+)
|
||||
// the resulting quaternion may have negative scalar component q0
|
||||
qAeqBxC(&(SV->fqPl), &(SV->fqMi), &(SV->fDeltaq));
|
||||
qAeqBxC(&(SV->qPl), &(SV->qMi), &(SV->Deltaq));
|
||||
|
||||
// normalize the a posteriori orientation quaternion to stop error propagation
|
||||
// normalize the a posteriori orientation quaternion to stop error propagation
|
||||
// the renormalization function ensures that the scalar component q0 is non-negative
|
||||
fqAeqNormqA(&(SV->fqPl));
|
||||
fqAeqNormqA(&(SV->qPl));
|
||||
|
||||
// compute the a posteriori rotation matrix from the a posteriori quaternion
|
||||
fRotationMatrixFromQuaternion(SV->fRPl, &(SV->fqPl));
|
||||
fRotationMatrixFromQuaternion(SV->RPl, &(SV->qPl));
|
||||
|
||||
// compute the rotation vector from the a posteriori quaternion
|
||||
fRotationVectorDegFromQuaternion(&(SV->fqPl), SV->fRVecPl);
|
||||
fRotationVectorDegFromQuaternion(&(SV->qPl), SV->RVecPl);
|
||||
|
||||
// update the a posteriori gyro offset vector b+ and
|
||||
// assign the entire linear acceleration error vector to update the linear acceleration
|
||||
for (i = X; i <= Z; i++) {
|
||||
// b+[k] = b-[k] - be+[k] = b+[k] - be+[k] (deg/s)
|
||||
SV->fbPl[i] -= SV->fbErrPl[i];
|
||||
SV->bPl[i] -= SV->bErrPl[i];
|
||||
// a+ = a- - ae+ (g, sensor frame)
|
||||
SV->faSePl[i] = SV->faSeMi[i] - SV->faErrSePl[i];
|
||||
SV->aSePl[i] = SV->aSeMi[i] - SV->aErrSePl[i];
|
||||
}
|
||||
|
||||
// compute the linear acceleration in the global frame from the accelerometer measurement (sensor frame).
|
||||
// de-rotate the accelerometer measurement from the sensor to global frame using the inverse (transpose)
|
||||
// de-rotate the accelerometer measurement from the sensor to global frame using the inverse (transpose)
|
||||
// of the a posteriori rotation matrix
|
||||
SV->faGlPl[X] = SV->fRPl[X][X] * Accel->fGpFast[X] + SV->fRPl[Y][X] * Accel->fGpFast[Y] +
|
||||
SV->fRPl[Z][X] * Accel->fGpFast[Z];
|
||||
SV->faGlPl[Y] = SV->fRPl[X][Y] * Accel->fGpFast[X] + SV->fRPl[Y][Y] * Accel->fGpFast[Y] +
|
||||
SV->fRPl[Z][Y] * Accel->fGpFast[Z];
|
||||
SV->faGlPl[Z] = SV->fRPl[X][Z] * Accel->fGpFast[X] + SV->fRPl[Y][Z] * Accel->fGpFast[Y] +
|
||||
SV->fRPl[Z][Z] * Accel->fGpFast[Z];
|
||||
// remove gravity and correct the sign if the coordinate system is gravity positive / acceleration negative
|
||||
SV->aGlPl[X] = SV->RPl[X][X] * Accel->GpFast[X] + SV->RPl[Y][X] * Accel->GpFast[Y] +
|
||||
SV->RPl[Z][X] * Accel->GpFast[Z];
|
||||
SV->aGlPl[Y] = SV->RPl[X][Y] * Accel->GpFast[X] + SV->RPl[Y][Y] * Accel->GpFast[Y] +
|
||||
SV->RPl[Z][Y] * Accel->GpFast[Z];
|
||||
SV->aGlPl[Z] = SV->RPl[X][Z] * Accel->GpFast[X] + SV->RPl[Y][Z] * Accel->GpFast[Y] +
|
||||
SV->RPl[Z][Z] * Accel->GpFast[Z];
|
||||
// remove gravity and correct the sign if the coordinate system is gravity positive / acceleration negative
|
||||
// gravity positive NED
|
||||
SV->faGlPl[X] = -SV->faGlPl[X];
|
||||
SV->faGlPl[Y] = -SV->faGlPl[Y];
|
||||
SV->faGlPl[Z] = -(SV->faGlPl[Z] - 1.0F);
|
||||
SV->aGlPl[X] = -SV->aGlPl[X];
|
||||
SV->aGlPl[Y] = -SV->aGlPl[Y];
|
||||
SV->aGlPl[Z] = -(SV->aGlPl[Z] - 1.0F);
|
||||
|
||||
// update the reference geomagnetic vector using magnetic disturbance error if valid calibration and no jamming
|
||||
if (MagCal->iValidMagCal && !iMagJamming) {
|
||||
if (MagCal->ValidMagCal && !iMagJamming) {
|
||||
// de-rotate the NED magnetic disturbance error de+ from the sensor to the global reference frame
|
||||
// using the inverse (transpose) of the a posteriori rotation matrix
|
||||
SV->fdErrGlPl[X] = SV->fRPl[X][X] * SV->fdErrSePl[X] +
|
||||
SV->fRPl[Y][X] * SV->fdErrSePl[Y] +
|
||||
SV->fRPl[Z][X] * SV->fdErrSePl[Z];
|
||||
SV->fdErrGlPl[Z] = SV->fRPl[X][Z] * SV->fdErrSePl[X] +
|
||||
SV->fRPl[Y][Z] * SV->fdErrSePl[Y] +
|
||||
SV->fRPl[Z][Z] * SV->fdErrSePl[Z];
|
||||
SV->dErrGlPl[X] = SV->RPl[X][X] * SV->dErrSePl[X] +
|
||||
SV->RPl[Y][X] * SV->dErrSePl[Y] +
|
||||
SV->RPl[Z][X] * SV->dErrSePl[Z];
|
||||
SV->dErrGlPl[Z] = SV->RPl[X][Z] * SV->dErrSePl[X] +
|
||||
SV->RPl[Y][Z] * SV->dErrSePl[Y] +
|
||||
SV->RPl[Z][Z] * SV->dErrSePl[Z];
|
||||
|
||||
// compute components of the new geomagnetic vector
|
||||
// the north pointing component fadj must always be non-negative
|
||||
fopp = SV->fmGl[Z] - SV->fdErrGlPl[Z];
|
||||
fadj = SV->fmGl[X] - SV->fdErrGlPl[X];
|
||||
fopp = SV->mGl[Z] - SV->dErrGlPl[Z];
|
||||
fadj = SV->mGl[X] - SV->dErrGlPl[X];
|
||||
if (fadj < 0.0F) {
|
||||
fadj = 0.0F;
|
||||
}
|
||||
|
|
@ -571,19 +571,19 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
}
|
||||
|
||||
// compute the new geomagnetic vector (always north pointing)
|
||||
SV->fDeltaPl = fasin_deg(fsindelta);
|
||||
SV->fmGl[X] = MagCal->fB * fcosdelta;
|
||||
SV->fmGl[Z] = MagCal->fB * fsindelta;
|
||||
SV->DeltaPl = fasin_deg(fsindelta);
|
||||
SV->mGl[X] = MagCal->B * fcosdelta;
|
||||
SV->mGl[Z] = MagCal->B * fsindelta;
|
||||
} // end hyp == 0.0F
|
||||
} // end iValidMagCal
|
||||
} // end ValidMagCal
|
||||
|
||||
// *********************************************************************************
|
||||
// compute the a posteriori Euler angles from the orientation matrix
|
||||
// *********************************************************************************
|
||||
|
||||
// calculate the NED Euler angles
|
||||
fNEDAnglesDegFromRotationMatrix(SV->fRPl, &(SV->fPhiPl), &(SV->fThePl), &(SV->fPsiPl),
|
||||
&(SV->fRhoPl), &(SV->fChiPl));
|
||||
fNEDAnglesDegFromRotationMatrix(SV->RPl, &(SV->PhiPl), &(SV->ThePl), &(SV->PsiPl),
|
||||
&(SV->RhoPl), &(SV->ChiPl));
|
||||
|
||||
// ***********************************************************************************
|
||||
// calculate (symmetric) a posteriori error covariance matrix P+
|
||||
|
|
@ -597,17 +597,17 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// the resulting matrix is sparse but not symmetric
|
||||
for (i = 0; i < 6; i++) {
|
||||
// initialize pfPPlus12x12ij for current i, j=0
|
||||
pfPPlus12x12ij = SV->fPPlus12x12[i];
|
||||
pfPPlus12x12ij = SV->PPlus12x12[i];
|
||||
|
||||
for (j = 0; j < 12; j++) {
|
||||
// zero P+[i][j]
|
||||
// zero P+[i][j]
|
||||
*pfPPlus12x12ij = 0.0F;
|
||||
|
||||
// initialize pfC6x12ik for current i, k=0
|
||||
pfC6x12ik = SV->fC6x12[i];
|
||||
pfC6x12ik = SV->C6x12[i];
|
||||
|
||||
// initialize pfQw12x12kj for current j, k=0
|
||||
pfQw12x12kj = &SV->fQw12x12[0][j];
|
||||
pfQw12x12kj = &SV->Qw12x12[0][j];
|
||||
|
||||
// sum matrix products over inner loop over k
|
||||
for (k = 0; k < 12; k++) {
|
||||
|
|
@ -624,13 +624,13 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
pfC6x12ik++;
|
||||
pfQw12x12kj += 12;
|
||||
|
||||
} // end of loop over k
|
||||
}
|
||||
|
||||
// increment pfPPlus12x12ij for next iteration of j
|
||||
pfPPlus12x12ij++;
|
||||
|
||||
} // end of loop over j
|
||||
} // end of loop over i
|
||||
}
|
||||
}
|
||||
|
||||
// compute P+ = (I12 - K * C) * Qw = Qw - K * (C * Qw) = Qw - K * P+ (6x12 sub-matrix)
|
||||
// storing result P+ in Qw and over-writing Qw which is OK since Qw is later computed from P+
|
||||
|
|
@ -638,14 +638,14 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// only on and above diagonal terms of P+ are computed since P+ is symmetric
|
||||
for (i = 0; i < 12; i++) {
|
||||
// initialize pfQw12x12ij for current i, j=i
|
||||
pfQw12x12ij = SV->fQw12x12[i] + i;
|
||||
pfQw12x12ij = SV->Qw12x12[i] + i;
|
||||
|
||||
for (j = i; j < 12; j++) {
|
||||
// initialize pfK12x6ik for current i, k=0
|
||||
pfK12x6ik = SV->fK12x6[i];
|
||||
pfK12x6ik = SV->K12x6[i];
|
||||
|
||||
// initialize pfPPlus12x12kj for current j, k=0
|
||||
pfPPlus12x12kj = *SV->fPPlus12x12 + j;
|
||||
pfPPlus12x12kj = *SV->PPlus12x12 + j;
|
||||
|
||||
// compute on and above diagonal matrix entry
|
||||
for (k = 0; k < 6; k++) {
|
||||
|
|
@ -653,34 +653,30 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
if (*pfPPlus12x12kj != 0.0F) {
|
||||
*pfQw12x12ij -= *pfK12x6ik * *pfPPlus12x12kj;
|
||||
}
|
||||
|
||||
// increment pfK12x6ik and pfPPlus12x12kj for next iteration of k
|
||||
pfK12x6ik++;
|
||||
pfPPlus12x12kj += 12;
|
||||
|
||||
} // end of loop over k
|
||||
}
|
||||
|
||||
// increment pfQw12x12ij for next iteration of j
|
||||
pfQw12x12ij++;
|
||||
|
||||
} // end of loop over j
|
||||
} // end of loop over i
|
||||
}
|
||||
}
|
||||
|
||||
// Qw now holds the on and above diagonal elements of P+
|
||||
// so perform a simple copy to the all elements of P+
|
||||
// after execution of this code P+ is valid but Qw remains invalid
|
||||
for (i = 0; i < 12; i++) {
|
||||
// initialize pfPPlus12x12ij and pfQw12x12ij for current i, j=i
|
||||
pfPPlus12x12ij = SV->fPPlus12x12[i] + i;
|
||||
pfQw12x12ij = SV->fQw12x12[i] + i;
|
||||
pfPPlus12x12ij = SV->PPlus12x12[i] + i;
|
||||
pfQw12x12ij = SV->Qw12x12[i] + i;
|
||||
|
||||
// copy the on-diagonal elements and increment pointers to enter loop at j=i+1
|
||||
*(pfPPlus12x12ij++) = *(pfQw12x12ij++);
|
||||
|
||||
// loop over above diagonal columns j copying to below-diagonal elements
|
||||
for (j = i + 1; j < 12; j++)
|
||||
{
|
||||
*(pfPPlus12x12ij++)= SV->fPPlus12x12[j][i] = *(pfQw12x12ij++);
|
||||
for (j = i + 1; j < 12; j++) {
|
||||
*(pfPPlus12x12ij++)= SV->PPlus12x12[j][i] = *(pfQw12x12ij++);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -693,26 +689,26 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
// zero the matrix Qw
|
||||
for (i = 0; i < 12; i++) {
|
||||
for (j = 0; j < 12; j++) {
|
||||
SV->fQw12x12[i][j] = 0.0F;
|
||||
SV->Qw12x12[i][j] = 0.0F;
|
||||
}
|
||||
}
|
||||
|
||||
// update the covariance matrix components
|
||||
for (i = 0; i < 3; i++) {
|
||||
// Qw[th-th-] = Qw[0-2][0-2] = E[th-(th-)^T] = Q[th+th+] + deltat^2 * (Q[b+b+] + (Qwb + QvG) * I)
|
||||
SV->fQw12x12[i][i] = SV->fPPlus12x12[i][i] + SV->fdeltatsq * (SV->fPPlus12x12[i + 3][i + 3] + SV->fQwbplusQvG);
|
||||
SV->Qw12x12[i][i] = SV->PPlus12x12[i][i] + SV->deltatsq * (SV->PPlus12x12[i + 3][i + 3] + SV->QwbplusQvG);
|
||||
|
||||
// Qw[b-b-] = Qw[3-5][3-5] = E[b-(b-)^T] = Q[b+b+] + Qwb * I
|
||||
SV->fQw12x12[i + 3][i + 3] = SV->fPPlus12x12[i + 3][i + 3] + FQWB_9DOF_GBY_KALMAN;
|
||||
SV->Qw12x12[i + 3][i + 3] = SV->PPlus12x12[i + 3][i + 3] + FQWB_9DOF_GBY_KALMAN;
|
||||
|
||||
// Qw[th-b-] = Qw[0-2][3-5] = E[th-(b-)^T] = -deltat * (Q[b+b+] + Qwb * I) = -deltat * Qw[b-b-]
|
||||
SV->fQw12x12[i][i + 3] = SV->fQw12x12[i + 3][i] = -SV->fdeltat * SV->fQw12x12[i + 3][i + 3];
|
||||
SV->Qw12x12[i][i + 3] = SV->Qw12x12[i + 3][i] = -SV->deltat * SV->Qw12x12[i + 3][i + 3];
|
||||
|
||||
// Qw[a-a-] = Qw[6-8][6-8] = E[a-(a-)^T] = ca^2 * Q[a+a+] + Qwa * I
|
||||
SV->fQw12x12[i + 6][i + 6] = SV->fcasq * SV->fPPlus12x12[i + 6][i + 6] + FQWA_9DOF_GBY_KALMAN;
|
||||
SV->Qw12x12[i + 6][i + 6] = SV->casq * SV->PPlus12x12[i + 6][i + 6] + FQWA_9DOF_GBY_KALMAN;
|
||||
|
||||
// Qw[d-d-] = Qw[9-11][9-11] = E[d-(d-)^T] = cd^2 * Q[d+d+] + Qwd * I
|
||||
SV->fQw12x12[i + 9][i + 9] = SV->fcdsq * SV->fPPlus12x12[i + 9][i + 9] + FQWD_9DOF_GBY_KALMAN;
|
||||
SV->Qw12x12[i + 9][i + 9] = SV->cdsq * SV->PPlus12x12[i + 9][i + 9] + FQWD_9DOF_GBY_KALMAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -731,7 +727,7 @@ void fRun_9DOF_GBY_KALMAN(SV_9DOF_GBY_KALMAN_t *SV,
|
|||
void f3DOFTiltNED(float fR[][3], float fGp[])
|
||||
{
|
||||
// the NED self-consistency twist occurs at 90 deg pitch
|
||||
|
||||
|
||||
// local variables
|
||||
int16_t i; // counter
|
||||
float fmodGxyz; // modulus of the x, y, z accelerometer readings
|
||||
|
|
@ -788,7 +784,7 @@ void f3DOFTiltNED(float fR[][3], float fGp[])
|
|||
|
||||
// Aerospace NED magnetometer 3DOF flat eCompass function computing rotation matrix fR
|
||||
void f3DOFMagnetometerMatrixNED(float fR[][3], float fBc[])
|
||||
{
|
||||
{
|
||||
// local variables
|
||||
float fmodBxy; // modulus of the x, y magnetometer readings
|
||||
|
||||
|
|
@ -804,7 +800,7 @@ void f3DOFMagnetometerMatrixNED(float fR[][3], float fBc[])
|
|||
// define the fixed entries in the z row and column
|
||||
fR[Z][X] = fR[Z][Y] = fR[X][Z] = fR[Y][Z] = 0.0F;
|
||||
fR[Z][Z] = 1.0F;
|
||||
|
||||
|
||||
// define the remaining entries
|
||||
fR[X][X] = fR[Y][Y] = fBc[X] / fmodBxy;
|
||||
fR[Y][X] = fBc[Y] / fmodBxy;
|
||||
|
|
@ -912,7 +908,7 @@ static void fNEDAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg,
|
|||
// for NED, the compass heading Rho equals the yaw angle Psi
|
||||
*pfRhoDeg = *pfPsiDeg;
|
||||
|
||||
// calculate the tilt angle from vertical Chi (0 <= Chi <= 180 deg)
|
||||
// calculate the tilt angle from vertical Chi (0 <= Chi <= 180 deg)
|
||||
*pfChiDeg = facos_deg(R[Z][Z]);
|
||||
|
||||
return;
|
||||
|
|
@ -1099,7 +1095,7 @@ void fRotationVectorDegFromRotationMatrix(float R[][3], float rvecdeg[])
|
|||
if ((R[Y][Z] - R[Z][Y]) < 0.0F) rvecdeg[X] = -rvecdeg[X];
|
||||
if ((R[Z][X] - R[X][Z]) < 0.0F) rvecdeg[Y] = -rvecdeg[Y];
|
||||
if ((R[X][Y] - R[Y][X]) < 0.0F) rvecdeg[Z] = -rvecdeg[Z];
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1117,12 +1113,12 @@ static void fRotationVectorDegFromQuaternion(Quaternion_t *pq, float rvecdeg[])
|
|||
fetarad = 0.0F;
|
||||
fetadeg = 0.0F;
|
||||
} else {
|
||||
// general case returning 0 < eta < 360 deg
|
||||
fetarad = 2.0F * acosf(pq->q0);
|
||||
// general case returning 0 < eta < 360 deg
|
||||
fetarad = 2.0F * acosf(pq->q0);
|
||||
fetadeg = fetarad * FRADTODEG;
|
||||
}
|
||||
|
||||
// map the rotation angle onto the range -180 deg <= eta < 180 deg
|
||||
// map the rotation angle onto the range -180 deg <= eta < 180 deg
|
||||
if (fetadeg >= 180.0F) {
|
||||
fetadeg -= 360.0F;
|
||||
fetarad = fetadeg * FDEGTORAD;
|
||||
|
|
@ -1133,7 +1129,7 @@ static void fRotationVectorDegFromQuaternion(Quaternion_t *pq, float rvecdeg[])
|
|||
|
||||
// calculate the rotation vector (deg)
|
||||
if (sinhalfeta == 0.0F) {
|
||||
// the rotation angle eta is zero and the axis is irrelevant
|
||||
// the rotation angle eta is zero and the axis is irrelevant
|
||||
rvecdeg[X] = rvecdeg[Y] = rvecdeg[Z] = 0.0F;
|
||||
} else {
|
||||
// general case with non-zero rotation angle
|
||||
|
|
@ -1339,7 +1335,7 @@ static float fatan_deg(float x)
|
|||
|
||||
// reset all flags
|
||||
ixisnegative = ixexceeds1 = ixmapped = 0;
|
||||
|
||||
|
||||
// test for negative argument to allow use of tan(-x)=-tan(x)
|
||||
if (x < 0.0F) {
|
||||
x = -x;
|
||||
|
|
@ -1369,7 +1365,7 @@ static float fatan_deg(float x)
|
|||
if (ixmapped) fangledeg += 30.0F;
|
||||
if (ixexceeds1) fangledeg = 90.0F - fangledeg;
|
||||
if (ixisnegative) fangledeg = -fangledeg;
|
||||
|
||||
|
||||
return (fangledeg);
|
||||
}
|
||||
|
||||
|
|
@ -1386,7 +1382,7 @@ static float fatan2_deg(float y, float x)
|
|||
// otherwise y= 0.0 and return 0 deg (invalid arguments)
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
|
||||
// from here onwards, x is guaranteed to be non-zero
|
||||
// compute atan2 for quadrant 1 (0 to 90 deg) and quadrant 4 (-90 to 0 deg)
|
||||
if (x > 0.0F) return (fatan_deg(y / x));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue