mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-09 09:28:31 -04:00
AP_NavEKF2: Reduce effect of rounding errors on covariance prediction
This commit is contained in:
parent
4e928bf294
commit
35b08849f7
@ -393,7 +393,7 @@ NavEKF2::NavEKF2(const AP_AHRS *ahrs, AP_Baro &baro, const RangeFinder &rng) :
|
|||||||
gyroBiasNoiseScaler(2.0f), // scale factor applied to imu gyro bias learning before the vehicle is armed
|
gyroBiasNoiseScaler(2.0f), // scale factor applied to imu gyro bias learning before the vehicle is armed
|
||||||
hgtAvg_ms(100), // average number of msec between height measurements
|
hgtAvg_ms(100), // average number of msec between height measurements
|
||||||
betaAvg_ms(100), // average number of msec between synthetic sideslip measurements
|
betaAvg_ms(100), // average number of msec between synthetic sideslip measurements
|
||||||
covTimeStepMax(0.07f), // maximum time (sec) between covariance prediction updates
|
covTimeStepMax(0.1f), // maximum time (sec) between covariance prediction updates
|
||||||
covDelAngMax(0.05f), // maximum delta angle between covariance prediction updates
|
covDelAngMax(0.05f), // maximum delta angle between covariance prediction updates
|
||||||
DCM33FlowMin(0.71f), // If Tbn(3,3) is less than this number, optical flow measurements will not be fused as tilt is too high.
|
DCM33FlowMin(0.71f), // If Tbn(3,3) is less than this number, optical flow measurements will not be fused as tilt is too high.
|
||||||
fScaleFactorPnoise(1e-10f), // Process noise added to focal length scale factor state variance at each time step
|
fScaleFactorPnoise(1e-10f), // Process noise added to focal length scale factor state variance at each time step
|
||||||
@ -401,7 +401,8 @@ NavEKF2::NavEKF2(const AP_AHRS *ahrs, AP_Baro &baro, const RangeFinder &rng) :
|
|||||||
flowIntervalMax_ms(100), // maximum allowable time between flow fusion events
|
flowIntervalMax_ms(100), // maximum allowable time between flow fusion events
|
||||||
gndEffectTimeout_ms(1000), // time in msec that baro ground effect compensation will timeout after initiation
|
gndEffectTimeout_ms(1000), // time in msec that baro ground effect compensation will timeout after initiation
|
||||||
gndEffectBaroScaler(4.0f), // scaler applied to the barometer observation variance when operating in ground effect
|
gndEffectBaroScaler(4.0f), // scaler applied to the barometer observation variance when operating in ground effect
|
||||||
gndGradientSigma(2) // RMS terrain gradient percentage assumed by the terrain height estimation
|
gndGradientSigma(2), // RMS terrain gradient percentage assumed by the terrain height estimation
|
||||||
|
fusionTimeStep_ms(20) // The nominal number of msec between covariance prediction and fusion operations
|
||||||
{
|
{
|
||||||
AP_Param::setup_object_defaults(this, var_info);
|
AP_Param::setup_object_defaults(this, var_info);
|
||||||
}
|
}
|
||||||
|
@ -297,6 +297,7 @@ private:
|
|||||||
const uint16_t gndEffectTimeout_ms; // time in msec that ground effect mode is active after being activated
|
const uint16_t gndEffectTimeout_ms; // time in msec that ground effect mode is active after being activated
|
||||||
const float gndEffectBaroScaler; // scaler applied to the barometer observation variance when ground effect mode is active
|
const float gndEffectBaroScaler; // scaler applied to the barometer observation variance when ground effect mode is active
|
||||||
const uint8_t gndGradientSigma; // RMS terrain gradient percentage assumed by the terrain height estimation
|
const uint8_t gndGradientSigma; // RMS terrain gradient percentage assumed by the terrain height estimation
|
||||||
|
const uint8_t fusionTimeStep_ms; // The nominal time interval between covariance predictions and measurement fusions in msec
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //AP_NavEKF2
|
#endif //AP_NavEKF2
|
||||||
|
@ -118,6 +118,9 @@ void NavEKF2_core::writeOptFlowMeas(uint8_t &rawFlowQuality, Vector2f &rawFlowRa
|
|||||||
flowValidMeaTime_ms = imuSampleTime_ms;
|
flowValidMeaTime_ms = imuSampleTime_ms;
|
||||||
// estimate sample time of the measurement
|
// estimate sample time of the measurement
|
||||||
ofDataNew.time_ms = imuSampleTime_ms - frontend._flowDelay_ms - frontend.flowTimeDeltaAvg_ms/2;
|
ofDataNew.time_ms = imuSampleTime_ms - frontend._flowDelay_ms - frontend.flowTimeDeltaAvg_ms/2;
|
||||||
|
// Assign measurement to nearest fusion interval so that multiple measurements can be fused on the same frame
|
||||||
|
// This allows us to perform the covariance prediction over longer time steps which reduces numerical precision errors
|
||||||
|
ofDataNew.time_ms = roundToNearest(ofDataNew.time_ms, frontend.fusionTimeStep_ms);
|
||||||
// Save data to buffer
|
// Save data to buffer
|
||||||
StoreOF();
|
StoreOF();
|
||||||
// Check for data at the fusion time horizon
|
// Check for data at the fusion time horizon
|
||||||
@ -193,6 +196,10 @@ void NavEKF2_core::readMagData()
|
|||||||
// estimate of time magnetometer measurement was taken, allowing for delays
|
// estimate of time magnetometer measurement was taken, allowing for delays
|
||||||
magMeasTime_ms = imuSampleTime_ms - frontend.magDelay_ms;
|
magMeasTime_ms = imuSampleTime_ms - frontend.magDelay_ms;
|
||||||
|
|
||||||
|
// Assign measurement to nearest fusion interval so that multiple measurements can be fused on the same frame
|
||||||
|
// This allows us to perform the covariance prediction over longer time steps which reduces numerical precision errors
|
||||||
|
magMeasTime_ms = roundToNearest(magMeasTime_ms, frontend.fusionTimeStep_ms);
|
||||||
|
|
||||||
// read compass data and scale to improve numerical conditioning
|
// read compass data and scale to improve numerical conditioning
|
||||||
magDataNew.mag = _ahrs->get_compass()->get_field() * 0.001f;
|
magDataNew.mag = _ahrs->get_compass()->get_field() * 0.001f;
|
||||||
|
|
||||||
@ -358,6 +365,10 @@ void NavEKF2_core::readGpsData()
|
|||||||
// ideally we should be using a timing signal from the GPS receiver to set this time
|
// ideally we should be using a timing signal from the GPS receiver to set this time
|
||||||
gpsDataNew.time_ms = lastTimeGpsReceived_ms - frontend._gpsDelay_ms;
|
gpsDataNew.time_ms = lastTimeGpsReceived_ms - frontend._gpsDelay_ms;
|
||||||
|
|
||||||
|
// Assign measurement to nearest fusion interval so that multiple measurements can be fused on the same frame
|
||||||
|
// This allows us to perform the covariance prediction over longer time steps which reduces numerical precision errors
|
||||||
|
gpsDataNew.time_ms = roundToNearest(gpsDataNew.time_ms, frontend.fusionTimeStep_ms);
|
||||||
|
|
||||||
// read the NED velocity from the GPS
|
// read the NED velocity from the GPS
|
||||||
gpsDataNew.vel = _ahrs->get_gps().velocity();
|
gpsDataNew.vel = _ahrs->get_gps().velocity();
|
||||||
|
|
||||||
@ -495,6 +506,9 @@ void NavEKF2_core::readGpsData()
|
|||||||
gpsDataNew.pos.x = lastKnownPositionNE.x;
|
gpsDataNew.pos.x = lastKnownPositionNE.x;
|
||||||
gpsDataNew.pos.y = lastKnownPositionNE.y;
|
gpsDataNew.pos.y = lastKnownPositionNE.y;
|
||||||
gpsDataNew.time_ms = imuSampleTime_ms-frontend._gpsDelay_ms;
|
gpsDataNew.time_ms = imuSampleTime_ms-frontend._gpsDelay_ms;
|
||||||
|
// Assign measurement to nearest fusion interval so that multiple measurements can be fused on the same frame
|
||||||
|
// This allows us to perform the covariance prediction over longer time steps which reduces numerical precision errors
|
||||||
|
gpsDataNew.time_ms = roundToNearest(gpsDataNew.time_ms, frontend.fusionTimeStep_ms);
|
||||||
// save measurement to buffer to be fused later
|
// save measurement to buffer to be fused later
|
||||||
StoreGPS();
|
StoreGPS();
|
||||||
}
|
}
|
||||||
@ -633,6 +647,10 @@ void NavEKF2_core::readHgtData()
|
|||||||
// estimate of time height measurement was taken, allowing for delays
|
// estimate of time height measurement was taken, allowing for delays
|
||||||
hgtMeasTime_ms = lastHgtReceived_ms - frontend._hgtDelay_ms;
|
hgtMeasTime_ms = lastHgtReceived_ms - frontend._hgtDelay_ms;
|
||||||
|
|
||||||
|
// Assign measurement to nearest fusion interval so that multiple measurements can be fused on the same frame
|
||||||
|
// This allows us to perform the covariance prediction over longer time steps which reduces numerical precision errors
|
||||||
|
hgtMeasTime_ms = roundToNearest(hgtMeasTime_ms, frontend.fusionTimeStep_ms);
|
||||||
|
|
||||||
// save baro measurement to buffer to be fused later
|
// save baro measurement to buffer to be fused later
|
||||||
baroDataNew.time_ms = hgtMeasTime_ms;
|
baroDataNew.time_ms = hgtMeasTime_ms;
|
||||||
StoreBaro();
|
StoreBaro();
|
||||||
@ -696,6 +714,9 @@ void NavEKF2_core::readAirSpdData()
|
|||||||
tasDataNew.tas = aspeed->get_airspeed() * aspeed->get_EAS2TAS();
|
tasDataNew.tas = aspeed->get_airspeed() * aspeed->get_EAS2TAS();
|
||||||
timeTasReceived_ms = aspeed->last_update_ms();
|
timeTasReceived_ms = aspeed->last_update_ms();
|
||||||
tasDataNew.time_ms = timeTasReceived_ms - frontend.tasDelay_ms;
|
tasDataNew.time_ms = timeTasReceived_ms - frontend.tasDelay_ms;
|
||||||
|
// Assign measurement to nearest fusion interval so that multiple measurements can be fused on the same frame
|
||||||
|
// This allows us to perform the covariance prediction over longer time steps which reduces numerical precision errors
|
||||||
|
tasDataNew.time_ms = roundToNearest(tasDataNew.time_ms, frontend.fusionTimeStep_ms);
|
||||||
newDataTas = true;
|
newDataTas = true;
|
||||||
StoreTAS();
|
StoreTAS();
|
||||||
RecallTAS();
|
RecallTAS();
|
||||||
@ -704,4 +725,10 @@ void NavEKF2_core::readAirSpdData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Round to the nearest multiple of a integer
|
||||||
|
uint32_t NavEKF2_core::roundToNearest(uint32_t dividend, uint32_t divisor )
|
||||||
|
{
|
||||||
|
return ((uint32_t)round((float)dividend/float(divisor)))*divisor;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAL_CPU_CLASS
|
#endif // HAL_CPU_CLASS
|
||||||
|
@ -593,6 +593,9 @@ private:
|
|||||||
// using a simple observer
|
// using a simple observer
|
||||||
void calcOutputStatesFast();
|
void calcOutputStatesFast();
|
||||||
|
|
||||||
|
// Round to the nearest multiple of a integer
|
||||||
|
uint32_t roundToNearest(uint32_t dividend, uint32_t divisor );
|
||||||
|
|
||||||
// measurement buffer sizes
|
// measurement buffer sizes
|
||||||
static const uint32_t IMU_BUFFER_LENGTH = 100; // number of IMU samples stored in the buffer. Samples*delta_time must be > max sensor delay
|
static const uint32_t IMU_BUFFER_LENGTH = 100; // number of IMU samples stored in the buffer. Samples*delta_time must be > max sensor delay
|
||||||
static const uint32_t OBS_BUFFER_LENGTH = 5; // number of non-IMU sensor samples stored in the buffer.
|
static const uint32_t OBS_BUFFER_LENGTH = 5; // number of non-IMU sensor samples stored in the buffer.
|
||||||
|
Loading…
Reference in New Issue
Block a user