@@ -11914,7 +11914,7 @@ def GroundEffectCompensation_takeOffExpected(self):
1191411914 (duration, want_lt))
1191511915
1191611916 def TakeoffGroundEffectAlt(self):
11917- '''Test TKOFF_GNDEFF_ALT controls ground effect altitude threshold '''
11917+ '''Test TKOFF_GNDEFF_ALT and TKOFF_GNDEFF_TMO control ground effect '''
1191811918 self.context_push()
1191911919 self.set_parameter("LOG_FILE_DSRMROT", 1)
1192011920
@@ -11949,6 +11949,28 @@ def TakeoffGroundEffectAlt(self):
1194911949 "Smaller threshold should have shorter ground effect (small=%fs >= large=%fs)"
1195011950 % (total_small, total_large))
1195111951
11952+ # Subtest C: TKOFF_GNDEFF_TMO requires both timeout AND altitude
11953+ # With small altitude threshold but timeout set, ground effect should persist longer
11954+ self.start_subtest("TKOFF_GNDEFF_TMO extends ground effect duration")
11955+ self.set_parameters({
11956+ "TKOFF_GNDEFF_ALT": 0.5, # Small threshold - would clear quickly without timeout
11957+ "TKOFF_GNDEFF_TMO": 3, # Require 3s timeout as well
11958+ })
11959+ self.reboot_sitl()
11960+ self.takeoff(5, mode='ALT_HOLD')
11961+ self.delay_sim_time(5)
11962+ self.change_mode('LAND')
11963+ self.wait_disarmed()
11964+ durations_tmo = self.get_takeoffexpected_durations_from_current_onboard_log(ignore_multi=True)
11965+ total_tmo = sum(durations_tmo)
11966+ self.progress("takeoff_expected total with GNDEFF_TMO=3: %fs" % total_tmo)
11967+
11968+ # With timeout, ground effect should persist longer than without (even with small alt threshold)
11969+ if total_tmo <= total_small:
11970+ raise NotAchievedException(
11971+ "TKOFF_GNDEFF_TMO should extend ground effect (tmo=%fs <= no_tmo=%fs)"
11972+ % (total_tmo, total_small))
11973+
1195211974 self.context_pop()
1195311975 self.reboot_sitl()
1195411976
@@ -11957,18 +11979,17 @@ def VibrationRectificationBiasLearning(self):
1195711979 self.context_push()
1195811980 # ACC_ZBIAS_LEARN bitmask: 1=learn+save, 2=use, 4=inhibit EKF when disarmed
1195911981 # Value 3 = learn+save + use
11982+ # Reset INS_ACC_VRFB_Z to 0 to ensure clean start (may have leftover from previous tests)
1196011983 self.set_parameters({
1196111984 "ACC_ZBIAS_LEARN": 3,
1196211985 "SIM_ACC1_BIAS_Z": 0.15,
1196311986 "LOG_FILE_DSRMROT": 1,
11987+ "INS_ACC_VRFB_Z": 0,
1196411988 })
1196511989 self.reboot_sitl()
1196611990
1196711991 # A: Verify learning during hover and save on disarm
1196811992 self.start_subtest("Bias learned during hover and saved on disarm")
11969- vrfb_z = self.get_parameter("INS_ACC_VRFB_Z")
11970- if abs(vrfb_z) > 0.001:
11971- raise NotAchievedException("INS_ACC_VRFB_Z should start at 0, got %f" % vrfb_z)
1197211993 self.wait_ready_to_arm()
1197311994 self.takeoff(10, mode='LOITER')
1197411995 self.delay_sim_time(30)
@@ -12005,6 +12026,42 @@ def VibrationRectificationBiasLearning(self):
1200512026 if abs(vrfb_z) > 0.001:
1200612027 raise NotAchievedException("INS_ACC_VRFB_Z should remain 0, got %f" % vrfb_z)
1200712028
12029+ # D: Verify bit 2 (inhibit EKF ground learning) works with full bitmask
12030+ # Value 7 = learn+save + use + inhibit ground learning
12031+ self.start_subtest("Full bitmask (7) with ground learning inhibit")
12032+ self.set_parameters({
12033+ "INS_ACC_VRFB_Z": 0,
12034+ "ACC_ZBIAS_LEARN": 7,
12035+ "SIM_ACC1_BIAS_Z": 0.15,
12036+ })
12037+ self.reboot_sitl()
12038+ self.wait_ready_to_arm()
12039+ # Fly and verify learning still works (bit 2 only affects disarmed state)
12040+ self.takeoff(10, mode='LOITER')
12041+ self.delay_sim_time(30)
12042+ self.land_and_disarm()
12043+ vrfb_z = self.get_parameter("INS_ACC_VRFB_Z")
12044+ self.progress("INS_ACC_VRFB_Z with full bitmask (7): %f" % vrfb_z)
12045+ if abs(vrfb_z) < 0.01:
12046+ raise NotAchievedException(
12047+ "INS_ACC_VRFB_Z should be non-zero with bitmask 7, got %f" % vrfb_z)
12048+
12049+ # E: Verify frozen correction survives flight (proxy for lane switch survival)
12050+ # After learning, fly again and verify the saved bias is still applied
12051+ self.start_subtest("Frozen correction persists across flights")
12052+ saved_vrfb_z = vrfb_z
12053+ self.reboot_sitl()
12054+ self.wait_ready_to_arm()
12055+ self.takeoff(10, mode='LOITER')
12056+ self.delay_sim_time(10)
12057+ self.land_and_disarm()
12058+ vrfb_z = self.get_parameter("INS_ACC_VRFB_Z")
12059+ # The saved bias should persist (may drift slightly due to continued learning)
12060+ if abs(vrfb_z) < 0.01:
12061+ raise NotAchievedException(
12062+ "INS_ACC_VRFB_Z should persist across flights, got %f" % vrfb_z)
12063+ self.progress("INS_ACC_VRFB_Z persisted: was %f, now %f" % (saved_vrfb_z, vrfb_z))
12064+
1200812065 self.context_pop()
1200912066 self.reboot_sitl()
1201012067
0 commit comments