#!/usr/bin/env python ''' estimate COMPASS_MOT_* parameters for throttle based compensation ''' from __future__ import print_function from builtins import range import math from argparse import ArgumentParser parser = ArgumentParser(description=__doc__) parser.add_argument("--condition",dest="condition", default=None, help="select packets by condition") parser.add_argument("logs", metavar="LOG", nargs="+") args = parser.parse_args() from pymavlink import mavutil from pymavlink.rotmat import Vector3 def mag_error(p, data): cx,cy,cz,r = p errout = 0 # cruse bounds mechanism if r < 0.3: errout = (0.3 - r) * 100 r = 0.3 if r > 2.0: errout = (r - 2.0) * 100 r = 2.0 corr = Vector3(cx,cy,cz) (baseline_field,baseline_throttle) = data[0] ret = [] for d in data: (mag,throttle) = d cmag = mag + corr * math.pow(throttle,r) err = (cmag - baseline_field).length() err += errout ret.append(err) return ret def fit_data(data): from scipy import optimize p0 = [0.0, 0.0, 0.0, 1.0] p1, ier = optimize.leastsq(mag_error, p0[:], args=(data)) if not ier in [1, 2, 3, 4]: raise RuntimeError("Unable to find solution") return (Vector3(p1[0], p1[1], p1[2]), p1[3]) def magfit(logfile): '''find best magnetometer offset fit to a log file''' print("Processing log %s" % filename) mlog = mavutil.mavlink_connection(filename) data = [] throttle = 0 # now gather all the data while True: m = mlog.recv_match(condition=args.condition) if m is None: break if m.get_type() == "MAG": mag = Vector3(m.MagX, m.MagY, m.MagZ) data.append((mag, throttle)) #if m.get_type() == "RCOU": # throttle = math.sqrt(m.C1/500.0) if m.get_type() == "CTUN": throttle = m.ThO print("Extracted %u data points" % len(data)) (cmot,r) = fit_data(data) print("Fit : %s r: %s" % (cmot,r)) x = range(len(data)) errors = mag_error((cmot.x,cmot.y,cmot.z,r), data) import matplotlib.pyplot as plt plt.plot(x, errors, 'bo-') x1,x2,y1,y2 = plt.axis() plt.axis((x1,x2,0,y2)) plt.ylabel('Error') plt.xlabel('Sample') plt.show() for filename in args.logs: magfit(filename)