2014-01-27 02:38:57 -04:00
|
|
|
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"
|
2014-02-12 15:55:00 -04:00
|
|
|
self.enable = False # TEMP
|
2014-01-27 02:38:57 -04:00
|
|
|
|
|
|
|
def run(self, logdata):
|
|
|
|
self.result = TestResult()
|
|
|
|
self.result.status = TestResult.StatusType.PASS
|
|
|
|
|
2014-02-26 08:50:55 -04:00
|
|
|
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
|
|
|
|
|
2014-01-27 02:38:57 -04:00
|
|
|
# TODO: implement pitch/roll input/output divergence testing -
|
|
|
|
|
|
|
|
# note: names changed from PitchIn to DesPitch at some point, check for both
|
2014-02-03 01:21:30 -04:00
|
|
|
|
|
|
|
# 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
|
2014-02-26 08:50:55 -04:00
|
|
|
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
|
2014-02-03 01:21:30 -04:00
|
|
|
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:
|
2014-02-26 08:50:55 -04:00
|
|
|
print "On line %d mode changed to %s (AUTO)" % (line,mode) # TEMP
|
2014-02-03 01:21:30 -04:00
|
|
|
if not isAuto:
|
|
|
|
manualSegments.append((prevLine,line-1))
|
2014-02-26 08:50:55 -04:00
|
|
|
print " Previous manual segment: " + `(prevLine,line-1)` # TEMP
|
|
|
|
prevLine = line
|
2014-02-03 01:21:30 -04:00
|
|
|
isAuto = True
|
|
|
|
elif mode in manualModes:
|
2014-02-26 08:50:55 -04:00
|
|
|
print "On line %d mode changed to %s (MANUAL)" % (line,mode) # TEMP
|
2014-02-03 01:21:30 -04:00
|
|
|
if isAuto:
|
|
|
|
autoSegments.append((prevLine,line-1))
|
2014-02-26 08:50:55 -04:00
|
|
|
print " Previous auto segment: " + `(prevLine,line-1)` # TEMP
|
|
|
|
prevLine = line
|
2014-02-03 01:21:30 -04:00
|
|
|
isAuto = False
|
2014-02-26 08:50:55 -04:00
|
|
|
elif mode in ignoreModes:
|
2014-02-03 01:21:30 -04:00
|
|
|
pass
|
|
|
|
else:
|
2014-02-26 08:50:55 -04:00
|
|
|
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
|
|
|
|
# ...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|