mirror of https://github.com/ArduPilot/ardupilot
AP_NavEKF3: Add missing vertical position derivative calculation
This commit is contained in:
parent
e2d3afaaa7
commit
5b1d9ed868
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue