mavextract.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #!/usr/bin/env python
  2. '''
  3. extract one mode type from a log
  4. '''
  5. from __future__ import print_function
  6. import os
  7. import struct
  8. from argparse import ArgumentParser
  9. parser = ArgumentParser(description=__doc__)
  10. parser.add_argument("--no-timestamps", dest="notimestamps", action='store_true', help="Log doesn't have timestamps")
  11. parser.add_argument("--robust", action='store_true', help="Enable robust parsing (skip over bad data)")
  12. parser.add_argument("--condition", default=None, help="select packets by condition")
  13. parser.add_argument("--mode", default='auto', help="mode to extract")
  14. parser.add_argument("--link", default=None, type=int, help="only extract specific comms link")
  15. parser.add_argument("logs", metavar="LOG", nargs="+")
  16. args = parser.parse_args()
  17. from pymavlink import mavutil
  18. def older_message(m, lastm):
  19. '''return true if m is older than lastm by timestamp'''
  20. atts = {'time_boot_ms' : 1.0e-3,
  21. 'time_unix_usec' : 1.0e-6,
  22. 'time_usec' : 1.0e-6}
  23. for a in list(atts.keys()):
  24. if hasattr(m, a):
  25. mul = atts[a]
  26. t1 = m.getattr(a) * mul
  27. t2 = lastm.getattr(a) * mul
  28. if t2 >= t1 and t2 - t1 < 60:
  29. return True
  30. return False
  31. def process(filename):
  32. '''process one logfile'''
  33. print("Processing %s" % filename)
  34. mlog = mavutil.mavlink_connection(filename, notimestamps=args.notimestamps,
  35. robust_parsing=args.robust)
  36. ext = os.path.splitext(filename)[1]
  37. isbin = ext in ['.bin', '.BIN']
  38. islog = ext in ['.log', '.LOG']
  39. output = None
  40. count = 1
  41. dirname = os.path.dirname(filename)
  42. if isbin or islog:
  43. extension = "bin"
  44. else:
  45. extension = "tlog"
  46. file_header = ''
  47. messages = []
  48. # we allow a list of modes that map to one mode number. This allows for --mode=AUTO,RTL and consider the RTL as part of AUTO
  49. modes = args.mode.upper().split(',')
  50. flightmode = None
  51. while True:
  52. m = mlog.recv_match()
  53. if m is None:
  54. break
  55. if args.link is not None and m._link != args.link:
  56. continue
  57. mtype = m.get_type()
  58. if mtype in messages:
  59. if older_message(m, messages[mtype]):
  60. continue
  61. # we don't use mlog.flightmode as that can be wrong if we are extracting a single link
  62. if mtype == 'HEARTBEAT' and m.get_srcComponent() != mavutil.mavlink.MAV_COMP_ID_GIMBAL and m.type != mavutil.mavlink.MAV_TYPE_GCS:
  63. flightmode = mavutil.mode_string_v10(m).upper()
  64. if mtype == 'MODE':
  65. flightmode = mlog.flightmode
  66. if (isbin or islog) and m.get_type() in ["FMT", "PARM", "CMD"]:
  67. file_header += m.get_msgbuf()
  68. if (isbin or islog) and m.get_type() == 'MSG' and m.Message.startswith("Ardu"):
  69. file_header += m.get_msgbuf()
  70. if m.get_type() in ['PARAM_VALUE','MISSION_ITEM']:
  71. timestamp = getattr(m, '_timestamp', None)
  72. file_header += struct.pack('>Q', timestamp*1.0e6) + m.get_msgbuf()
  73. if not mavutil.evaluate_condition(args.condition, mlog.messages):
  74. continue
  75. if flightmode in modes:
  76. if output is None:
  77. path = os.path.join(dirname, "%s%u.%s" % (modes[0], count, extension))
  78. count += 1
  79. print("Creating %s" % path)
  80. output = open(path, mode='wb')
  81. output.write(file_header)
  82. else:
  83. if output is not None:
  84. output.close()
  85. output = None
  86. if output and m.get_type() != 'BAD_DATA':
  87. timestamp = getattr(m, '_timestamp', None)
  88. if not isbin:
  89. output.write(struct.pack('>Q', timestamp*1.0e6))
  90. output.write(m.get_msgbuf())
  91. for filename in args.logs:
  92. process(filename)