forked from Archive/PX4-Autopilot
Merge remote-tracking branch 'upstream/mtecs_estimator' into navigator_rewrite_estimator
This commit is contained in:
commit
d4f9914d19
|
@ -1,5 +1,6 @@
|
||||||
#include "estimator_23states.h"
|
#include "estimator_23states.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define EKF_COVARIANCE_DIVERGED 1.0e8f
|
#define EKF_COVARIANCE_DIVERGED 1.0e8f
|
||||||
|
@ -33,6 +34,8 @@ AttPosEKF::AttPosEKF()
|
||||||
magDeclination = 0.0f;
|
magDeclination = 0.0f;
|
||||||
dAngIMU.zero();
|
dAngIMU.zero();
|
||||||
dVelIMU.zero();
|
dVelIMU.zero();
|
||||||
|
ekfDiverged = false;
|
||||||
|
delAngTotal.zero();
|
||||||
|
|
||||||
memset(&last_ekf_error, 0, sizeof(last_ekf_error));
|
memset(&last_ekf_error, 0, sizeof(last_ekf_error));
|
||||||
ZeroVariables();
|
ZeroVariables();
|
||||||
|
@ -70,6 +73,10 @@ void AttPosEKF::UpdateStrapdownEquationsNED()
|
||||||
dVelIMU.y = dVelIMU.y;
|
dVelIMU.y = dVelIMU.y;
|
||||||
dVelIMU.z = dVelIMU.z - states[13];
|
dVelIMU.z = dVelIMU.z - states[13];
|
||||||
|
|
||||||
|
delAngTotal.x += correctedDelAng.x;
|
||||||
|
delAngTotal.y += correctedDelAng.y;
|
||||||
|
delAngTotal.z += correctedDelAng.z;
|
||||||
|
|
||||||
// Save current measurements
|
// Save current measurements
|
||||||
Vector3f prevDelAng = correctedDelAng;
|
Vector3f prevDelAng = correctedDelAng;
|
||||||
|
|
||||||
|
@ -201,7 +208,8 @@ void AttPosEKF::CovariancePrediction(float dt)
|
||||||
float nextP[n_states][n_states];
|
float nextP[n_states][n_states];
|
||||||
|
|
||||||
// calculate covariance prediction process noise
|
// calculate covariance prediction process noise
|
||||||
for (uint8_t i= 0; i<=9; i++) processNoise[i] = 1.0e-9f;
|
for (uint8_t i= 0; i<4; i++) processNoise[i] = 1.0e-9f;
|
||||||
|
for (uint8_t i= 4; i<10; i++) processNoise[i] = 1.0e-9f;
|
||||||
for (uint8_t i=10; i<=12; i++) processNoise[i] = dt * dAngBiasSigma;
|
for (uint8_t i=10; i<=12; i++) processNoise[i] = dt * dAngBiasSigma;
|
||||||
// scale gyro bias noise when on ground to allow for faster bias estimation
|
// scale gyro bias noise when on ground to allow for faster bias estimation
|
||||||
for (uint8_t i=10; i<=12; i++) processNoise[i] = dt * dAngBiasSigma;
|
for (uint8_t i=10; i<=12; i++) processNoise[i] = dt * dAngBiasSigma;
|
||||||
|
@ -2081,7 +2089,7 @@ void AttPosEKF::ForceSymmetry()
|
||||||
|
|
||||||
if ((fabsf(P[i][j]) > EKF_COVARIANCE_DIVERGED) ||
|
if ((fabsf(P[i][j]) > EKF_COVARIANCE_DIVERGED) ||
|
||||||
(fabsf(P[j][i]) > EKF_COVARIANCE_DIVERGED)) {
|
(fabsf(P[j][i]) > EKF_COVARIANCE_DIVERGED)) {
|
||||||
// XXX divergence report error
|
last_ekf_error.covariancesExcessive = true;
|
||||||
InitializeDynamic(velNED, magDeclination);
|
InitializeDynamic(velNED, magDeclination);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2117,6 +2125,24 @@ bool AttPosEKF::GyroOffsetsDiverged()
|
||||||
return diverged;
|
return diverged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AttPosEKF::VelNEDDiverged()
|
||||||
|
{
|
||||||
|
Vector3f current_vel;
|
||||||
|
current_vel.x = states[4];
|
||||||
|
current_vel.y = states[5];
|
||||||
|
current_vel.z = states[6];
|
||||||
|
|
||||||
|
Vector3f gps_vel;
|
||||||
|
gps_vel.x = velNED[0];
|
||||||
|
gps_vel.y = velNED[1];
|
||||||
|
gps_vel.z = velNED[2];
|
||||||
|
|
||||||
|
Vector3f delta = current_vel - gps_vel;
|
||||||
|
float delta_len = delta.length();
|
||||||
|
|
||||||
|
return (delta_len > 20.0f);
|
||||||
|
}
|
||||||
|
|
||||||
bool AttPosEKF::FilterHealthy()
|
bool AttPosEKF::FilterHealthy()
|
||||||
{
|
{
|
||||||
if (!statesInitialised) {
|
if (!statesInitialised) {
|
||||||
|
@ -2188,6 +2214,7 @@ void AttPosEKF::FillErrorReport(struct ekf_status_report *err)
|
||||||
{
|
{
|
||||||
err->states[i] = states[i];
|
err->states[i] = states[i];
|
||||||
}
|
}
|
||||||
|
err->n_states = n_states;
|
||||||
|
|
||||||
err->velHealth = current_ekf_state.velHealth;
|
err->velHealth = current_ekf_state.velHealth;
|
||||||
err->posHealth = current_ekf_state.posHealth;
|
err->posHealth = current_ekf_state.posHealth;
|
||||||
|
@ -2290,13 +2317,19 @@ int AttPosEKF::CheckAndBound()
|
||||||
// Store the old filter state
|
// Store the old filter state
|
||||||
bool currStaticMode = staticMode;
|
bool currStaticMode = staticMode;
|
||||||
|
|
||||||
|
if (ekfDiverged) {
|
||||||
|
ekfDiverged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
// Reset the filter if the states went NaN
|
// Reset the filter if the states went NaN
|
||||||
if (StatesNaN(&last_ekf_error)) {
|
if (StatesNaN(&last_ekf_error)) {
|
||||||
ekf_debug("re-initializing dynamic");
|
ekf_debug("re-initializing dynamic");
|
||||||
|
|
||||||
InitializeDynamic(velNED, magDeclination);
|
InitializeDynamic(velNED, magDeclination);
|
||||||
|
|
||||||
return 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the filter if the IMU data is too old
|
// Reset the filter if the IMU data is too old
|
||||||
|
@ -2308,7 +2341,7 @@ int AttPosEKF::CheckAndBound()
|
||||||
ResetStoredStates();
|
ResetStoredStates();
|
||||||
|
|
||||||
// that's all we can do here, return
|
// that's all we can do here, return
|
||||||
return 2;
|
ret = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we're on ground - this also sets static mode.
|
// Check if we're on ground - this also sets static mode.
|
||||||
|
@ -2322,7 +2355,7 @@ int AttPosEKF::CheckAndBound()
|
||||||
ResetHeight();
|
ResetHeight();
|
||||||
ResetStoredStates();
|
ResetStoredStates();
|
||||||
|
|
||||||
return 3;
|
ret = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the filter if gyro offsets are excessive
|
// Reset the filter if gyro offsets are excessive
|
||||||
|
@ -2331,10 +2364,29 @@ int AttPosEKF::CheckAndBound()
|
||||||
InitializeDynamic(velNED, magDeclination);
|
InitializeDynamic(velNED, magDeclination);
|
||||||
|
|
||||||
// that's all we can do here, return
|
// that's all we can do here, return
|
||||||
return 4;
|
ret = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
// Reset the filter if it diverges too far from GPS
|
||||||
|
if (VelNEDDiverged()) {
|
||||||
|
FillErrorReport(&last_ekf_error);
|
||||||
|
InitializeDynamic(velNED, magDeclination);
|
||||||
|
|
||||||
|
// that's all we can do here, return
|
||||||
|
ret = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_ekf_state.covariancesExcessive) {
|
||||||
|
FillErrorReport(&last_ekf_error);
|
||||||
|
current_ekf_state.covariancesExcessive = false;
|
||||||
|
ret = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
ekfDiverged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttPosEKF::AttitudeInit(float ax, float ay, float az, float mx, float my, float mz, float declination, float *initQuat)
|
void AttPosEKF::AttitudeInit(float ax, float ay, float az, float mx, float my, float mz, float declination, float *initQuat)
|
||||||
|
@ -2386,6 +2438,8 @@ void AttPosEKF::AttitudeInit(float ax, float ay, float az, float mx, float my, f
|
||||||
void AttPosEKF::InitializeDynamic(float (&initvelNED)[3], float declination)
|
void AttPosEKF::InitializeDynamic(float (&initvelNED)[3], float declination)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
ZeroVariables();
|
||||||
|
|
||||||
// Fill variables with valid data
|
// Fill variables with valid data
|
||||||
velNED[0] = initvelNED[0];
|
velNED[0] = initvelNED[0];
|
||||||
velNED[1] = initvelNED[1];
|
velNED[1] = initvelNED[1];
|
||||||
|
@ -2469,6 +2523,7 @@ void AttPosEKF::ZeroVariables()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Initialize on-init initialized variables
|
// Initialize on-init initialized variables
|
||||||
|
|
||||||
storeIndex = 0;
|
storeIndex = 0;
|
||||||
|
|
||||||
// Do the data structure init
|
// Do the data structure init
|
||||||
|
@ -2486,6 +2541,7 @@ void AttPosEKF::ZeroVariables()
|
||||||
correctedDelAng.zero();
|
correctedDelAng.zero();
|
||||||
summedDelAng.zero();
|
summedDelAng.zero();
|
||||||
summedDelVel.zero();
|
summedDelVel.zero();
|
||||||
|
lastGyroOffset.zero();
|
||||||
|
|
||||||
for (unsigned i = 0; i < data_buffer_size; i++) {
|
for (unsigned i = 0; i < data_buffer_size; i++) {
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#include "estimator_utilities.h"
|
#include "estimator_utilities.h"
|
||||||
|
|
||||||
|
const unsigned int n_states = 23;
|
||||||
|
const unsigned int data_buffer_size = 50;
|
||||||
|
|
||||||
class AttPosEKF {
|
class AttPosEKF {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -121,6 +124,7 @@ public:
|
||||||
Vector3f earthRateNED; // earths angular rate vector in NED (rad/s)
|
Vector3f earthRateNED; // earths angular rate vector in NED (rad/s)
|
||||||
Vector3f angRate; // angular rate vector in XYZ body axes measured by the IMU (rad/s)
|
Vector3f angRate; // angular rate vector in XYZ body axes measured by the IMU (rad/s)
|
||||||
Vector3f lastGyroOffset; // Last gyro offset
|
Vector3f lastGyroOffset; // Last gyro offset
|
||||||
|
Vector3f delAngTotal;
|
||||||
|
|
||||||
Mat3f Tbn; // transformation matrix from body to NED coordinates
|
Mat3f Tbn; // transformation matrix from body to NED coordinates
|
||||||
Mat3f Tnb; // transformation amtrix from NED to body coordinates
|
Mat3f Tnb; // transformation amtrix from NED to body coordinates
|
||||||
|
@ -180,6 +184,8 @@ public:
|
||||||
bool useCompass; ///< boolean true if magnetometer data is being used
|
bool useCompass; ///< boolean true if magnetometer data is being used
|
||||||
bool useRangeFinder; ///< true when rangefinder is being used
|
bool useRangeFinder; ///< true when rangefinder is being used
|
||||||
|
|
||||||
|
bool ekfDiverged;
|
||||||
|
|
||||||
struct ekf_status_report current_ekf_state;
|
struct ekf_status_report current_ekf_state;
|
||||||
struct ekf_status_report last_ekf_error;
|
struct ekf_status_report last_ekf_error;
|
||||||
|
|
||||||
|
@ -281,6 +287,8 @@ bool FilterHealthy();
|
||||||
|
|
||||||
bool GyroOffsetsDiverged();
|
bool GyroOffsetsDiverged();
|
||||||
|
|
||||||
|
bool VelNEDDiverged();
|
||||||
|
|
||||||
void ResetHeight(void);
|
void ResetHeight(void);
|
||||||
|
|
||||||
void AttitudeInit(float ax, float ay, float az, float mx, float my, float mz, float declination, float *initQuat);
|
void AttitudeInit(float ax, float ay, float az, float mx, float my, float mz, float declination, float *initQuat);
|
||||||
|
|
|
@ -46,9 +46,6 @@ Vector3f operator*(Vector3f vecIn1, float sclIn1);
|
||||||
|
|
||||||
void swap_var(float &d1, float &d2);
|
void swap_var(float &d1, float &d2);
|
||||||
|
|
||||||
const unsigned int n_states = 23;
|
|
||||||
const unsigned int data_buffer_size = 50;
|
|
||||||
|
|
||||||
enum GPS_FIX {
|
enum GPS_FIX {
|
||||||
GPS_FIX_NOFIX = 0,
|
GPS_FIX_NOFIX = 0,
|
||||||
GPS_FIX_2D = 2,
|
GPS_FIX_2D = 2,
|
||||||
|
@ -65,7 +62,8 @@ struct ekf_status_report {
|
||||||
uint32_t velFailTime;
|
uint32_t velFailTime;
|
||||||
uint32_t posFailTime;
|
uint32_t posFailTime;
|
||||||
uint32_t hgtFailTime;
|
uint32_t hgtFailTime;
|
||||||
float states[n_states];
|
float states[32];
|
||||||
|
unsigned n_states;
|
||||||
bool angNaN;
|
bool angNaN;
|
||||||
bool summedDelVelNaN;
|
bool summedDelVelNaN;
|
||||||
bool KHNaN;
|
bool KHNaN;
|
||||||
|
@ -74,6 +72,8 @@ struct ekf_status_report {
|
||||||
bool covarianceNaN;
|
bool covarianceNaN;
|
||||||
bool kalmanGainsNaN;
|
bool kalmanGainsNaN;
|
||||||
bool statesNaN;
|
bool statesNaN;
|
||||||
|
bool gyroOffsetsExcessive;
|
||||||
|
bool covariancesExcessive;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ekf_debug(const char *fmt, ...);
|
void ekf_debug(const char *fmt, ...);
|
Loading…
Reference in New Issue