autotest: do not fire the simulated parachute while setting it up

SIM_Parachute deploys as soon as the PWM on SIM_PARA_PIN reads 1250 or
more, and it starts watching that pin the moment the pin number is set.
The parachute tests set the pin in the same set_parameters() call as the
release servo's function, which races the servo output: assigning
SERVO9_FUNCTION=27 leaves the channel at its previous value until
AP_Parachute drives it to CHUTE_SERVO_OFF (1100 by default, below the
trigger), and anything at or above 1250 in that window fires the chute
during setup.

The test then fails in a way which does not look like a setup problem at
all: "BANG!  Parachute deployed" arrives before the test starts waiting
for it, and the real release later in the mission is silent because the
chute has already gone, so the wait times out with "Failed to receive
text: bang".  Seen overnight in Parachute and in GCSFailsafe's parachute
subtest, one run in 26 each.

Configure the vehicle first, wait for the release channel to reach its
off position, and only then let the simulation watch the pin.  Done in
one helper, as four tests set this up the same way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Peter Barker
2026-09-10 18:32:45 +10:00
committed by Peter Barker
co-authored by Claude Opus 5
parent 363235939d
commit 98cb21986d
+33 -29
View File
@@ -1557,14 +1557,7 @@ class AutoTestPlane(vehicle_test_suite.TestSuite):
self.start_subtest("Test Failsafe: Deploy Parachute")
self.load_mission("plane-parachute-mission.txt")
self.set_current_waypoint(1)
self.set_parameters({
"CHUTE_ENABLED": 1,
"CHUTE_TYPE": 10,
"SERVO9_FUNCTION": 27,
"SIM_PARA_ENABLE": 1,
"SIM_PARA_PIN": 9,
"FS_LONG_ACTN": 3,
})
self.setup_simulated_parachute({"FS_LONG_ACTN": 3})
self.change_mode("AUTO")
self.progress("Disconnecting GCS")
self.set_heartbeat_rate(0)
@@ -1979,17 +1972,42 @@ class AutoTestPlane(vehicle_test_suite.TestSuite):
self.disarm_vehicle(force=True)
self.reboot_sitl()
def Parachute(self):
'''Test Parachute'''
self.set_rc(9, 1000)
self.set_parameters({
def setup_simulated_parachute(self, extra_parameters=None):
'''set the vehicle and its simulated parachute up, without firing it
SIM_Parachute deploys as soon as the PWM on SIM_PARA_PIN reads 1250
or more, and it begins watching that pin the moment the pin number
is set. Setting the pin in the same set_parameters() call as the
release servo's function therefore races the servo output: until
AP_Parachute has driven the channel to CHUTE_SERVO_OFF (1100 by
default, below the trigger) it still holds whatever the last test
left there, and anything at or above 1250 fires the chute during
setup. The "BANG!" then arrives before the test starts waiting for
it, and the real release later in the test is silent because the
chute has already gone.
So configure the vehicle first, wait for the release servo to reach
its off position, and only then let the simulation watch the pin.
'''
parameters = {
"CHUTE_ENABLED": 1,
"CHUTE_TYPE": 10,
"SERVO9_FUNCTION": 27,
"SIM_PARA_ENABLE": 1,
}
if extra_parameters is not None:
parameters.update(extra_parameters)
self.set_parameters(parameters)
self.wait_servo_channel_value(9, 1250, comparator=operator.lt, timeout=10)
self.set_parameters({
"SIM_PARA_PIN": 9,
"SIM_PARA_ENABLE": 1,
})
def Parachute(self):
'''Test Parachute'''
self.set_rc(9, 1000)
self.setup_simulated_parachute()
self.load_mission("plane-parachute-mission.txt")
self.set_current_waypoint(1)
self.change_mode('AUTO')
@@ -2002,14 +2020,7 @@ class AutoTestPlane(vehicle_test_suite.TestSuite):
def ParachuteSinkRate(self):
'''Test Parachute (SinkRate triggering)'''
self.set_rc(9, 1000)
self.set_parameters({
"CHUTE_ENABLED": 1,
"CHUTE_TYPE": 10,
"SERVO9_FUNCTION": 27,
"SIM_PARA_ENABLE": 1,
"SIM_PARA_PIN": 9,
"CHUTE_CRT_SINK": 9,
})
self.setup_simulated_parachute({"CHUTE_CRT_SINK": 9})
self.progress("Takeoff")
self.takeoff(alt=300)
@@ -7545,14 +7556,7 @@ class AutoTestPlane(vehicle_test_suite.TestSuite):
def DO_PARACHUTE(self):
'''test triggering parachute via mavlink'''
self.set_parameters({
"CHUTE_ENABLED": 1,
"CHUTE_TYPE": 10,
"SERVO9_FUNCTION": 27,
"SIM_PARA_ENABLE": 1,
"SIM_PARA_PIN": 9,
"FS_LONG_ACTN": 3,
})
self.setup_simulated_parachute({"FS_LONG_ACTN": 3})
for command in self.run_cmd, self.run_cmd_int:
# We release the parachute sitting on the ground, which the
# vehicle permits only while it has never flown: