2014-03-03 13:46:17 -04:00
|
|
|
import math
|
2022-07-18 11:09:04 -03:00
|
|
|
from functools import reduce
|
|
|
|
|
|
|
|
import DataflashLog
|
|
|
|
from LogAnalyzer import Test, TestResult
|
2014-03-03 13:46:17 -04:00
|
|
|
|
2014-01-27 02:38:57 -04:00
|
|
|
|
|
|
|
class TestCompass(Test):
|
2014-08-12 12:54:15 -03:00
|
|
|
'''test for compass offsets and throttle interference'''
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
Test.__init__(self)
|
|
|
|
self.name = "Compass"
|
|
|
|
|
|
|
|
def run(self, logdata, verbose):
|
|
|
|
self.result = TestResult()
|
|
|
|
self.result.status = TestResult.StatusType.GOOD
|
|
|
|
|
2014-10-25 18:30:52 -03:00
|
|
|
def vec_len(x):
|
2022-07-18 11:09:04 -03:00
|
|
|
return math.sqrt(x[0] ** 2 + x[1] ** 2 + x[2] ** 2)
|
2014-10-25 18:30:52 -03:00
|
|
|
|
|
|
|
def FAIL():
|
|
|
|
self.result.status = TestResult.StatusType.FAIL
|
|
|
|
|
|
|
|
def WARN():
|
|
|
|
if self.result.status != TestResult.StatusType.FAIL:
|
|
|
|
self.result.status = TestResult.StatusType.WARN
|
|
|
|
|
2014-08-12 12:58:02 -03:00
|
|
|
try:
|
2014-10-25 18:30:52 -03:00
|
|
|
warnOffset = 300
|
|
|
|
failOffset = 500
|
|
|
|
param_offsets = (
|
2021-12-04 00:22:57 -04:00
|
|
|
logdata.parameters["COMPASS_OFS_X"],
|
|
|
|
logdata.parameters["COMPASS_OFS_Y"],
|
2022-07-18 11:09:04 -03:00
|
|
|
logdata.parameters["COMPASS_OFS_Z"],
|
|
|
|
)
|
2014-10-25 18:30:52 -03:00
|
|
|
|
|
|
|
if vec_len(param_offsets) > failOffset:
|
|
|
|
FAIL()
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = "FAIL: Large compass offset params (X:%.2f, Y:%.2f, Z:%.2f)\n" % (
|
|
|
|
param_offsets[0],
|
|
|
|
param_offsets[1],
|
|
|
|
param_offsets[2],
|
|
|
|
)
|
2014-10-25 18:30:52 -03:00
|
|
|
elif vec_len(param_offsets) > warnOffset:
|
|
|
|
WARN()
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = "WARN: Large compass offset params (X:%.2f, Y:%.2f, Z:%.2f)\n" % (
|
|
|
|
param_offsets[0],
|
|
|
|
param_offsets[1],
|
|
|
|
param_offsets[2],
|
|
|
|
)
|
2014-10-25 18:30:52 -03:00
|
|
|
|
2014-08-12 12:58:02 -03:00
|
|
|
if "MAG" in logdata.channels:
|
2014-10-25 18:30:52 -03:00
|
|
|
max_log_offsets = zip(
|
2022-07-18 11:09:04 -03:00
|
|
|
map(lambda x: x[1], logdata.channels["MAG"]["OfsX"].listData),
|
|
|
|
map(lambda x: x[1], logdata.channels["MAG"]["OfsY"].listData),
|
|
|
|
map(lambda x: x[1], logdata.channels["MAG"]["OfsZ"].listData),
|
|
|
|
)
|
|
|
|
max_log_offsets = reduce(lambda x, y: x if vec_len(x) > vec_len(y) else y, max_log_offsets)
|
2014-10-25 18:30:52 -03:00
|
|
|
|
|
|
|
if vec_len(max_log_offsets) > failOffset:
|
|
|
|
FAIL()
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage += "FAIL: Large compass offset in MAG data (X:%.2f, Y:%.2f, Z:%.2f)\n" % (
|
|
|
|
max_log_offsets[0],
|
|
|
|
max_log_offsets[1],
|
|
|
|
max_log_offsets[2],
|
|
|
|
)
|
2014-10-25 18:30:52 -03:00
|
|
|
elif vec_len(max_log_offsets) > warnOffset:
|
|
|
|
WARN()
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage += "WARN: Large compass offset in MAG data (X:%.2f, Y:%.2f, Z:%.2f)\n" % (
|
|
|
|
max_log_offsets[0],
|
|
|
|
max_log_offsets[1],
|
|
|
|
max_log_offsets[2],
|
|
|
|
)
|
2014-08-12 12:58:02 -03:00
|
|
|
|
|
|
|
# check for mag field length change, and length outside of recommended range
|
|
|
|
if "MAG" in logdata.channels:
|
|
|
|
percentDiffThresholdWARN = 0.25
|
|
|
|
percentDiffThresholdFAIL = 0.35
|
|
|
|
minMagFieldThreshold = 120.0
|
|
|
|
maxMagFieldThreshold = 550.0
|
|
|
|
index = 0
|
|
|
|
length = len(logdata.channels["MAG"]["MagX"].listData)
|
|
|
|
magField = []
|
2022-07-18 11:09:04 -03:00
|
|
|
(minMagField, maxMagField) = (None, None)
|
|
|
|
(minMagFieldLine, maxMagFieldLine) = (None, None)
|
2014-08-12 12:58:02 -03:00
|
|
|
zerosFound = False
|
2022-07-18 11:09:04 -03:00
|
|
|
while index < length:
|
2014-08-12 12:58:02 -03:00
|
|
|
mx = logdata.channels["MAG"]["MagX"].listData[index][1]
|
|
|
|
my = logdata.channels["MAG"]["MagY"].listData[index][1]
|
|
|
|
mz = logdata.channels["MAG"]["MagZ"].listData[index][1]
|
2022-07-18 11:09:04 -03:00
|
|
|
if (
|
|
|
|
(mx == 0) and (my == 0) and (mz == 0)
|
|
|
|
): # sometimes they're zero, not sure why, same reason as why we get NaNs as offsets?
|
2014-08-12 12:58:02 -03:00
|
|
|
zerosFound = True
|
|
|
|
else:
|
2022-07-18 11:09:04 -03:00
|
|
|
mf = math.sqrt(mx * mx + my * my + mz * mz)
|
2014-08-12 12:58:02 -03:00
|
|
|
magField.append(mf)
|
2022-07-18 11:09:04 -03:00
|
|
|
if mf < minMagField:
|
2014-08-12 12:58:02 -03:00
|
|
|
minMagField = mf
|
|
|
|
minMagFieldLine = logdata.channels["MAG"]["MagX"].listData[index][0]
|
2022-07-18 11:09:04 -03:00
|
|
|
if mf > maxMagField:
|
2014-08-12 12:58:02 -03:00
|
|
|
maxMagField = mf
|
|
|
|
maxMagFieldLine = logdata.channels["MAG"]["MagX"].listData[index][0]
|
|
|
|
if index == 0:
|
2022-07-18 11:09:04 -03:00
|
|
|
(minMagField, maxMagField) = (mf, mf)
|
2014-08-12 12:58:02 -03:00
|
|
|
index += 1
|
2017-09-23 22:51:51 -03:00
|
|
|
if minMagField is None:
|
2014-10-25 18:30:52 -03:00
|
|
|
FAIL()
|
2017-09-23 22:51:51 -03:00
|
|
|
self.result.statusMessage = self.result.statusMessage + "No valid mag data found\n"
|
2014-08-12 12:54:15 -03:00
|
|
|
else:
|
2022-07-18 11:09:04 -03:00
|
|
|
percentDiff = (maxMagField - minMagField) / minMagField
|
2017-09-23 22:51:51 -03:00
|
|
|
if percentDiff > percentDiffThresholdFAIL:
|
|
|
|
FAIL()
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = (
|
|
|
|
self.result.statusMessage + "Large change in mag_field (%.2f%%)\n" % (percentDiff * 100)
|
|
|
|
)
|
2017-09-23 22:51:51 -03:00
|
|
|
elif percentDiff > percentDiffThresholdWARN:
|
|
|
|
WARN()
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = (
|
|
|
|
self.result.statusMessage + "Moderate change in mag_field (%.2f%%)\n" % (percentDiff * 100)
|
|
|
|
)
|
2017-09-23 22:51:51 -03:00
|
|
|
else:
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = (
|
|
|
|
self.result.statusMessage
|
|
|
|
+ "mag_field interference within limits (%.2f%%)\n" % (percentDiff * 100)
|
|
|
|
)
|
2017-09-23 22:51:51 -03:00
|
|
|
if minMagField < minMagFieldThreshold:
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = (
|
|
|
|
self.result.statusMessage
|
|
|
|
+ "Min mag field length (%.2f) < recommended (%.2f)\n" % (minMagField, minMagFieldThreshold)
|
|
|
|
)
|
2017-09-23 22:51:51 -03:00
|
|
|
if maxMagField > maxMagFieldThreshold:
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = (
|
|
|
|
self.result.statusMessage
|
|
|
|
+ "Max mag field length (%.2f) > recommended (%.2f)\n" % (maxMagField, maxMagFieldThreshold)
|
|
|
|
)
|
2017-09-23 22:51:51 -03:00
|
|
|
if verbose:
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = self.result.statusMessage + "Min mag_field of %.2f on line %d\n" % (
|
|
|
|
minMagField,
|
|
|
|
minMagFieldLine,
|
|
|
|
)
|
|
|
|
self.result.statusMessage = self.result.statusMessage + "Max mag_field of %.2f on line %d\n" % (
|
|
|
|
maxMagField,
|
|
|
|
maxMagFieldLine,
|
|
|
|
)
|
2014-08-12 12:58:02 -03:00
|
|
|
if zerosFound:
|
2017-09-23 22:51:51 -03:00
|
|
|
if self.result.status == TestResult.StatusType.GOOD:
|
|
|
|
WARN()
|
2014-08-12 12:58:02 -03:00
|
|
|
self.result.statusMessage = self.result.statusMessage + "All zeros found in MAG X/Y/Z log data\n"
|
|
|
|
|
2014-08-12 12:54:15 -03:00
|
|
|
else:
|
2022-07-18 11:09:04 -03:00
|
|
|
self.result.statusMessage = (
|
|
|
|
self.result.statusMessage + "No MAG data, unable to test mag_field interference\n"
|
|
|
|
)
|
2014-08-12 12:58:02 -03:00
|
|
|
|
|
|
|
except KeyError as e:
|
|
|
|
self.result.status = TestResult.StatusType.FAIL
|
|
|
|
self.result.statusMessage = str(e) + ' not found'
|