ardupilot/Tools/LogAnalyzer/tests/TestPitchRollCoupling.py

91 lines
3.0 KiB
Python
Raw Normal View History

from LogAnalyzer import Test,TestResult
import DataflashLog
class TestPitchRollCoupling(Test):
'''test for divergence between input and output pitch/roll, i.e. mechanical failure or bad PID tuning'''
def __init__(self):
self.name = "Pitch/Roll"
self.enable = False # TEMP
def run(self, logdata):
self.result = TestResult()
self.result.status = TestResult.StatusType.PASS
if logdata.vehicleType != "ArduCopter":
self.result.status = TestResult.StatusType.NA
if not "ATT" in logdata.channels:
self.result.status = TestResult.StatusType.UNKNOWN
self.result.statusMessage = "No ATT log data"
return
# TODO: implement pitch/roll input/output divergence testing -
# note: names changed from PitchIn to DesPitch at some point, check for both
# what to test for?
# - only analyse while we're airborne
# - absolute diff between in+out?
# - accumulated diff between in+out?
# - slope diff between in+out curves?
# - roll/pitch over max in non-acro modes?
# - if direct control use CTUN roll+pitch, if auto mode use NTUN data
# figure out where each mode begins and ends, so we can treat auto and manual modes differently
autoModes = ["RTL","AUTO","LAND","LOITER","GUIDED","CIRCLE","OF_LOITER"] # use NTUN DRol+DPit
manualModes = ["STABILIZE","DRIFT","ALT_HOLD"] # use CTUN RollIn/DesRoll + PitchIn/DesPitch
ignoreModes = ["ACRO","SPORT","FLIP","AUTOTUNE"] # ignore data from these modes
autoSegments = [] # list of (startLine,endLine) pairs
manualSegments = [] # list of (startLine,endLine) pairs
orderedModes = collections.OrderedDict(sorted(logdata.modeChanges.items(), key=lambda t: t[0]))
isAuto = False # always start in a manual control mode
prevLine = 1
for line,modepair in orderedModes.iteritems():
mode = modepair[0].upper()
if mode in autoModes:
print "On line %d mode changed to %s (AUTO)" % (line,mode) # TEMP
if not isAuto:
manualSegments.append((prevLine,line-1))
print " Previous manual segment: " + `(prevLine,line-1)` # TEMP
prevLine = line
isAuto = True
elif mode in manualModes:
print "On line %d mode changed to %s (MANUAL)" % (line,mode) # TEMP
if isAuto:
autoSegments.append((prevLine,line-1))
print " Previous auto segment: " + `(prevLine,line-1)` # TEMP
prevLine = line
isAuto = False
elif mode in ignoreModes:
pass
else:
raise Exception("Unknown mode in TestPitchRollCoupling: %s" % mode)
# look through manual segments
for startLine,endLine in manualSegments:
(value,attLine) = logdata.channels["ATT"]["Roll"].getNearestValue(startLine, lookForwards=True)
print "Nearest ATT line after %d is %d" % (startLine,attLine)
index = logdata.channels["ATT"]["Roll"].getIndexOf(attLine)
print "First ATT line in manual segment (%d,%d) is line %d" % (startLine,endLine,logdata.channels["ATT"]["Roll"].listData[index][0])
# look through auto segments
# ...