@ -29,6 +29,9 @@ void NavEKF2_core::ResetVelocity(void)
@@ -29,6 +29,9 @@ void NavEKF2_core::ResetVelocity(void)
zeroRows ( P , 3 , 4 ) ;
zeroCols ( P , 3 , 4 ) ;
gps_elements gps_corrected = gpsDataNew ;
CorrectGPSForAntennaOffset ( gps_corrected ) ;
if ( PV_AidingMode ! = AID_ABSOLUTE ) {
stateStruct . velocity . zero ( ) ;
// set the variances using the measurement noise parameter
@ -36,8 +39,8 @@ void NavEKF2_core::ResetVelocity(void)
@@ -36,8 +39,8 @@ void NavEKF2_core::ResetVelocity(void)
} else {
// reset horizontal velocity states to the GPS velocity if available
if ( imuSampleTime_ms - lastTimeGpsReceived_ms < 250 ) {
stateStruct . velocity . x = gpsDataNew . vel . x ;
stateStruct . velocity . y = gpsDataNew . vel . y ;
stateStruct . velocity . x = gps_corrected . vel . x ;
stateStruct . velocity . y = gps_corrected . vel . y ;
// set the variances using the reported GPS speed accuracy
P [ 4 ] [ 4 ] = P [ 3 ] [ 3 ] = sq ( MAX ( frontend - > _gpsHorizVelNoise , gpsSpdAccuracy ) ) ;
// clear the timeout flags and counters
@ -83,6 +86,9 @@ void NavEKF2_core::ResetPosition(void)
@@ -83,6 +86,9 @@ void NavEKF2_core::ResetPosition(void)
zeroRows ( P , 6 , 7 ) ;
zeroCols ( P , 6 , 7 ) ;
gps_elements gps_corrected = gpsDataNew ;
CorrectGPSForAntennaOffset ( gps_corrected ) ;
if ( PV_AidingMode ! = AID_ABSOLUTE ) {
// reset all position state history to the last known position
stateStruct . position . x = lastKnownPositionNE . x ;
@ -93,10 +99,10 @@ void NavEKF2_core::ResetPosition(void)
@@ -93,10 +99,10 @@ void NavEKF2_core::ResetPosition(void)
// Use GPS data as first preference if fresh data is available
if ( imuSampleTime_ms - lastTimeGpsReceived_ms < 250 ) {
// record the ID of the GPS for the data we are using for the reset
last_gps_idx = gpsDataNew . sensor_idx ;
last_gps_idx = gps_corrected . sensor_idx ;
// write to state vector and compensate for offset between last GPS measurement and the EKF time horizon
stateStruct . position . x = gpsDataNew . pos . x + 0.001f * gpsDataNew . vel . x * ( float ( imuDataDelayed . time_ms ) - float ( gpsDataNew . time_ms ) ) ;
stateStruct . position . y = gpsDataNew . pos . y + 0.001f * gpsDataNew . vel . y * ( float ( imuDataDelayed . time_ms ) - float ( gpsDataNew . time_ms ) ) ;
stateStruct . position . x = gps_corrected . pos . x + 0.001f * gps_corrected . vel . x * ( float ( imuDataDelayed . time_ms ) - float ( gps_corrected . time_ms ) ) ;
stateStruct . position . y = gps_corrected . pos . y + 0.001f * gps_corrected . vel . y * ( float ( imuDataDelayed . time_ms ) - float ( gps_corrected . time_ms ) ) ;
// set the variances using the position measurement noise parameter
P [ 6 ] [ 6 ] = P [ 7 ] [ 7 ] = sq ( MAX ( gpsPosAccuracy , frontend - > _gpsHorizPosNoise ) ) ;
// clear the timeout flags and counters
@ -242,6 +248,33 @@ bool NavEKF2_core::resetHeightDatum(void)
@@ -242,6 +248,33 @@ bool NavEKF2_core::resetHeightDatum(void)
return true ;
}
/*
correct GPS data for position offset of antenna phase centre relative to the IMU
*/
void NavEKF2_core : : CorrectGPSForAntennaOffset ( gps_elements & gps_data )
{
const Vector3f & posOffsetBody = AP : : gps ( ) . get_antenna_offset ( gpsDataDelayed . sensor_idx ) - accelPosOffset ;
if ( posOffsetBody . is_zero ( ) ) {
return ;
}
// Don't fuse velocity data if GPS doesn't support it
if ( fuseVelData ) {
// TODO use a filtered angular rate with a group delay that matches the GPS delay
Vector3f angRate = imuDataDelayed . delAng * ( 1.0f / imuDataDelayed . delAngDT ) ;
Vector3f velOffsetBody = angRate % posOffsetBody ;
Vector3f velOffsetEarth = prevTnb . mul_transpose ( velOffsetBody ) ;
gps_data . vel . x - = velOffsetEarth . x ;
gps_data . vel . y - = velOffsetEarth . y ;
gps_data . vel . z - = velOffsetEarth . z ;
}
Vector3f posOffsetEarth = prevTnb . mul_transpose ( posOffsetBody ) ;
gps_data . pos . x - = posOffsetEarth . x ;
gps_data . pos . y - = posOffsetEarth . y ;
gps_data . hgt + = posOffsetEarth . z ;
}
/********************************************************
* FUSE MEASURED_DATA *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@ -275,25 +308,8 @@ void NavEKF2_core::SelectVelPosFusion()
@@ -275,25 +308,8 @@ void NavEKF2_core::SelectVelPosFusion()
fusePosData = true ;
extNavUsedForPos = false ;
// correct GPS data for position offset of antenna phase centre relative to the IMU
Vector3f posOffsetBody = AP : : gps ( ) . get_antenna_offset ( gpsDataDelayed . sensor_idx ) - accelPosOffset ;
if ( ! posOffsetBody . is_zero ( ) ) {
// Don't fuse velocity data if GPS doesn't support it
if ( fuseVelData ) {
// TODO use a filtered angular rate with a group delay that matches the GPS delay
Vector3f angRate = imuDataDelayed . delAng * ( 1.0f / imuDataDelayed . delAngDT ) ;
Vector3f velOffsetBody = angRate % posOffsetBody ;
Vector3f velOffsetEarth = prevTnb . mul_transpose ( velOffsetBody ) ;
gpsDataDelayed . vel . x - = velOffsetEarth . x ;
gpsDataDelayed . vel . y - = velOffsetEarth . y ;
gpsDataDelayed . vel . z - = velOffsetEarth . z ;
}
Vector3f posOffsetEarth = prevTnb . mul_transpose ( posOffsetBody ) ;
gpsDataDelayed . pos . x - = posOffsetEarth . x ;
gpsDataDelayed . pos . y - = posOffsetEarth . y ;
gpsDataDelayed . hgt + = posOffsetEarth . z ;
}
// correct for antenna position
CorrectGPSForAntennaOffset ( gpsDataDelayed ) ;
// copy corrected GPS data to observation vector
if ( fuseVelData ) {
@ -355,8 +371,8 @@ void NavEKF2_core::SelectVelPosFusion()
@@ -355,8 +371,8 @@ void NavEKF2_core::SelectVelPosFusion()
posResetNE . y = stateStruct . position . y ;
// Set the position states to the position from the new GPS
stateStruct . position . x = gpsDataNew . pos . x ;
stateStruct . position . y = gpsDataNew . pos . y ;
stateStruct . position . x = gpsDataDelayed . pos . x ;
stateStruct . position . y = gpsDataDelayed . pos . y ;
// Calculate the position offset due to the reset
posResetNE . x = stateStruct . position . x - posResetNE . x ;