AP_NavEKF3: Add missing vertical position derivative calculation

This commit is contained in:
Paul Riseborough 2019-10-13 09:26:47 +11:00 committed by Randy Mackay
parent e2d3afaaa7
commit 5b1d9ed868
6 changed files with 39 additions and 7 deletions

View File

@ -588,6 +588,14 @@ const AP_Param::GroupInfo NavEKF3::var_info[] = {
// @RebootRequired: True
AP_GROUPINFO("FLOW_USE", 54, NavEKF3, _flowUse, FLOW_USE_DEFAULT),
// @Param: HRT_FILT
// @DisplayName: Height rate filter crossover frequency
// @Description: Specifies the crossover frequency of the complementary filter used to calculate the output predictor height rate derivative.
// @Range: 0.1 100.0
// @Units: Hz
// @RebootRequired: False
AP_GROUPINFO("HRT_FILT", 55, NavEKF3, _hrt_filt_freq, 2.0f),
AP_GROUPEND
};

View File

@ -447,6 +447,7 @@ private:
AP_Float _visOdmVelErrMin; // Observation 1-STD velocity error assumed for visual odometry sensor at highest reported quality (m/s)
AP_Float _wencOdmVelErr; // Observation 1-STD velocity error assumed for wheel odometry sensor (m/s)
AP_Int8 _flowUse; // Controls if the optical flow data is fused into the main navigation estimator and/or the terrain estimator.
AP_Float _hrt_filt_freq; // frequency of output observer height rate complementary filter in Hz
// Possible values for _flowUse
#define FLOW_USE_NONE 0

View File

@ -224,7 +224,7 @@ float NavEKF3_core::getPosDownDerivative(void) const
{
// return the value calculated from a complementary filter applied to the EKF height and vertical acceleration
// correct for the IMU offset (EKF calculations are at the IMU)
return posDownDerivative + velOffsetNED.z;
return vertCompFiltState.vel + velOffsetNED.z;
}
// This returns the specific forces in the NED frame

View File

@ -157,6 +157,7 @@ void NavEKF3_core::ResetHeight(void)
for (uint8_t i=0; i<imu_buffer_length; i++) {
storedOutput[i].position.z = stateStruct.position.z;
}
vertCompFiltState.pos = stateStruct.position.z;
// Calculate the position jump due to the reset
posResetD = stateStruct.position.z - posResetD;
@ -187,6 +188,7 @@ void NavEKF3_core::ResetHeight(void)
}
outputDataNew.velocity.z = stateStruct.velocity.z;
outputDataDelayed.velocity.z = stateStruct.velocity.z;
vertCompFiltState.vel = outputDataNew.velocity.z;
// reset the corresponding covariances
zeroRows(P,6,6);
@ -339,6 +341,7 @@ void NavEKF3_core::SelectVelPosFusion()
// Add the offset to the output observer states
outputDataNew.position.z += posResetD;
vertCompFiltState.pos = outputDataNew.position.z;
outputDataDelayed.position.z += posResetD;
for (uint8_t i=0; i<imu_buffer_length; i++) {
storedOutput[i].position.z += posResetD;

View File

@ -281,8 +281,7 @@ void NavEKF3_core::InitialiseVariables()
gpsVertVelFilt = 0.0f;
gpsHorizVelFilt = 0.0f;
memset(&statesArray, 0, sizeof(statesArray));
posDownDerivative = 0.0f;
posDown = 0.0f;
memset(&vertCompFiltState, 0, sizeof(vertCompFiltState));
posVelFusionDelayed = false;
optFlowFusionDelayed = false;
flowFusionActive = false;
@ -760,6 +759,24 @@ void NavEKF3_core::calcOutputStates()
// sum delta velocities to get velocity
outputDataNew.velocity += delVelNav;
// Implement third order complementary filter for height and height rate
// Reference Paper :
// Optimizing the Gains of the Baro-Inertial Vertical Channel
// Widnall W.S, Sinha P.K,
// AIAA Journal of Guidance and Control, 78-1307R
// Perform filter calculation using backwards Euler integration
// Coefficients selected to place all three filter poles at omega
const float CompFiltOmega = M_2PI * constrain_float(frontend->_hrt_filt_freq, 0.1f, 100.0f);
float omega2 = CompFiltOmega * CompFiltOmega;
float pos_err = outputDataNew.position.z - vertCompFiltState.pos;
float integ1_input = pos_err * omega2 * CompFiltOmega * imuDataNew.delVelDT;
vertCompFiltState.acc += integ1_input;
float integ2_input = delVelNav.z + (vertCompFiltState.acc + pos_err * omega2 * 3.0f) * imuDataNew.delVelDT;
vertCompFiltState.vel += integ2_input;
float integ3_input = (vertCompFiltState.vel + pos_err * CompFiltOmega * 3.0f) * imuDataNew.delVelDT;
vertCompFiltState.pos += integ3_input;
// apply a trapezoidal integration to velocities to calculate position
outputDataNew.position += (outputDataNew.velocity + lastVelocity) * (imuDataNew.delVelDT*0.5f);
@ -1409,8 +1426,8 @@ void NavEKF3_core::StoreOutputReset()
}
outputDataDelayed = outputDataNew;
// reset the states for the complementary filter used to provide a vertical position derivative output
posDown = stateStruct.position.z;
posDownDerivative = stateStruct.velocity.z;
vertCompFiltState.pos = stateStruct.position.z;
vertCompFiltState.vel = stateStruct.velocity.z;
}
// Reset the stored output quaternion history to current EKF state

View File

@ -1022,8 +1022,11 @@ private:
resetDataSource velResetSource; // preferred source of data for a velocity reset
// variables used to calculate a vertical velocity that is kinematically consistent with the vertical position
float posDownDerivative; // Rate of change of vertical position (dPosD/dt) in m/s. This is the first time derivative of PosD.
float posDown; // Down position state used in calculation of posDownRate
struct {
float pos;
float vel;
float acc;
} vertCompFiltState;
// variables used by the pre-initialisation GPS checks
struct Location gpsloc_prev; // LLH location of previous GPS measurement