isb_extract.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/env python
  2. '''
  3. extract ISBH and ISBD messages from AP_Logging files into a csv file
  4. '''
  5. from __future__ import print_function
  6. import numpy
  7. import os
  8. import sys
  9. import time
  10. from argparse import ArgumentParser
  11. parser = ArgumentParser(description=__doc__)
  12. parser.add_argument("--condition", default=None, help="select packets by condition")
  13. parser.add_argument("logs", metavar="LOG", nargs="+")
  14. args = parser.parse_args()
  15. from pymavlink import mavutil
  16. def mavfft_fttd(logfile):
  17. '''display fft for raw ACC data in logfile'''
  18. '''object to store data about a single FFT plot'''
  19. class PlotData(object):
  20. def __init__(self, ffth):
  21. self.seqno = -1
  22. self.fftnum = ffth.N
  23. self.sensor_type = ffth.type
  24. self.instance = ffth.instance
  25. self.sample_rate_hz = ffth.smp_rate
  26. self.multiplier = ffth.mul
  27. self.SampleUS = ffth.SampleUS
  28. self.data = {}
  29. self.data["X"] = []
  30. self.data["Y"] = []
  31. self.data["Z"] = []
  32. self.holes = False
  33. self.freq = None
  34. def add_fftd(self, fftd):
  35. if fftd.N != self.fftnum:
  36. print("Skipping ISBD with wrong fftnum (%u vs %u)\n" % (fftd.fftnum, self.fftnum))
  37. return
  38. if self.holes:
  39. print("Skipping ISBD(%u) for ISBH(%u) with holes in it" % (fftd.seqno, self.fftnum))
  40. return
  41. if fftd.seqno != self.seqno+1:
  42. print("ISBH(%u) has holes in it" % fftd.N)
  43. self.holes = True
  44. return
  45. self.seqno += 1
  46. self.data["X"].extend(fftd.x)
  47. self.data["Y"].extend(fftd.y)
  48. self.data["Z"].extend(fftd.z)
  49. def prefix(self):
  50. if self.sensor_type == 0:
  51. return "Accel"
  52. elif self.sensor_type == 1:
  53. return "Gyro"
  54. else:
  55. return "?Unknown Sensor Type?"
  56. def tag(self):
  57. return str(self)
  58. def __str__(self):
  59. return "%s[%u]" % (self.prefix(), self.instance)
  60. print("Processing log %s" % filename)
  61. mlog = mavutil.mavlink_connection(filename)
  62. things_to_plot = []
  63. plotdata = None
  64. msgcount = 0
  65. start_time = time.time()
  66. while True:
  67. m = mlog.recv_match(condition=args.condition)
  68. if m is None:
  69. break
  70. msgcount += 1
  71. if msgcount % 1000 == 0:
  72. sys.stderr.write(".")
  73. msg_type = m.get_type()
  74. if msg_type == "ISBH":
  75. if plotdata is not None:
  76. # close off previous data collection
  77. things_to_plot.append(plotdata)
  78. # initialise plot-data collection object
  79. plotdata = PlotData(m)
  80. continue
  81. if msg_type == "ISBD":
  82. if plotdata is None:
  83. print("Skipping ISBD outside ISBH (fftnum=%u)\n" % m.N)
  84. continue
  85. plotdata.add_fftd(m)
  86. print("", file=sys.stderr)
  87. time_delta = time.time() - start_time
  88. print("%us messages %u messages/second %u kB/second" % (msgcount, msgcount/time_delta, os.stat(filename).st_size/time_delta))
  89. print("Extracted %u fft data sets" % len(things_to_plot), file=sys.stderr)
  90. sum_fft = {}
  91. freqmap = {}
  92. count = 0
  93. first_freq = None
  94. files = {}
  95. for p in things_to_plot:
  96. fname = p.prefix() + str(p.instance) + ".csv"
  97. if not fname in files:
  98. files[fname] = open(fname, "w")
  99. f = files[fname]
  100. f.write("SampleUS,X,Y,Z\n")
  101. f = files[fname]
  102. dt = 1.0e6 / p.sample_rate_hz
  103. for i in range(len(p.data['X'])):
  104. x = p.data['X'][i]/p.multiplier
  105. y = p.data['Y'][i]/p.multiplier
  106. z = p.data['Z'][i]/p.multiplier
  107. f.write("%u,%.5f,%.5f,%.5f\n" % (int(p.SampleUS+i*dt), x, y, z))
  108. for f in files:
  109. files[f].close()
  110. for filename in args.logs:
  111. mavfft_fttd(filename)