From 789fd061923d051317dd5f420347c7ccb0355ce0 Mon Sep 17 00:00:00 2001 From: Markus Koetter Date: Sun, 27 Jul 2014 17:25:32 +0200 Subject: [PATCH] LogAnalyzer - Improve Autotune Test - previously version could report failed autotune sessions as valid and valid sessions as failed --- Tools/LogAnalyzer/tests/TestAutotune.py | 111 +++++++++++++++++------- 1 file changed, 81 insertions(+), 30 deletions(-) diff --git a/Tools/LogAnalyzer/tests/TestAutotune.py b/Tools/LogAnalyzer/tests/TestAutotune.py index a268fe2442..f09b42cb0e 100644 --- a/Tools/LogAnalyzer/tests/TestAutotune.py +++ b/Tools/LogAnalyzer/tests/TestAutotune.py @@ -1,10 +1,51 @@ from LogAnalyzer import Test,TestResult import DataflashLog +# from ArduCopter/defines.h +AUTOTUNE_INITIALISED = 30 +AUTOTUNE_OFF = 31 +AUTOTUNE_RESTART = 32 +AUTOTUNE_SUCCESS = 33 +AUTOTUNE_FAILED = 34 +AUTOTUNE_REACHED_LIMIT = 35 +AUTOTUNE_PILOT_TESTING = 36 +AUTOTUNE_SAVEDGAINS = 37 + +AUTOTUNE_EVENTS = frozenset([AUTOTUNE_INITIALISED, + AUTOTUNE_OFF, + AUTOTUNE_RESTART, + AUTOTUNE_SUCCESS, + AUTOTUNE_FAILED, + AUTOTUNE_REACHED_LIMIT, + AUTOTUNE_PILOT_TESTING, + AUTOTUNE_SAVEDGAINS]) class TestAutotune(Test): '''test for autotune success (copter only)''' + class AutotuneSession(object): + def __init__(self, events): + self.events = events + @property + def linestart(self): + return self.events[0][0] + @property + def linestop(self): + return self.events[-1][0] + @property + def success(self): + return AUTOTUNE_SUCCESS in [i for _,i in self.events] + @property + def failure(self): + return AUTOTUNE_FAILED in [i for _,i in self.events] + @property + def limit(self): + return AUTOTUNE_REACHED_LIMIT in [i for _,i in self.events] + + def __repr__(self): + return "".format(self.linestart,self.linestop) + + def __init__(self): Test.__init__(self) self.name = "Autotune" @@ -26,27 +67,22 @@ class TestAutotune(Test): if r: return - for line,ev in logdata.channels["EV"]["Id"].listData: - if ev != 30: # Autotune Start - continue - nextline = startline = line - nextev = -1 - while nextev not in(35,34): - try: - (nextev,nextline) = logdata.channels["EV"]["Id"].getNearestValueFwd(nextline+1) - except: - break + events = filter(lambda x: x[1] in AUTOTUNE_EVENTS, logdata.channels["EV"]["Id"].listData) + attempts = [] - if nextev not in(35,34): # autotune is still running - continue + j = None + for i in range(0,len(events)): + line,ev = events[i] + if ev == AUTOTUNE_INITIALISED: + if j is not None: + attempts.append(TestAutotune.AutotuneSession(events[j:i])) + j = i - if nextev == 34: # autotune failed - self.result.status = TestResult.StatusType.FAIL - s = "[-]" - else: - self.result.status = TestResult.StatusType.GOOD - s = "[+]" + # last attempt + if j is not None: + attempts.append(TestAutotune.AutotuneSession(events[j:])) + for a in attempts: # this should not be necessary! def class_from_channel(c): members = dict({'__init__':lambda x: setattr(x,i,None) for i in logdata.channels[c]}) @@ -57,18 +93,33 @@ class TestAutotune(Test): ) return cls - atde = class_from_channel('ATDE')() - for key in logdata.channels['ATDE']: - setattr(atde, key, logdata.channels['ATDE'][key].getNearestValueBack(nextline)[0]) - - atun = class_from_channel('ATUN')() - for key in logdata.channels['ATUN']: - setattr(atun, key, logdata.channels['ATUN'][key].getNearestValueBack(nextline)[0]) - self.result.statusMessage += '{s} ATDE Angle:{atde.Angle} Rate:{atde.Rate} ATUN RPGain:{atun.RPGain} RDGain:{atun.RDGain} SPGain:{atun.SPGain} (@line:{l})\n'.format(l=nextline,s=s,atde=atde, atun=atun) - - if nextev not in(35,34): - self.result.statusMessage += "incomplete autotune attempt started @{l}\n".format(l=startline) - + # last wins + if a.success: + self.result.status = TestResult.StatusType.GOOD + s = "[+]" + elif a.failure: + self.result.status = TestResult.StatusType.FAIL + s = "[-]" + else: + self.result.status = TestResult.StatusType.UNKNOWN + s = "[?]" + s += " Autotune {}-{}\n".format(a.linestart,a.linestop) + self.result.statusMessage += s + if verbose: + linenext = a.linestart + 1 + while linenext < a.linestop: + try: + line = logdata.channels['ATUN']['RateMax'].getNearestValueFwd(linenext)[1] + if line > a.linestop: + break + except: + break + atun = class_from_channel('ATUN')() + for key in logdata.channels['ATUN']: + setattr(atun, key, logdata.channels['ATUN'][key].getNearestValueFwd(linenext)[0]) + linenext = logdata.channels['ATUN'][key].getNearestValueFwd(linenext)[1] + 1 + self.result.statusMessage += 'ATUN Axis:{atun.Axis} TuneStep:{atun.TuneStep} RateMin:{atun.RateMin:5.0f} RateMax:{atun.RateMax:5.0f} RPGain:{atun.RPGain:1.4f} RDGain:{atun.RDGain:1.4f} SPGain:{atun.SPGain:1.1f} (@line:{l})\n'.format(l=linenext,s=s, atun=atun) + self.result.statusMessage += '\n'