mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-05 07:28:29 -04:00
autotest: Improved motor failure test
This is based on https://github.com/ArduPilot/ardupilot/pull/6028 by GuilhermeGSousa
This commit is contained in:
parent
0078a68fbb
commit
dab3b93dc3
@ -992,6 +992,117 @@ class AutoTestCopter(AutoTest):
|
|||||||
|
|
||||||
self.progress("AVC mission completed: passed!")
|
self.progress("AVC mission completed: passed!")
|
||||||
|
|
||||||
|
def fly_motor_fail(self, fail_servo=0, fail_mul=0.0, holdtime=30):
|
||||||
|
"""Test flight with reduced motor efficiency"""
|
||||||
|
|
||||||
|
# we only expect an octocopter to survive ATM:
|
||||||
|
servo_counts = {
|
||||||
|
# 2: 6, # hexa
|
||||||
|
3: 8, # octa
|
||||||
|
# 5: 6, # Y6
|
||||||
|
}
|
||||||
|
frame_class = int(self.get_parameter("FRAME_CLASS"))
|
||||||
|
if frame_class not in servo_counts:
|
||||||
|
self.progress("Test not relevant for frame_class %u" % frame_class)
|
||||||
|
return
|
||||||
|
|
||||||
|
servo_count = servo_counts[frame_class]
|
||||||
|
|
||||||
|
if fail_servo < 0 or fail_servo > servo_count:
|
||||||
|
raise ValueError('fail_servo outside range for frame class')
|
||||||
|
|
||||||
|
self.mavproxy.send('switch 5\n') # loiter mode
|
||||||
|
self.wait_mode('LOITER')
|
||||||
|
|
||||||
|
self.change_alt(alt_min=50)
|
||||||
|
|
||||||
|
# Get initial values
|
||||||
|
start_hud = self.mav.recv_match(type='VFR_HUD', blocking=True)
|
||||||
|
start_attitude = self.mav.recv_match(type='ATTITUDE', blocking=True)
|
||||||
|
|
||||||
|
hover_time = 5
|
||||||
|
try:
|
||||||
|
tstart = self.get_sim_time()
|
||||||
|
int_error_alt = 0
|
||||||
|
int_error_yaw_rate = 0
|
||||||
|
int_error_yaw = 0
|
||||||
|
self.progress("Hovering for %u seconds" % hover_time)
|
||||||
|
failed = False
|
||||||
|
while self.get_sim_time() < tstart + holdtime + hover_time:
|
||||||
|
ti = self.get_sim_time()
|
||||||
|
|
||||||
|
servo = self.mav.recv_match(type='SERVO_OUTPUT_RAW',
|
||||||
|
blocking=True)
|
||||||
|
hud = self.mav.recv_match(type='VFR_HUD', blocking=True)
|
||||||
|
attitude = self.mav.recv_match(type='ATTITUDE', blocking=True)
|
||||||
|
|
||||||
|
if not failed and self.get_sim_time() - tstart > hover_time:
|
||||||
|
self.progress("Killing motor %u (%u%%)" %
|
||||||
|
(fail_servo+1, fail_mul))
|
||||||
|
self.set_parameter("SIM_ENGINE_FAIL", fail_servo)
|
||||||
|
self.set_parameter("SIM_ENGINE_MUL", fail_mul)
|
||||||
|
failed = True
|
||||||
|
|
||||||
|
if failed:
|
||||||
|
self.progress("Hold Time: %f/%f" %
|
||||||
|
(self.get_sim_time()-tstart, holdtime))
|
||||||
|
|
||||||
|
servo_pwm = [servo.servo1_raw,
|
||||||
|
servo.servo2_raw,
|
||||||
|
servo.servo3_raw,
|
||||||
|
servo.servo4_raw,
|
||||||
|
servo.servo5_raw,
|
||||||
|
servo.servo6_raw,
|
||||||
|
servo.servo7_raw,
|
||||||
|
servo.servo8_raw]
|
||||||
|
|
||||||
|
self.progress("PWM output per motor")
|
||||||
|
for i, pwm in enumerate(servo_pwm[0:servo_count]):
|
||||||
|
if pwm > 1900:
|
||||||
|
state = "oversaturated"
|
||||||
|
elif pwm < 1200:
|
||||||
|
state = "undersaturated"
|
||||||
|
else:
|
||||||
|
state = "OK"
|
||||||
|
|
||||||
|
if failed and i==fail_servo:
|
||||||
|
state += " (failed)"
|
||||||
|
|
||||||
|
self.progress("servo %u [pwm=%u] [%s]" % (i+1, pwm, state))
|
||||||
|
|
||||||
|
alt_delta = hud.alt - start_hud.alt
|
||||||
|
yawrate_delta = attitude.yawspeed - start_attitude.yawspeed
|
||||||
|
yaw_delta = attitude.yaw - start_attitude.yaw
|
||||||
|
|
||||||
|
self.progress("Alt=%fm (delta=%fm)" % (hud.alt, alt_delta))
|
||||||
|
self.progress("Yaw rate=%f (delta=%f) (rad/s)" %
|
||||||
|
(attitude.yawspeed, yawrate_delta))
|
||||||
|
self.progress("Yaw=%f (delta=%f) (deg)" %
|
||||||
|
(attitude.yaw, yaw_delta))
|
||||||
|
|
||||||
|
dt = self.get_sim_time() - ti
|
||||||
|
int_error_alt += abs(alt_delta/dt)
|
||||||
|
int_error_yaw_rate += abs(yawrate_delta/dt)
|
||||||
|
int_error_yaw += abs(yaw_delta/dt)
|
||||||
|
self.progress("## Error Integration ##")
|
||||||
|
self.progress(" Altitude: %fm" % int_error_alt)
|
||||||
|
self.progress(" Yaw rate: %f rad/s" % int_error_yaw_rate)
|
||||||
|
self.progress(" Yaw: %f deg" % int_error_yaw)
|
||||||
|
self.progress("----")
|
||||||
|
|
||||||
|
if alt_delta < -20:
|
||||||
|
self.progress("Vehicle is descending")
|
||||||
|
raise NotAchievedException()
|
||||||
|
|
||||||
|
self.set_parameter("SIM_ENGINE_FAIL", 0)
|
||||||
|
self.set_parameter("SIM_ENGINE_MUL", 1.0)
|
||||||
|
except Exception as e:
|
||||||
|
self.set_parameter("SIM_ENGINE_FAIL", 0)
|
||||||
|
self.set_parameter("SIM_ENGINE_MUL", 1.0)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def fly_mission(self, height_accuracy=-1.0, target_altitude=None):
|
def fly_mission(self, height_accuracy=-1.0, target_altitude=None):
|
||||||
"""Fly a mission from a file."""
|
"""Fly a mission from a file."""
|
||||||
global num_wp
|
global num_wp
|
||||||
@ -1154,6 +1265,21 @@ class AutoTestCopter(AutoTest):
|
|||||||
# RTL
|
# RTL
|
||||||
self.run_test("RTL after CIRCLE mode", self.fly_RTL)
|
self.run_test("RTL after CIRCLE mode", self.fly_RTL)
|
||||||
|
|
||||||
|
# Arm
|
||||||
|
self.set_rc(3, 1000)
|
||||||
|
self.mavproxy.send('mode stabilize\n') # stabilize mode
|
||||||
|
self.wait_mode('STABILIZE')
|
||||||
|
|
||||||
|
# Takeoff
|
||||||
|
self.run_test("Takeoff to test motor failure",
|
||||||
|
lambda: self.takeoff(10, arm=True))
|
||||||
|
|
||||||
|
self.run_test("Fly motor failure test",
|
||||||
|
self.fly_motor_fail)
|
||||||
|
|
||||||
|
# RTL
|
||||||
|
self.run_test("RTL after motor failure test", self.fly_RTL)
|
||||||
|
|
||||||
# Arm
|
# Arm
|
||||||
self.set_rc(3, 1000)
|
self.set_rc(3, 1000)
|
||||||
self.mavproxy.send('mode stabilize\n') # stabilize mode
|
self.mavproxy.send('mode stabilize\n') # stabilize mode
|
||||||
|
Loading…
Reference in New Issue
Block a user