AP_NavEKF2: continuously update gpsGoodToAlign

use it to determine how to handle a height datum reset
This commit is contained in:
Andrew Tridgell 2019-07-02 08:49:48 +10:00
parent b9a5794671
commit 9372073f63
6 changed files with 42 additions and 26 deletions

View File

@ -540,13 +540,9 @@ void NavEKF2_core::readGpsData()
useGpsVertVel = false;
}
// Monitor quality of the GPS velocity data before and after alignment using separate checks
if (PV_AidingMode != AID_ABSOLUTE) {
// Pre-alignment checks
gpsGoodToAlign = calcGpsGoodToAlign();
} else {
gpsGoodToAlign = false;
}
// Monitor quality of the GPS velocity data both before and after alignment. This updates
// GpsGoodToAlign class variable
calcGpsGoodToAlign();
// Post-alignment checks
calcGpsGoodForFlight();

View File

@ -595,7 +595,7 @@ void NavEKF2_core::send_status_report(mavlink_channel_t chan)
// report the reason for why the backend is refusing to initialise
const char *NavEKF2_core::prearm_failure_reason(void) const
{
if (imuSampleTime_ms - lastGpsVelFail_ms > 10000) {
if (gpsGoodToAlign) {
// we are not failing
return nullptr;
}

View File

@ -214,21 +214,22 @@ bool NavEKF2_core::resetHeightDatum(void)
// reset the height state
stateStruct.position.z = 0.0f;
// adjust the height of the EKF origin so that the origin plus baro height before and after the reset is the same
if (validOrigin) {
const AP_GPS &gps = AP::gps();
if (gps.status() >= AP_GPS::GPS_OK_FIX_3D) {
if (validOrigin && !inFlight) {
if (!gpsGoodToAlign) {
// if we don't have GPS lock then we shouldn't be doing a
// resetHeightDatum, but if we do then the best option is
// to maintain the old error
ekfGpsRefHgt += (int32_t)(100.0f * oldHgt);
} else {
// if we have a good GPS lock then reset to the GPS
// altitude. This ensures the reported AMSL alt from
// getLLH() is equal to GPS altitude, while also ensuring
// that the relative alt is zero
ekfGpsRefHgt = gps.location().alt*0.01;
} else {
// if we don't have GPS lock then we shouldn't be doing a
// resetHeightDatum, but if we do then the best option is
// to maintain the old error
ekfGpsRefHgt += oldHgt;
ekfGpsRefHgt = AP::gps().location().alt*0.01;
}
}
// adjust the terrain state
terrainState += oldHgt;
return true;

View File

@ -18,20 +18,33 @@ extern const AP_HAL::HAL& hal;
We also record the failure reason so that prearm_failure_reason()
can give a good report to the user on why arming is failing
This sets gpsGoodToAlign class variable
*/
bool NavEKF2_core::calcGpsGoodToAlign(void)
void NavEKF2_core::calcGpsGoodToAlign(void)
{
const AP_GPS &gps = AP::gps();
if (inFlight && assume_zero_sideslip() && !use_compass()) {
// this is a special case where a plane has launched without magnetometer
// is now in the air and needs to align yaw to the GPS and start navigating as soon as possible
return true;
gpsGoodToAlign = true;
return;
}
// User defined multiplier to be applied to check thresholds
float checkScaler = 0.01f*(float)frontend->_gpsCheckScaler;
if (gpsGoodToAlign) {
/*
if we have already passed GPS alignment checks then raise
the check threshold so that we have some hysterisis and
don't continuously change from able to arm to not able to
arm
*/
checkScaler *= 1.3f;
}
// If we have good magnetometer consistency and bad innovations for longer than 5 seconds then we reset heading and field states
// This enables us to handle large changes to the external magnetic field environment that occur before arming
if ((magTestRatio.x <= 1.0f && magTestRatio.y <= 1.0f && yawTestRatio <= 1.0f) || !consistentMagData) {
@ -223,16 +236,20 @@ bool NavEKF2_core::calcGpsGoodToAlign(void)
lastGpsVelFail_ms = imuSampleTime_ms;
}
// record time of fail
// record time of fail or pass
if (gpsSpdAccFail || numSatsFail || hdopFail || hAccFail || vAccFail || yawFail || gpsDriftFail || gpsVertVelFail || gpsHorizVelFail) {
lastGpsVelFail_ms = imuSampleTime_ms;
} else {
lastGpsVelPass_ms = imuSampleTime_ms;
}
// continuous period without fail required to return a healthy status
if (imuSampleTime_ms - lastGpsVelFail_ms > 10000) {
return true;
// continuous period of 10s without fail required to set healthy
// continuous period of 5s without pass required to set unhealthy
if (!gpsGoodToAlign && imuSampleTime_ms - lastGpsVelFail_ms > 10000) {
gpsGoodToAlign = true;
} else if (gpsGoodToAlign && imuSampleTime_ms - lastGpsVelPass_ms > 5000) {
gpsGoodToAlign = false;
}
return false;
}
// update inflight calculaton that determines if GPS data is good enough for reliable navigation

View File

@ -134,6 +134,7 @@ void NavEKF2_core::InitialiseVariables()
gndHgtValidTime_ms = 0;
ekfStartTime_ms = imuSampleTime_ms;
lastGpsVelFail_ms = 0;
lastGpsVelPass_ms = 0;
lastGpsAidBadTime_ms = 0;
timeTasReceived_ms = 0;
lastPreAlignGpsCheckTime_ms = imuSampleTime_ms;

View File

@ -718,8 +718,8 @@ private:
// determine if a touchdown is expected so that we can compensate for expected barometer errors due to ground effect
bool getTouchdownExpected();
// Assess GPS data quality and return true if good enough to align the EKF
bool calcGpsGoodToAlign(void);
// Assess GPS data quality and set gpsGoodToAlign if good enough to align the EKF
void calcGpsGoodToAlign(void);
// return true and set the class variable true if the delta angle bias has been learned
bool checkGyroCalStatus(void);
@ -876,6 +876,7 @@ private:
float gpsPosAccuracy; // estimated position accuracy in m returned by the GPS receiver
float gpsHgtAccuracy; // estimated height accuracy in m returned by the GPS receiver
uint32_t lastGpsVelFail_ms; // time of last GPS vertical velocity consistency check fail
uint32_t lastGpsVelPass_ms; // time of last GPS vertical velocity consistency check pass
uint32_t lastGpsAidBadTime_ms; // time in msec gps aiding was last detected to be bad
float posDownAtTakeoff; // flight vehicle vertical position sampled at transition from on-ground to in-air and used as a reference (m)
bool useGpsVertVel; // true if GPS vertical velocity should be used