123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- '''
- module for loading/saving sets of mavlink parameters
- '''
- from __future__ import print_function
- import fnmatch, math, time, struct
- from pymavlink import mavutil
- class MAVParmDict(dict):
- def __init__(self, *args):
- dict.__init__(self, args)
- # some parameters should not be loaded from files
- self.exclude_load = [
- 'ARSPD_OFFSET',
- 'CMD_INDEX',
- 'CMD_TOTAL',
- 'FENCE_TOTAL',
- 'FORMAT_VERSION',
- 'GND_ABS_PRESS',
- 'GND_TEMP',
- 'LOG_LASTFILE',
- 'MIS_TOTAL',
- 'SYSID_SW_MREV',
- 'SYS_NUM_RESETS',
- ]
- self.mindelta = 0.000001
- def mavset(self, mav, name, value, retries=3, parm_type=None):
- '''set a parameter on a mavlink connection'''
- got_ack = False
- if parm_type is not None and parm_type != mavutil.mavlink.MAV_PARAM_TYPE_REAL32:
- # need to encode as a float for sending
- if parm_type == mavutil.mavlink.MAV_PARAM_TYPE_UINT8:
- vstr = struct.pack(">xxxB", int(value))
- elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_INT8:
- vstr = struct.pack(">xxxb", int(value))
- elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_UINT16:
- vstr = struct.pack(">xxH", int(value))
- elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_INT16:
- vstr = struct.pack(">xxh", int(value))
- elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_UINT32:
- vstr = struct.pack(">I", int(value))
- elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_INT32:
- vstr = struct.pack(">i", int(value))
- else:
- print("can't send %s of type %u" % (name, parm_type))
- return False
- vfloat, = struct.unpack(">f", vstr)
- else:
- vfloat = float(value)
-
- while retries > 0 and not got_ack:
- retries -= 1
- mav.param_set_send(name.upper(), vfloat, parm_type=parm_type)
- tstart = time.time()
- while time.time() - tstart < 1:
- ack = mav.recv_match(type='PARAM_VALUE', blocking=False)
- if ack is None:
- time.sleep(0.1)
- continue
- if str(name).upper() == str(ack.param_id).upper():
- got_ack = True
- self.__setitem__(name, float(value))
- break
- if not got_ack:
- print("timeout setting %s to %f" % (name, vfloat))
- return False
- return True
- def save(self, filename, wildcard='*', verbose=False):
- '''save parameters to a file'''
- f = open(filename, mode='w')
- k = list(self.keys())
- k.sort()
- count = 0
- for p in k:
- if p and fnmatch.fnmatch(str(p).upper(), wildcard.upper()):
- value = self.__getitem__(p)
- if isinstance(value, float):
- f.write("%-16.16s %f\n" % (p, value))
- else:
- f.write("%-16.16s %s\n" % (p, str(value)))
- count += 1
- f.close()
- if verbose:
- print("Saved %u parameters to %s" % (count, filename))
- def load(self, filename, wildcard='*', mav=None, check=True, use_excludes=True):
- '''load parameters from a file'''
- try:
- f = open(filename, mode='r')
- except Exception as e:
- print("Failed to open file '%s': %s" % (filename, str(e)))
- return False
- count = 0
- changed = 0
- for line in f:
- line = line.strip()
- if not line or line[0] == "#":
- continue
- line = line.replace(',',' ')
- a = line.split()
- if len(a) != 2:
- print("Invalid line: %s" % line)
- continue
- # some parameters should not be loaded from files
- if use_excludes and a[0] in self.exclude_load:
- continue
- if not fnmatch.fnmatch(a[0].upper(), wildcard.upper()):
- continue
- if mav is not None:
- if check:
- if a[0] not in list(self.keys()):
- print("Unknown parameter %s" % a[0])
- continue
- old_value = self.__getitem__(a[0])
- if math.fabs(old_value - float(a[1])) <= self.mindelta:
- count += 1
- continue
- if self.mavset(mav, a[0], a[1]):
- print("changed %s from %f to %f" % (a[0], old_value, float(a[1])))
- else:
- print("set %s to %f" % (a[0], float(a[1])))
- self.mavset(mav, a[0], a[1])
- changed += 1
- else:
- self.__setitem__(a[0], float(a[1]))
- count += 1
- f.close()
- if mav is not None:
- print("Loaded %u parameters from %s (changed %u)" % (count, filename, changed))
- else:
- print("Loaded %u parameters from %s" % (count, filename))
- return True
- def show_param_value(self, name, value):
- print("%-16.16s %s" % (name, value))
- def show(self, wildcard='*'):
- '''show parameters'''
- k = sorted(self.keys())
- for p in k:
- if fnmatch.fnmatch(str(p).upper(), wildcard.upper()):
- self.show_param_value(str(p), "%f" % self.get(p))
- def diff(self, filename, wildcard='*', use_excludes=True):
- '''show differences with another parameter file'''
- other = MAVParmDict()
- if not other.load(filename, use_excludes=use_excludes):
- return
- keys = sorted(list(set(self.keys()).union(set(other.keys()))))
- for k in keys:
- if not fnmatch.fnmatch(str(k).upper(), wildcard.upper()):
- continue
- if not k in other:
- value = float(self[k])
- print("%-16.16s %12.4f" % (k, value))
- elif not k in self:
- print("%-16.16s %12.4f" % (k, float(other[k])))
- elif abs(self[k] - other[k]) > self.mindelta:
- value = float(self[k])
- print("%-16.16s %12.4f %12.4f" % (k, other[k], value))
-
-
|