Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix infinite climb bug when using EK3_OGN_HGT_MASK #26917

Merged
merged 3 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Tools/autotest/arducopter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11377,6 +11377,43 @@ def GuidedForceArm(self):
self.disarm_vehicle(force=True)
self.reboot_sitl()

def EK3_OGN_HGT_MASK_climbing(self):
'''check combination of height bits doesn't cause climb'''
self.context_push()
self.set_parameters({
'EK3_OGN_HGT_MASK': 5,
})
self.reboot_sitl()

expected_alt = 10

self.change_mode('GUIDED')
self.wait_ready_to_arm()
current_alt = self.get_altitude()

expected_alt_abs = current_alt + expected_alt

self.takeoff(expected_alt, mode='GUIDED')
self.delay_sim_time(5)

def check_altitude(mav, m):
m_type = m.get_type()
epsilon = 10 # in metres
if m_type == 'GPS_RAW_INT':
got_gps_alt = m.alt * 0.001
if abs(expected_alt_abs - got_gps_alt) > epsilon:
raise NotAchievedException(f"Bad GPS altitude (got={got_gps_alt} want={expected_alt_abs})")
elif m_type == 'GLOBAL_POSITION_INT':
if abs(expected_alt - m.relative_alt * 0.001) > epsilon:
raise NotAchievedException("Bad canonical altitude")

self.install_message_hook_context(check_altitude)

self.delay_sim_time(1500)

self.context_pop()
self.reboot_sitl(force=True)

def tests2b(self): # this block currently around 9.5mins here
'''return list of all tests'''
ret = ([
Expand Down Expand Up @@ -11461,6 +11498,7 @@ def tests2b(self): # this block currently around 9.5mins here
self.GuidedModeThrust,
self.CompassMot,
self.AutoRTL,
self.EK3_OGN_HGT_MASK_climbing,
self.EK3_OGN_HGT_MASK,
self.FarOrigin,
self.GuidedForceArm,
Expand Down
2 changes: 2 additions & 0 deletions libraries/AP_NavEKF3/AP_NavEKF3_Measurements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,8 +685,10 @@ void NavEKF3_core::readGpsData()
gpsDataNew.lat = gpsloc.lat;
gpsDataNew.lng = gpsloc.lng;
if ((frontend->_originHgtMode & (1<<2)) == 0) {
// the height adjustment to match GPS is being achieved by adjusting the origin height
gpsDataNew.hgt = (ftype)((double)0.01 * (double)gpsloc.alt - ekfGpsRefHgt);
} else {
// the height adjustment to match GPS is being achieved by adjusting the measurements
gpsDataNew.hgt = 0.01 * (gpsloc.alt - EKF_origin.alt);
}
storedGPS.push(gpsDataNew);
Expand Down
12 changes: 1 addition & 11 deletions libraries/AP_NavEKF3/AP_NavEKF3_Outputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,17 +260,7 @@ bool NavEKF3_core::getPosNE(Vector2f &posNE) const
// Return true if the estimate is valid
bool NavEKF3_core::getPosD_local(float &posD) const
{
// The EKF always has a height estimate regardless of mode of operation
// Correct for the IMU offset (EKF calculations are at the IMU)
// Also correct for changes to the origin height
if ((frontend->_originHgtMode & (1<<2)) == 0) {
// Any sensor height drift corrections relative to the WGS-84 reference are applied to the origin.
posD = outputDataNew.position.z + posOffsetNED.z;
} else {
// The origin height is static and corrections are applied to the local vertical position
// so that height returned by getLLH() = height returned by getOriginLLH - posD
posD = outputDataNew.position.z + posOffsetNED.z + 0.01f * (float)EKF_origin.alt - (float)ekfGpsRefHgt;
}
posD = outputDataNew.position.z + posOffsetNED.z;

// Return the current height solution status
return filterStatus.flags.vert_pos;
Expand Down
9 changes: 9 additions & 0 deletions libraries/AP_NavEKF3/AP_NavEKF3_PosVelFusion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,11 @@ void NavEKF3_core::selectHeightForFusion()
hgtMea = MAX(rangeDataDelayed.rng * prevTnb.c.z, rngOnGnd);
// correct for terrain position relative to datum
hgtMea -= terrainState;
// correct sensor so that local position height adjusts to match GPS
if (frontend->_originHgtMode & (1 << 1) && frontend->_originHgtMode & (1 << 2)) {
// offset has to be applied to the measurement, not the NED origin
hgtMea += (float)(ekfGpsRefHgt - 0.01 * (double)EKF_origin.alt);
}
velPosObs[5] = -hgtMea;
// enable fusion
fuseHgtData = true;
Expand All @@ -1304,6 +1309,10 @@ void NavEKF3_core::selectHeightForFusion()
} else if (baroDataToFuse && (activeHgtSource == AP_NavEKF_Source::SourceZ::BARO)) {
// using Baro data
hgtMea = baroDataDelayed.hgt - baroHgtOffset;
// correct sensor so that local position height adjusts to match GPS
if (frontend->_originHgtMode & (1 << 0) && frontend->_originHgtMode & (1 << 2)) {
hgtMea += (float)(ekfGpsRefHgt - 0.01 * (double)EKF_origin.alt);
}
// enable fusion
fuseHgtData = true;
// set the observation noise
Expand Down
Loading