mavparm.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. '''
  2. module for loading/saving sets of mavlink parameters
  3. '''
  4. from __future__ import print_function
  5. import fnmatch, math, time, struct
  6. from pymavlink import mavutil
  7. class MAVParmDict(dict):
  8. def __init__(self, *args):
  9. dict.__init__(self, args)
  10. # some parameters should not be loaded from files
  11. self.exclude_load = [
  12. 'ARSPD_OFFSET',
  13. 'CMD_INDEX',
  14. 'CMD_TOTAL',
  15. 'FENCE_TOTAL',
  16. 'FORMAT_VERSION',
  17. 'GND_ABS_PRESS',
  18. 'GND_TEMP',
  19. 'LOG_LASTFILE',
  20. 'MIS_TOTAL',
  21. 'SYSID_SW_MREV',
  22. 'SYS_NUM_RESETS',
  23. ]
  24. self.mindelta = 0.000001
  25. def mavset(self, mav, name, value, retries=3, parm_type=None):
  26. '''set a parameter on a mavlink connection'''
  27. got_ack = False
  28. if parm_type is not None and parm_type != mavutil.mavlink.MAV_PARAM_TYPE_REAL32:
  29. # need to encode as a float for sending
  30. if parm_type == mavutil.mavlink.MAV_PARAM_TYPE_UINT8:
  31. vstr = struct.pack(">xxxB", int(value))
  32. elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_INT8:
  33. vstr = struct.pack(">xxxb", int(value))
  34. elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_UINT16:
  35. vstr = struct.pack(">xxH", int(value))
  36. elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_INT16:
  37. vstr = struct.pack(">xxh", int(value))
  38. elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_UINT32:
  39. vstr = struct.pack(">I", int(value))
  40. elif parm_type == mavutil.mavlink.MAV_PARAM_TYPE_INT32:
  41. vstr = struct.pack(">i", int(value))
  42. else:
  43. print("can't send %s of type %u" % (name, parm_type))
  44. return False
  45. vfloat, = struct.unpack(">f", vstr)
  46. else:
  47. vfloat = float(value)
  48. while retries > 0 and not got_ack:
  49. retries -= 1
  50. mav.param_set_send(name.upper(), vfloat, parm_type=parm_type)
  51. tstart = time.time()
  52. while time.time() - tstart < 1:
  53. ack = mav.recv_match(type='PARAM_VALUE', blocking=False)
  54. if ack is None:
  55. time.sleep(0.1)
  56. continue
  57. if str(name).upper() == str(ack.param_id).upper():
  58. got_ack = True
  59. self.__setitem__(name, float(value))
  60. break
  61. if not got_ack:
  62. print("timeout setting %s to %f" % (name, vfloat))
  63. return False
  64. return True
  65. def save(self, filename, wildcard='*', verbose=False):
  66. '''save parameters to a file'''
  67. f = open(filename, mode='w')
  68. k = list(self.keys())
  69. k.sort()
  70. count = 0
  71. for p in k:
  72. if p and fnmatch.fnmatch(str(p).upper(), wildcard.upper()):
  73. value = self.__getitem__(p)
  74. if isinstance(value, float):
  75. f.write("%-16.16s %f\n" % (p, value))
  76. else:
  77. f.write("%-16.16s %s\n" % (p, str(value)))
  78. count += 1
  79. f.close()
  80. if verbose:
  81. print("Saved %u parameters to %s" % (count, filename))
  82. def load(self, filename, wildcard='*', mav=None, check=True, use_excludes=True):
  83. '''load parameters from a file'''
  84. try:
  85. f = open(filename, mode='r')
  86. except Exception as e:
  87. print("Failed to open file '%s': %s" % (filename, str(e)))
  88. return False
  89. count = 0
  90. changed = 0
  91. for line in f:
  92. line = line.strip()
  93. if not line or line[0] == "#":
  94. continue
  95. line = line.replace(',',' ')
  96. a = line.split()
  97. if len(a) != 2:
  98. print("Invalid line: %s" % line)
  99. continue
  100. # some parameters should not be loaded from files
  101. if use_excludes and a[0] in self.exclude_load:
  102. continue
  103. if not fnmatch.fnmatch(a[0].upper(), wildcard.upper()):
  104. continue
  105. if mav is not None:
  106. if check:
  107. if a[0] not in list(self.keys()):
  108. print("Unknown parameter %s" % a[0])
  109. continue
  110. old_value = self.__getitem__(a[0])
  111. if math.fabs(old_value - float(a[1])) <= self.mindelta:
  112. count += 1
  113. continue
  114. if self.mavset(mav, a[0], a[1]):
  115. print("changed %s from %f to %f" % (a[0], old_value, float(a[1])))
  116. else:
  117. print("set %s to %f" % (a[0], float(a[1])))
  118. self.mavset(mav, a[0], a[1])
  119. changed += 1
  120. else:
  121. self.__setitem__(a[0], float(a[1]))
  122. count += 1
  123. f.close()
  124. if mav is not None:
  125. print("Loaded %u parameters from %s (changed %u)" % (count, filename, changed))
  126. else:
  127. print("Loaded %u parameters from %s" % (count, filename))
  128. return True
  129. def show_param_value(self, name, value):
  130. print("%-16.16s %s" % (name, value))
  131. def show(self, wildcard='*'):
  132. '''show parameters'''
  133. k = sorted(self.keys())
  134. for p in k:
  135. if fnmatch.fnmatch(str(p).upper(), wildcard.upper()):
  136. self.show_param_value(str(p), "%f" % self.get(p))
  137. def diff(self, filename, wildcard='*', use_excludes=True):
  138. '''show differences with another parameter file'''
  139. other = MAVParmDict()
  140. if not other.load(filename, use_excludes=use_excludes):
  141. return
  142. keys = sorted(list(set(self.keys()).union(set(other.keys()))))
  143. for k in keys:
  144. if not fnmatch.fnmatch(str(k).upper(), wildcard.upper()):
  145. continue
  146. if not k in other:
  147. value = float(self[k])
  148. print("%-16.16s %12.4f" % (k, value))
  149. elif not k in self:
  150. print("%-16.16s %12.4f" % (k, float(other[k])))
  151. elif abs(self[k] - other[k]) > self.mindelta:
  152. value = float(self[k])
  153. print("%-16.16s %12.4f %12.4f" % (k, other[k], value))