ISToolsDataSorted.py
Go to the documentation of this file.
1 '''
2 Created on Feb 22, 2014
3 
4 @author: waltj
5 '''
6 from numbers import Number
7 import numpy as np
8 import os
9 import glob
10 import sys
11 import simplekml
12 import ctypes as ct
13 import pylib.pose as pose
14 import pylib.filterTools as ft
15 
16 # Profiling code
17 import time as systime
18 
19 from numpy import uint8 as u8
20 from numpy import uint16 as u16
21 from numpy import uint32 as u32
22 from numpy import int32 as i32
23 from numpy import float32 as f32
24 from numpy import int64 as i64
25 from numpy import float64 as f64
26 import datetime
27 
28 # Set Reference LLA (deg, deg, m) used for NED - Salem, UT
29 refLla = np.r_[40.0557114, -111.6585476, 1426.77]
30 gpsWeek = 0
31 showUtcTime = 0
32 
33 
34 # Set Reference latitude, longitude, height above ellipsoid (deg, deg, m) used for NED calculations
35 def setRefLla(lla):
36  global refLla
37  refLla = lla
38 
39 
40 def setShowUtcTime(show):
41  global showUtcTime
42  showUtcTime = show
43 
44 WEEK_TIME = []
45 def setGpsWeek(week):
46  global gpsWeek
47  global WEEK_TIME
48  # Search for a valid GPS week
49  size = np.shape(week)
50  if size and size[0] > 1:
51  # if week[0]:
52  # week = week[0]
53  # else:
54  # week = week[-1]
55  week = np.max(week)
56 
57  if week > gpsWeek:
58  gpsWeek = week
59 
60  GPS_start_Time = datetime.datetime.strptime('6/Jan/1980', "%d/%b/%Y")
61  WEEK_TIME = GPS_start_Time + (datetime.timedelta(weeks=int(week)))
62 
64  global WEEK_TIME
65  return [WEEK_TIME + datetime.timedelta(milliseconds=int(i)) for i in ms]
66 
68  global WEEK_TIME
69  return [WEEK_TIME + datetime.timedelta(seconds=float(i)) for i in s]
70 
71 def getTimeFromGTime(gtime):
72  GPS_start_Time = datetime.datetime.strptime('1/Jan/1970', "%d/%b/%Y")
73  return [GPS_start_Time + datetime.timedelta(seconds=float(t['time'] + t['sec'])) for t in gtime]
74 
75 # import time
76 
77 # Default run behavior
78 # execfile("..\INS_logger\IsParseLoggerDat.py")
79 
80 
81 # def getdict(self):
82 # dict((f, getattr(self, f)) for f, _ in self._fields_)
83 
84 
85 # Empty class/dictionary
86 class cObj:
87  def __init__(self):
88  # self.res = []
89  return
90 
91 
92 class cDataType:
93  def __init__(self, name='', dtype=0):
94  self.name = name
95  self.dtype = dtype
96 
97  def set(self, name, dtype):
98  self.name = name
99  self.dtype = dtype
100 
101 
102 # def nameID(self, did, name ):
103 # self.id = did
104 # self.name = name
105 #
106 # def dType(self, dtype):
107 # self.dtype = dtype
108 
109 def vector3(_v, name):
110  return np.c_[_v[name + '[0]'].T, _v[name + '[1]'].T, _v[name + '[2]'].T]
111 
112 
113 def vector4(_v, name):
114  return np.c_[_v[name + '[0]'].T, _v[name + '[1]'].T, _v[name + '[2]'].T, _v[name + '[3]'].T]
115 
116 
117 RAW_DATA_OBS = 1,
118 RAW_DATA_EPH = 2,
119 RAW_DATA_GEPH = 3,
120 RAW_DATA_SBAS = 4,
121 RAW_DATA_STA = 5,
122 RAW_DATA_RTK_SOL = 123
123 
124 dtypeGpsRaw = np.dtype([
125  ('dataSerNum', u32),
126  ('receiverIndex', u8),
127  ('type', u8),
128  ('count', u8),
129  ('reserved', u8)
130 ])
131 
132 dtypeGtime = np.dtype([
133  ('time', i64),
134  ('sec', f64)])
135 
136 dtypeEph = np.dtype([
137  ('sat', i32),
138  ('iode', i32),
139  ('iodc', i32),
140  ('sva', i32),
141  ('svh', i32),
142  ('week', i32),
143  ('code', i32),
144  ('flag', i32),
145  ('toe', dtypeGtime),
146  ('toc', dtypeGtime),
147  ('ttr', dtypeGtime),
148  ('A', f64),
149  ('e', f64),
150  ('i0', f64),
151  ('OMG0', f64),
152  ('omg', f64),
153  ('M0', f64),
154  ('deln', f64),
155  ('OMGd', f64),
156  ('idot', f64),
157  ('crc', f64),
158  ('crs', f64),
159  ('cuc', f64),
160  ('cus', f64),
161  ('cic', f64),
162  ('cis', f64),
163  ('toes', f64),
164  ('fit', f64),
165  ('f0', f64),
166  ('f1', f64),
167  ('f2', f64),
168  ('tgd', (f64, 4)),
169  ('Adot', f64),
170  ('ndot', f64),
171 ])
172 
173 dtypeGEph = np.dtype([
174  ('sat', i32),
175  ('iode', i32),
176  ('frq', i32),
177  ('svh', i32),
178  ('sva', i32),
179  ('age', i32),
180  ('toe', dtypeGtime),
181  ('tof', dtypeGtime),
182  ('pos', (f64, 3)),
183  ('vel', (f64, 3)),
184  ('acc', (f64, 3)),
185  ('taun', f64),
186  ('gamn', f64),
187  ('dtaun', f64)
188 ])
189 
190 dtypeSbas = np.dtype([
191  ('week', i32),
192  ('tow', i32),
193  ('prn', i32),
194  ('msg', (u8, 29)),
195  ('reserved', (u8, 3)),
196 ])
197 
198 dtypeSta = np.dtype([
199  ('deltype', i32),
200  ('pos', (f32, 3)),
201  ('delta', (f32, 3)),
202  ('hgt', f32),
203  ('stationId', i32),
204 ])
205 
206 dtypeObsD = np.dtype([
207  ('time', dtypeGtime),
208  ('sat', u8),
209  ('rcv', u8),
210  ('SNR', u8),
211  ('LLI', u8),
212  ('code', u8),
213  ('qualL', u8),
214  ('qualP', u8),
215  ('reserved', u8),
216  ('L', f64),
217  ('P', f64),
218  ('D', f32)
219 ])
220 
221 
222 class cDevice:
223  def __init__(self, index, directory, serialNumber, refIns=None):
224  global refLla
226  self.serialNumber = serialNumber
227 
228  self.dtCnkHdr = np.dtype([
229  ('marker', u32),
230  ('version', u16),
231  ('classification', u16),
232  ('name', np.dtype((str, 4))),
233  ('invName', np.dtype((str, 4))),
234  ('dataSize', u32),
235  ('invDataSize', u32),
236  ('grpNum', u32),
237  ('devSerialNum', u32),
238  ('pHandle', u32),
239  ('reserved', u32),
240  ])
241 
242  self.dtCnkSubHdr = np.dtype([
243  ('dHdr', [('id', u32),
244  ('size', u32),
245  ('offset', u32), ]),
246  ('dCount', u32),
247  ])
248 
249  # Data info
250  self.DID_COUNT = 73
251  self.di = [cDataType() for i in range(self.DID_COUNT)]
252 
253  self.di[1].set('devInfo', np.dtype([
254  ('dataSerNum', u32), # Indicates serial order in time
255  ('reserved', u32),
256  ('serialNumber', u32),
257  ('hardwareVer', (u8, 4)),
258  ('firmwareVer', (u8, 4)),
259  ('build', u32),
260  ('commVer', (u8, 4)),
261  ('repoRevision', f32),
262  ('manufacturer', np.dtype((str, 24))),
263  ('buildDate', (u8, 4)),
264  ('buildTime', (u8, 4)),
265  ('addInfo', np.dtype((str, 24))),
266  ]))
267 
268  dtypeImu = np.dtype([
269  ('pqr', (f32, 3)),
270  ('acc', (f32, 3)),
271  ])
272 
273  # 2 'crashInfo'
274 
275  self.di[3].set('preintegratedImu', np.dtype([
276  ('dataSerNum', u32), # Indicates serial order in time
277  ('time', f64),
278  ('theta1', (f32, 3)),
279  ('theta2', (f32, 3)),
280  ('vel1', (f32, 3)),
281  ('vel2', (f32, 3)),
282  ('dt', f32),
283  ]))
284 
285  self.di[4].set('ins1', np.dtype([
286  ('dataSerNum', u32), # Indicates serial order in time
287  ('week', u32),
288  ('tow', f64),
289  ('iStatus', u32),
290  ('hStatus', u32),
291  ('euler', (f32, 3)),
292  ('uvw', (f32, 3)),
293  ('lla', (f64, 3)),
294  ('ned', (f32, 3)),
295  ]))
296 
297  self.di[5].set('ins2', np.dtype([
298  ('dataSerNum', u32), # Indicates serial order in time
299  ('week', u32),
300  ('tow', f64),
301  ('iStatus', u32),
302  ('hStatus', u32),
303  ('q', (f32, 4)),
304  ('uvw', (f32, 3)),
305  ('lla', (f64, 3)),
306  ]))
307 
308  dtypeGpsPos = np.dtype([
309  ('dataSerNum', u32), # Indicates serial order in time
310  ('week', u32),
311  ('timeOfWeekMs', u32),
312  ('status', u32),
313  ('ecef', (f64, 3)),
314  ('lla', (f64, 3)),
315  ('hMSL', f32),
316  ('hAcc', f32),
317  ('vAcc', f32),
318  ('pDop', f32),
319  ('cnoMean', f32),
320  ('towOffset', f64)
321  ])
322 
323  self.di[6].set('gps1UbxPos', dtypeGpsPos)
324 
325  # 7 'config'
326  # 8 'asciiBCastPeriod'
327 
328  dtStartVars = np.dtype([
329  ('lla', (f64, 3)),
330  ('uvw', (f32, 3)),
331  ('q', (f32, 4)),
332  ])
333 
334  self.di[9].set('insMisc', np.dtype([
335  ('dataSerNum', u32), # Indicates serial order in time
336  ('tow', f64),
337  ('towMs', u32),
338  ('x', dtStartVars),
339  ('theta', (f32, 3)),
340  ('ned', (f32, 3)),
341  ('dcm', (f32, 9)),
342  ('pqr', (f32, 3)),
343  ('acc', (f32, 3)),
344  ('mag', (f32, 3)),
345  ('mslBar', f32),
346  ]))
347 
348  self.di[10].set('sysParams', np.dtype([
349  ('dataSerNum', u32), # Indicates serial order in time
350  ('towMs', u32),
351  ('iStatus', u32),
352  ('hStatus', u32),
353  ('imuTemp', f32),
354  ('baroTemp', f32),
355  ('mcuTemp', f32),
356  ('reserved1', f32),
357  ('sampleDtMs', u32),
358  ('insDtMs', u32),
359  ('reserved2', (f32, 4)),
360  ('genFaultcode', u32),
361  ]))
362 
363  # 11 'sysSensors'
364 
365  self.di[12].set('flashConfig', np.dtype([
366  ('dataSerNum', u32), # Indicates serial order in ti
367  ('size', u32),
368  ('checksum', u32),
369  ('key', u32),
370  ('startupSampleDtMs', u32),
371  ('startupNavDtMs', u32),
372  ('ser0BaudRate', u32),
373  ('ser1BaudRate', u32),
374  ('insRotation', (f32, 3)),
375  ('insOffset', (f32, 3)),
376  ('gps1AntOffset', (f32, 3)),
377  ('insDynModel', u32),
378  ('sysCfgBits', u32),
379  ('refLla', (f64, 3)),
380  ('lastLla', (f64, 3)),
381  ('lastLlaTimeOfWeekMs', u32),
382  ('lastLlaWeek', u32),
383  ('lastLlaUpdateDistance', f32),
384  ('ioConfig', u32),
385  ('cBrdConfig', u32),
386  ('gps2AntOffset', (f32, 3)),
387  ('zeroVelRotation', (f32, 3)),
388  ('zeroVelOffset', (f32, 3)),
389  ('magInclination', f32),
390  ('magDeclination', f32),
391  ('gpsTimeSyncPulsePeriodMs', u32),
392  ('startupGPSDtMs', u32),
393  ('RTKCfgBits', u32),
394  ('reserved', u32),
395  ('ser2BaudRate', u32),
396  ]))
397 
398  self.di[13].set('gps1Pos', dtypeGpsPos)
399  self.di[14].set('gps2Pos', dtypeGpsPos)
400 
401  # 15 'gps1Cno'
402  # 16 'gps2Cno'
403  # 17 'gps2Version'
404  # 18 'gps2Version'
405  # 19 'magCal'
406 
407  self.di[20].set('insResources', np.dtype([
408  ('dataSerNum', u32), # Indicates serial order in time
409  ('towMs', u32),
410  ('x_dot', dtStartVars),
411  ('magYawOffset', f32),
412  ]))
413 
414  self.di[21].set('gps1RtkPosRel', np.dtype([
415  ('dataSerNum', u32), # Indicates serial order in time
416  ('timeOfWeekMs', u32 ),
417  ('differentialAge', f32 ),
418  ('arRatio', f32 ),
419  ('vectorToBase', (f32, 3)),
420  ('distanceToBase', f32 ),
421  ('headingToBase', f32 ),
422  ]))
423 
424  self.di[22].set('gps1RtkPosMisc', np.dtype([
425  ('dataSerNum', u32), # Indicates serial order in time
426  ('timeOfWeekMs', u32),
427  ('accuracyPos', (f32, 3)),
428  ('accuracyCov', (f32, 3)),
429  ('arThreshold', f32),
430  ('gDop', f32),
431  ('hDop', f32),
432  ('vDop', f32),
433  ('baseLla', (f64, 3)),
434  ('cycleSlipCount', u32),
435  ('roverGpsObservationCount', u32),
436  ('baseGpsObservationCount', u32),
437  ('roverGlonassObservationCount', u32),
438  ('baseGlonassObservationCount', u32),
439  ('roverGalileoObservationCount', u32),
440  ('baseGalileoObservationCount', u32),
441  ('roverBeidouObservationCount', u32),
442  ('baseBeidouObservationCount', u32),
443  ('roverQzsObservationCount', u32),
444  ('baseQzsObservationCount', u32),
445  ('roverGpsEphemerisCount', u32),
446  ('baseGpsEphemerisCount', u32),
447  ('roverGlonassEphemerisCount', u32),
448  ('baseGlonassEphemerisCount', u32),
449  ('roverGalileoEphemerisCount', u32),
450  ('baseGalileoEphemerisCount', u32),
451  ('roverBeidouEphemerisCount', u32),
452  ('baseBeidouEphemerisCount', u32),
453  ('roverQzsEphemerisCount', u32),
454  ('baseQzsEphemerisCount', u32),
455  ('roverSbasCount', u32),
456  ('baseSbasCount', u32),
457  ('baseAntennaCount', u32),
458  ('ionUtcAlmCount', u32)
459  ]))
460 
461  # 23 'Feature Bits'
462 
463  dtypeSensorsMpuWTemp = np.dtype([
464  ('pqr', (f32, 3)),
465  ('acc', (f32, 3)),
466  ('mag', (f32, 3)),
467  ('temp', f32),
468  ])
469 
470  self.di[24].set('sensorsIs1', np.dtype([
471  ('dataSerNum', u32), # Indicates serial order in time
472  ('mpu', (dtypeSensorsMpuWTemp, 2)),
473  ]))
474 
475  # 25 'Sensor IS2'
476  # 26 'Sensor TC Bias'
477 
478  self.di[27].set('sensorBias', np.dtype([
479  ('dataSerNum', u32), # Indicates serial order in time
480  ('towMs', u32),
481  ('pqr', (f32, 3)),
482  ('acc', (f32, 3)),
483  ('mslBar', f32),
484  ('magI', (f32, 3)),
485  ('magB', (f32, 3)),
486  ]))
487 
488  # 28 'Sensor ADC'
489  # 29 'SCOMP'
490 
491  dtypeGpsVel = np.dtype([
492  ('dataSerNum', u32), # Indicates serial order in time
493  ('timeOfWeekMs', u32),
494  ('velEcef', (f32, 3)),
495  ('sAcc', f32)
496  ])
497 
498  self.di[30].set('gps1Vel', dtypeGpsVel)
499  self.di[31].set('gps2Vel', dtypeGpsVel)
500 
501  # 32 'HDW params'
502  # 33-37 Flash
503  # 38 'RTOS Info'
504 
505  self.di[39].set('debugArray', np.dtype([
506  ('dataSerNum', u32), # Indicates serial order in time
507  ('i', (i32, 9)),
508  ('f', (f32, 9)),
509  ('lf', (f64, 3)),
510  ]))
511 
512  self.di[47].set('insDev1', np.dtype([
513  ('dataSerNum', u32), # Indicates serial order in time
514  ('week', u32),
515  ('tow', f64),
516  ('iStatus', u32),
517  ('hStatus', u32),
518  ('euler', (f32, 3)),
519  ('uvw', (f32, 3)),
520  ('lla', (f64, 3)),
521  ('ned', (f32, 3)),
522  ('eulerErr', (f32, 3)),
523  ('uvwErr', (f32, 3)),
524  ('nedErr', (f32, 3)),
525  ]))
526 
527  self.di[48].set('ekfStates', np.dtype([
528  ('dataSerNum', u32), # Indicates serial order in time
529  ('time', f64),
530  ('qe2b', (f32, 4)),
531  ('ve', (f32, 3)),
532  ('ecef', (f64, 3)),
533  ('biasPqr', (f32, 3)),
534  ('biasAcc', (f32, 3)),
535  ('biasBaro', f32),
536  ('magDec', f32),
537  ('magInc', f32),
538  ]))
539 
540  # 49 'EKF Covariance'
541  # 50 'EKF Innovations'
542  # 51 'EKF Innovations Var'
543 
544  self.di[52].set('magnetometer1', np.dtype([
545  ('dataSerNum', u32), # Indicates serial order in time
546  ('time', f64),
547  ('mag', (f32, 3)),
548  ]))
549 
550  self.di[53].set('barometer', np.dtype([
551  ('dataSerNum', u32), # Indicates serial order in time
552  ('time', f64),
553  ('bar', f32),
554  ('mslBar', f32),
555  ('barTemp', f32),
556  ('humidity', f32),
557  ]))
558 
559  self.di[54].set('gps1RtkPos', dtypeGpsPos)
560 
561  self.di[55].set('gps1RtkCmpRel', np.dtype([
562  ('dataSerNum', u32), # Indicates serial order in time
563  ('timeOfWeekMs', u32 ),
564  ('differentialAge', f32 ),
565  ('arRatio', f32 ),
566  ('vectorToBase', (f32, 3)),
567  ('distanceToBase', f32 ),
568  ('headingToBase', f32 ),
569  ]))
570 
571  self.di[56].set('gpsVersion', np.dtype([
572  ('dataSerNum', u32), # Indicates serial order in time
573  ('swVersion', np.dtype((str, 30))),
574  ('hwVersion', np.dtype((str, 10))),
575  ('extension', np.dtype((str, 30))),
576  ('reserved', (u32, 2)),
577  ]))
578 
579  # 57 'Communications Loopback'
580 
581  self.di[58].set('dualImu', np.dtype([
582  ('dataSerNum', u32), # Indicates serial order in time
583  ('time', f64),
584  ('I', (dtypeImu, 2)),
585  ]))
586 
587  self.di[59].set('inl2MagObs', np.dtype([
588  ('dataSerNum', u32), # Indicates serial order in time
589  ('towMs', u32),
590  ('Ncal_samples', u32),
591  ('ready', u32),
592  ('calibrated', u32),
593  ('auto-recal', u32),
594  ('outlier', u32),
595  ('magHeading', f32),
596  ('insHeading', f32),
597  ('magInsHdgDelta', f32),
598  ('nis', f32),
599  ('nis_threshold', f32),
600  ('Wcal', (f32, 9)),
601  ('activeCalSet', u32),
602  ('magHeadingOffset', f32),
603  ]))
604 
605  # 60 - Raw GPS Ephemeris and Observation from Base
606  self.di[60].set('GPSBaseRaw', dtypeGpsRaw)
607 
608  # 61 - RTK Options
609  # 62 - Internal User page Info
610  # 63 - Manufacturing Info
611  # 64 - Self Test
612  # 65 - INS - 3 - ECEF Position & Quaternions NED
613  # 66 - INS - 4 - ECEF Position & Quaternions ECEF
614 
615  self.di[67].set('inl2Variance', np.dtype([
616  ('dataSerNum', u32), # Indicates serial order in time
617  ('towMs', u32),
618  ('PxyxNED', (f32, 3)),
619  ('PvelNED', (f32, 3)),
620  ('PattNED', (f32, 3)),
621  ('PABias', (f32, 3)),
622  ('PWBias', (f32, 3)),
623  ('PBaroBias', f32),
624  ('PDeclination', f32),
625  ]))
626 
627  # 68 - Strobe input time
628 
629  self.di[69].set('GPS1Raw', dtypeGpsRaw)
630  self.di[70].set('GPS2Raw', dtypeGpsRaw)
631 
632  self.di[91].set('gps1RtkCmpMisc', np.dtype([
633  ('dataSerNum', u32), # Indicates serial order in time
634  ('timeOfWeekMs', u32),
635  ('accuracyPos', (f32, 3)),
636  ('accuracyCov', (f32, 3)),
637  ('arThreshold', f32),
638  ('gDop', f32),
639  ('hDop', f32),
640  ('vDop', f32),
641  ('baseLla', (f64, 3)),
642  ('cycleSlipCount', u32),
643  ('roverGpsObservationCount', u32),
644  ('baseGpsObservationCount', u32),
645  ('roverGlonassObservationCount', u32),
646  ('baseGlonassObservationCount', u32),
647  ('roverGalileoObservationCount', u32),
648  ('baseGalileoObservationCount', u32),
649  ('roverBeidouObservationCount', u32),
650  ('baseBeidouObservationCount', u32),
651  ('roverQzsObservationCount', u32),
652  ('baseQzsObservationCount', u32),
653  ('roverGpsEphemerisCount', u32),
654  ('baseGpsEphemerisCount', u32),
655  ('roverGlonassEphemerisCount', u32),
656  ('baseGlonassEphemerisCount', u32),
657  ('roverGalileoEphemerisCount', u32),
658  ('baseGalileoEphemerisCount', u32),
659  ('roverBeidouEphemerisCount', u32),
660  ('baseBeidouEphemerisCount', u32),
661  ('roverQzsEphemerisCount', u32),
662  ('baseQzsEphemerisCount', u32),
663  ('roverSbasCount', u32),
664  ('baseSbasCount', u32),
665  ('baseAntennaCount', u32),
666  ('ionUtcAlmCount', u32)
667  ]))
668 
669  # Profiling
670  timeStart = systime.time()
671  self.loadTime = 0
672  self.unknownId = {}
673  self.directory = directory
674  self.serialNumber = serialNumber
675  self.rdat = {} # Raw data in python list format
676  self.data = {} # data in numpy format
677  self.index = index # index in all serial numbers
678  self.refLla = refLla
679  # self.version = []
680  # self.units = []
681 
682  if refIns is not None:
683  print("#%2d Opening: Ref INS %s" % (index, directory))
684 
685  fileMask = "LOG_REF_INS*.dat"
686  # Use first file in directory if not defined
687  else:
688  print("#%2d Opening: %s %s" % (index, serialNumber, directory))
689 
690  fileMask = "LOG_" + serialNumber + "*.sdat"
691 
692  if not os.path.isdir(directory):
693  print("Directory doesn't exist!")
694  sys.exit()
695  os.chdir(directory)
696  self.fileNames = glob.glob(fileMask)
697 
698  if not self.fileNames:
699  # print(" ***** Files not found! Check directory name and serial number. ***** ")
700  raise Exception('Load Error: .sdat files not found.')
701 
702  self.parse()
703  self.clean()
704 
705  # Profiling
706  self.loadTime = systime.time() - timeStart
707  print("Load time: %.2fs" % (self.loadTime))
708 
709  def clean(self):
710  for key, item in self.data.iteritems():
711  if not isinstance(item, np.ndarray):
712  continue
713 
714  for field in ['towMs', 'timeOfWeekMs', 'tow']:
715  if field in item.dtype.names:
716  if (np.diff(item[field].astype(np.int64)) < 0).any():
717  idx = np.argmin(np.diff(item[field].astype(np.int64)))
718  print("\033[93m" + "Time went backwards in ", key, r"!!!, removing all data " + ("before" if idx < len(item[field])/2.0 else "after") + "\033[0m")
719  if idx < len(item[field])/2.0:
720  self.data[key] = item[idx +1:]
721  else:
722  self.data[key] = item[:idx]
723  ms_multiplier = 1000.0 if 'Ms' in field else 1.0
724  if (np.diff(item[field]) > 3600 * ms_multiplier).any():
725  print("\033[93m" + "greater than 1 minute gap in ", key, " data, assuming GPS fix was acquired during data set, and chopping data"+ "\033[0m")
726  idx = np.argmax(np.diff(item[field])) + 1
727  self.data[key] = item[idx:]
728 
729  def parse(self):
730  self.curTime = np.r_[0]
731  self.raw_gps_keys = []
732 
733  # Iterate over files to concatenate data
734  self.fileNames.sort()
735  for fileName in self.fileNames:
736  print(fileName)
737  self.__parseFile(fileName)
738  # set the raw GPS dictionary as a datatype
739  for name in self.raw_gps_keys:
740  for key, item in self.data[name].iteritems():
741  self.data[name][key] = np.array(item)
742  if 'ins2' in self.data.keys():
743  setGpsWeek(self.data['ins2']['week'][0])
744 
745 
746  def parse_raw_gps(self, f, did, dati, sHdr, cHdr):
747 
748  valid_types = [1, 2, 3, 4, 5, 6, 123]
749  valid_receiver_indexes = [1, 2, 3, 4]
750 
751  if dati.name not in self.raw_gps_keys:
752  self.raw_gps_keys.append(dati.name)
753 
754  buf = np.fromfile(f, np.uint8, count=cHdr['dataSize'])
755  for i in range(sHdr['dCount']):
756  pointer = 0
757  hdr_size = np.dtype(dtypeGpsRaw).itemsize
758  gps_raw_header = buf[pointer:pointer + hdr_size].view(dtypeGpsRaw)
759  pointer += hdr_size
760 
761  # Pull in the header data
762  try:
763  type = gps_raw_header['type'][0]
764  count = gps_raw_header['count'][0]
765  receiverIndex = gps_raw_header['receiverIndex'][0]
766  assert (type in valid_types and receiverIndex in valid_receiver_indexes)
767  if dati.name not in self.data.keys():
768  self.data[dati.name] = {'dataSerNum': [gps_raw_header['dataSerNum'][0]],
769  'receiverIndex': [receiverIndex],
770  'type': [type],
771  'count': [count],
772  'corrupt_data': 0}
773  else:
774  self.data[dati.name]['dataSerNum'].append(gps_raw_header['dataSerNum'][0])
775  self.data[dati.name]['receiverIndex'].append(gps_raw_header['receiverIndex'][0])
776  self.data[dati.name]['type'].append(type)
777  self.data[dati.name]['count'].append(count)
778  except:
779  print("invalid raw gps header: type=", type, "count = ", count, "receiverIndex = ", receiverIndex)
780  self.data[dati.name]['corrupt_data'] += 1
781  continue
782 
783  if type == RAW_DATA_OBS:
784  try:
785  bytes_in_payload = np.dtype(dtypeObsD).itemsize * count
786  obs = buf[pointer:pointer + bytes_in_payload].view(dtypeObsD)
787  pointer += bytes_in_payload
788  if 'obs' not in self.data[dati.name]:
789  self.data[dati.name]['obs'] = np.rec.array(obs)
790  else:
791  self.data[dati.name]['obs'] = np.hstack((self.data[dati.name]['obs'], np.rec.array(obs)))
792  except:
793  print("badly formed raw gps data - DID: %d type: Obs, count: %d, actual: %f" %
794  (did, count, (len(buf) - 8) / (float(np.dtype(dtypeObsD).itemsize))))
795  self.data[dati.name]['corrupt_data'] += 1
796  continue
797 
798  def __parseFile(self, filename):
799  with open(filename, 'rb') as f:
800 
801  while 1:
802  # Read and validate chunk header
803  cHdr = np.fromfile(f, dtype=self.dtCnkHdr, count=1)
804 
805  count = cHdr['dataSize']
806 
807  if np.shape(cHdr)[0] == 0 or cHdr['marker'][0] != 0xFC05EA32:
808  # print( "Done parsing data!" )
809  break
810 
811  # Read chunk sub header
812  sHdr = np.fromfile(f, dtype=self.dtCnkSubHdr, count=1)
813 
814  # Find ID
815  did = sHdr['dHdr']['id'][0]
816  dsize = sHdr['dHdr']['size'][0]
817  # if did == 6:
818  # print( "DID: ",did )
819  if did >= self.DID_COUNT:
820  if did not in self.unknownDidDisplayed.keys():
821  self.unknownDidDisplayed[did] = True
822  print("==============================================================================")
823  print(" - ERROR - Data ID " + str(did) + " out of range " + str(
824  self.DID_COUNT) + ". Please add missing DID definitions to ISToolsDataSorted.pyx.")
825  print("==============================================================================")
826  did = 0
827  self.unknownDidDisplayed[did] = True
828  systime.sleep(0.5)
829 
830  dati = self.di[did]
831 
832  if dati.dtype:
833  if dsize == (dati.dtype.itemsize - 4):
834  # Known data type
835  # print("Found id: ", did)
836  cDat = np.fromfile(f, dati.dtype, count=sHdr['dCount'])
837 
838  if dati.name in self.data.keys():
839  # Append
840  # self.data[dati.name].append(cDat)
841  self.data[dati.name] = np.concatenate([self.data[dati.name], cDat])
842  else:
843  # Create
844  self.data[dati.name] = cDat
845 
846  # Handle Raw data differently (because it changes sizes and carries multiple messages)
847  elif dati.dtype == dtypeGpsRaw:
848  self.parse_raw_gps(f, did, dati, sHdr, cHdr)
849 
850  else:
851  # Mismatched data size
852  print("==============================================================================")
853  print(" - ERROR - Data ID", did, "(" + dati.name + ") mismatched size. Read", dsize, "expected", dati.dtype.itemsize - 4)
854  print("==============================================================================")
855  # systime.sleep(0.5)
856  # sys.exit()
857  cDat = np.fromfile(f, np.uint8, count=cHdr['dataSize'][0])
858  else:
859  # Unknown data type
860  if did not in self.unknownDidDisplayed.keys():
861  self.unknownDidDisplayed[did] = True
862  print("Undefined DID: ", did)
863  cDat = np.fromfile(f, np.uint8, count=cHdr['dataSize'][0])
864 
865 
866 class cDevices:
867  def __init__(self):
868  self.devices = []
869  self.loadTime = 0 # Profiling
870 
871  # Load data to be viewed. If the "selection.txt" file is found, the line by line contents
872  # of selection.txt specify an additional subdirectory and list of serial numbers to be loaded.
873  # If serial numbers are not specified, either in selection.txt or in the loadData() parameter,
874  # then all serial numbers and files are read.
875  # directory Directory data is loaded from. If not specified, the current directory is used. If no data found, use latest data sub directory.
876  # serialNumbers Device serial numbers to load. If not specified, all serial numbers and files found are loaded.
877  # startDev First index of found devices (serial numbers) to load.
878  # devCount Number of devices (serial numbers) to load.
879  def loadData(self, directory=None, serialNumbers=None, refIns=None, startDev=0, devCount=-1):
880 
881  # Profiling
882  self.loadTime = 0
883  timeLoadStart = systime.time()
884 
885  # We don't support reference INS right now
886  if refIns != None:
887  raise Exception('refIns not supported right now.')
888 
889  if directory is not None:
890  # Convert backslash to forward slash (Windows to Linux)
891  directory = directory.replace('\\', '/')
892 
893  if '~' in directory:
894  pass
895 
896  # Automatically open logs specified in "selection.txt"
897  os.chdir(directory)
898 
899  # Use selection file if it exists
900  selectionFileName = 'selection.txt'
901  if os.path.exists(selectionFileName):
902  with open(selectionFileName) as f:
903  lines = f.read().splitlines()
904 
905  # Convert backslash to forward slash (Windows to Linux)
906  directory += lines[0].replace('\\', '/')
907 
908  # Read serial numbers from selection.txt
909  serialNumbers = []
910  for serNum in lines[1:]:
911  # Stop if we find a blank line
912  if serNum == '':
913  break
914  serialNumbers.append(serNum)
915 
916  # If current directory has NO data, use newest sub directory containing data.
917  files = os.listdir(directory)
918  if not any(".sdat" in s for s in files):
919  dirName = None
920  dirTime = 0
921  for fname in files:
922  # Has data log directory name format
923  if len(fname) >= 15 and fname[0:2] == '20' and fname[8:9] == '_':
924  dTime = int(fname[0:8] + fname[9:15])
925  # Is latest
926  if dTime > dirTime:
927  dirTime = dTime
928  dirName = fname
929 
930  if dirName != None:
931  directory += dirName
932 
933  # Print directory
934  print("Loading Data: ", directory)
935 
936  # Add all devices in directory
937  if serialNumbers is None or serialNumbers == []:
938  # Find list of serial numbers from files in directory
939  files = os.listdir(directory)
940  serNums = []
941  for str in files:
942  if str.find('.sdat') != -1:
943  str = str.replace('.sdat', '')
944  if str.find('LOG_SN') != -1:
945  str = str[4:11]
946  if not str in serNums:
947  serNums.append(str)
948  elif str.find('LOG_PR') != -1:
949  str = str.replace('LOG_', '')
950  str = str[:str.find('_')]
951  if not str in serNums:
952  serNums.append(str)
953  serialNumbers = serNums
954 
955  count = len(serialNumbers)
956 
957  # Validate serial numbers
958  if count <= 0:
959  raise Exception('Load Error: .sdat files not found.')
960 
961  # Find size and last index
962  if devCount > 0 and devCount < count:
963  count = devCount
964  endIndex = min(startDev + count, len(serialNumbers))
965 
966  # print ("Start Index: ", startDev, " End Index: ", endIndex)
967 
968  # Add devices
969  for i in range(startDev, endIndex):
970  device = cDevice(i, directory, serialNumbers[i], refIns)
971  self.devices.append(device)
972 
973  # Profiling
974  self.loadTime = systime.time() - timeLoadStart
975  print("Total load time: %.2fs" % (self.loadTime))
976 
977 
978 def gpsTimeToUTC(gpsWeek, gpsSOW, leapSecs=14):
979  global showUtcTime
980  if showUtcTime == 0:
981  return gpsSOW
982 
983  # Search for a valid GPS week
984  size = np.shape(gpsWeek)
985  if size and size[0] > 1:
986  # if gpsWeek[0] == 0:
987  # gpsWeek = gpsWeek[-1]
988  # Use the largest value for the week
989  gpsWeek = np.max(gpsWeek)
990 
991  if gpsWeek == 0:
992  return gpsSOW
993 
994  secsInWeek = 604800
995  # secsInDay = 86400
996  gpsEpoch = (1980, 1, 6, 0, 0, 0) # (year, month, day, hh, mm, ss)
997  # secFract = gpsSOW % 1
998 
999  epochTuple = gpsEpoch + (-1, -1, 0)
1000  t0 = systime.mktime(epochTuple) - systime.timezone # mktime is localtime, correct for UTC
1001  tdiff = (gpsWeek * secsInWeek) + gpsSOW - leapSecs
1002  t = t0 + tdiff
1003  return t
1004 
1005 
1007  sizes = np.array([a.itemsize for a in arrays])
1008  offsets = np.r_[0, sizes.cumsum()]
1009  n = len(arrays[0])
1010  joint = np.empty((n, offsets[-1]), dtype=np.uint8)
1011  for a, size, offset in zip(arrays, sizes, offsets):
1012  joint[:, offset:offset + size] = a.view(np.uint8).reshape(n, size)
1013  dtype = sum((a.dtype.descr for a in arrays), [])
1014  return joint.ravel().view(dtype)
1015 
1016 
1017 # Join list of structured numpy arrays into one
1019  newdtype = sum((a.dtype.descr for a in arrays), [])
1020  newrecarray = np.empty(len(arrays[0]), dtype=newdtype)
1021  for a in arrays:
1022  for name in a.dtype.names:
1023  newrecarray[name] = a[name]
1024  return newrecarray
1025 
1026 
1027 class cSIMPLE:
1028  def __init__(self, _v):
1029  self.v = _v
1030 
1031 
1032 class cIMU:
1033  def __init__(self, _v):
1034  global gpsWeek
1035  self.v = _v
1036  self.__flt = cObj()
1037  self.__flt.pqr = None
1038  self.__flt.acc = None
1039  self.__flt.pqrNoBias = None
1040  self.__flt.accNoBias = None
1041  self.__flt.barNoBias = None
1042  self.cornerFreqHz = 60
1043  # self.cornerFreqHz = 30
1044  # self.cornerFreqHz = 15
1045 
1046  self.time = gpsTimeToUTC(gpsWeek, self.v['time'])
1047 
1048  self.i = [cObj(), cObj()]
1049  for j in range(0, 2):
1050  self.i[j].pqr = None
1051  self.i[j].acc = None
1052 
1053  # Dual IMU
1054  if 'I' in self.v.dtype.names:
1055  self.i[0].pqr = self.v['I']['pqr'][:, 0, :]
1056  self.i[1].pqr = self.v['I']['pqr'][:, 1, :]
1057  self.i[0].acc = self.v['I']['acc'][:, 0, :]
1058  self.i[1].acc = self.v['I']['acc'][:, 1, :]
1059 
1060  # Preintegrated IMU
1061  if 'theta1' in self.v.dtype.names and 'theta2' in self.v.dtype.names:
1062  divDt = 1.0 / self.v['dt']
1063  self.i[0].pqr = self.v['theta1']
1064  self.i[1].pqr = self.v['theta2']
1065  self.i[0].acc = self.v['vel1']
1066  self.i[1].acc = self.v['vel2']
1067 
1068  for i in range(0, 2):
1069  for a in range(0, 3):
1070  self.i[i].pqr[:, a] *= divDt
1071  self.i[i].acc[:, a] *= divDt
1072 
1073  def fltAcc(self):
1074  if self.__flt.acc is None:
1075  self.__flt.acc = ft.lpfNoDelay(self.v['acc'], self.cornerFreqHz, time=self.v['time'])
1076  return self.__flt.acc
1077 
1078  def fltPqr(self):
1079  if self.__flt.pqr is None:
1080  self.__flt.pqr = ft.lpfNoDelay(self.v['pqr'], self.cornerFreqHz, time=self.v['time'])
1081  return self.__flt.pqr
1082 
1083  def fltPqrNoBias(self):
1084  if 'pqrNoBias' in self.v.dtype.names and self.__flt.pqrNoBias is None:
1085  self.__flt.pqrNoBias = ft.lpfNoDelay(self.v['pqrNoBias'], self.cornerFreqHz, time=self.v['time'])
1086  return self.__flt.pqrNoBias
1087 
1088  def fltAccNoBias(self):
1089  if 'accNoBias' in self.v.dtype.names and self.__flt.accNoBias is None:
1090  self.__flt.accNoBias = ft.lpfNoDelay(self.v['accNoBias'], self.cornerFreqHz, time=self.v['time'])
1091  return self.__flt.accNoBias
1092 
1093  def fltBarNoBias(self):
1094  if 'mslBarNoBias' in self.v.dtype.names and self.__flt.barNoBias is None:
1095  self.__flt.mslBarNoBias = ft.lpfNoDelay(self.v['mslBarNoBias'], self.cornerFreqHz, time=self.v['time'])
1096  return self.__flt.mslBarNoBias
1097 
1098 
1099 # self.mslBar = ft.smooth(self.v['mslBar']+72, delta=200)
1100 # self.mslBarDot = ft.derivative(self.v['time'], self.mslBar, delta=10)
1101 # self.mslBarDotLpf = ft.lpfNoDelay(self.mslBarDot, cornerFreqHz=0.5, time = self.v['time'])
1102 
1103 class cINS:
1104  def __init__(self, _v):
1105  # self.v = _v
1106  self.v = _v[:-1] # Throw out last element
1107  self.__velNED = None
1108  self.__course = None
1109  self.__ecef = None
1110  self.__ned = None
1111  self.__istatus = None
1112  self.__hstatus = None
1113  self.__size = np.shape(self.v['tow'])[0]
1114  self.time = gpsTimeToUTC(self.v['week'], self.v['tow'])
1115 
1116  if not 'euler' in self.v.dtype.names and 'q' in self.v.dtype.names:
1117  # self.v['euler'] = pose.quat2eulerArray(self.v['q'])
1118  # self.euler = pose.quat2eulerArray(self.v['q'])
1119  dtypeeuler = np.dtype([('euler', (np.float, 3))])
1120  e = pose.quat2eulerArray(self.v['q'])
1121  euler = np.ndarray(np.shape(e)[0], dtype=dtypeeuler, buffer=e)
1122  self.v = join_struct_arrays2([self.v, euler])
1123 
1124  if not 'q' in self.v.dtype.names and 'euler' in self.v.dtype.names:
1125  # self.v['q'] = pose.euler2quatArray(self.v['euler'])
1126  # self.q = pose.euler2quatArray(self.v['euler'])
1127  dtypeq = np.dtype([('q', (np.float, 4))])
1128  q = pose.euler2quatArray(self.v['euler'])
1129  quat = np.ndarray(np.shape(q)[0], dtype=dtypeq, buffer=q)
1130  self.v = join_struct_arrays2([self.v, quat])
1131 
1132  # Velocity vector in inertial frame
1133  def velNed(self):
1134  if self.__velNED is None:
1135  self.__velNED = np.zeros(np.shape(self.v['uvw']))
1136 
1137  for i in range(0, self.__size):
1138  DCM = pose.eulerDCM(self.v['euler'][i, :])
1139  velNED = np.dot(DCM.T, self.v['uvw'][i, :]) # body to inertial frame
1140  self.__velNED[i, :] = velNED
1141 
1142  return self.__velNED
1143 
1144  def course(self):
1145  if self.__course is None:
1146  self.__course = np.arctan2(self.velNED[:, 1], self.velNED[:, 0])
1147  return self.__course
1148 
1149  def ned(self):
1150  global refLla
1151  if self.__ned is None:
1152  self.__ned = pose.lla2ned(refLla, self.v['lla'])
1153  return self.__ned
1154 
1155  def ecef(self):
1156  if self.__ecef is None:
1157  self.__ecef = pose.lla2ecef(self.v['lla'])
1158  return self.__ecef
1159 
1160  def set(self, time):
1161  self.time = time
1162 
1163  def speed2D(self):
1164  return np.sqrt(np.square(self.v['uvw'][:, 0]) +
1165  np.square(self.v['uvw'][:, 1]))
1166 
1167  def speed3D(self):
1168  return np.sqrt(np.square(self.v['uvw'][:, 0]) +
1169  np.square(self.v['uvw'][:, 1]) +
1170  np.square(self.v['uvw'][:, 2]))
1171 
1172  def iStatus(self):
1173  if self.__istatus is None:
1174  self.__istatus = insStatus(self.v['iStatus'])
1175  return self.__istatus
1176 
1177  def hStatus(self):
1178  if self.__hstatus is None:
1179  self.__hstatus = hdwStatus(self.v['hStatus'])
1180  return self.__hstatus
1181 
1182 
1183 class cRIMU:
1184  def __init__(self, _v,
1185  accBias=np.r_[0, 0, 0],
1186  pqrBias=np.r_[0, 0, 0],
1187  rotate=np.r_[0, 0, 0]):
1188  self.v = _v
1189  self.cornerFreqHz = 30
1190  self.__flt = cObj()
1191  self.__flt.pqr = None
1192  self.__flt.acc = None
1193 
1194  if accBias[0] != 0 or accBias[1] != 0 or accBias[2] != 0:
1195  self.v['acc'] += accBias
1196 
1197  if pqrBias[0] != 0 or pqrBias[1] != 0 or pqrBias[2] != 0:
1198  self.v['pqr'] += pqrBias
1199 
1200  if rotate[0] != 0 or rotate[1] != 0 or rotate[2] != 0:
1201  self.v['acc'] = pose.vectorRotateInertialToBody2(self.v['acc'], rotate)
1202  self.v['pqr'] = pose.vectorRotateInertialToBody2(self.v['pqr'], rotate)
1203 
1204  def fltPqr(self):
1205  if self.__flt.pqr is None:
1206  self.__flt.pqr = ft.lpfNoDelay(self.v['pqr'], self.cornerFreqHz, time=self.v['time'])
1207  return self.__flt.pqr
1208 
1209  def fltAcc(self):
1210  if self.__flt.acc is None:
1211  self.__flt.acc = ft.lpfNoDelay(self.v['acc'], self.cornerFreqHz, time=self.v['time'])
1212  return self.__flt.acc
1213 
1214 
1215 class cRINS:
1216  def __init__(self, _v, rotate=np.r_[0, 0, 0]):
1217  global refLla
1218  self.v = _v
1219 
1220  self.__ned = None
1221  self.__nedDotDot = None
1222  self.__uvw = None
1223  self.__rotate = rotate
1224 
1225  # self.v['nedDot'] = ft.smooth(self.v['nedDot'], delta=10)
1226  # self.v['euler'] = ft.smooth(self.v['euler'], delta=10)
1227  if self.__rotate[0] != 0 or self.__rotate[1] != 0 or self.__rotate[2] != 0:
1228  self.v['euler'][:, 0] += self.__rotate[0]
1229  self.v['euler'][:, 1] += self.__rotate[1]
1230  self.v['euler'][:, 2] += self.__rotate[2]
1231 
1232  def ned(self):
1233  if self.__ned is None:
1234  self.__ned = pose.lla2ned(refLla, self.v['lla'])
1235  return self.__ned
1236 
1237  def nedDotDot(self):
1238  if self.__nedDotDot is None:
1239  self.__nedDotDot = ft.derivative(self.v['time'], self.v['nedDot'], delta=2)
1240  self.__nedDotDot[:, 2] -= 9.80665
1241  cornerFreqHz = 10
1242  self.__nedDotDot = ft.lpfNoDelay(self.__nedDotDot, cornerFreqHz, time=self.v['time'])
1243  return self.__nedDotDot
1244 
1245  def uvw(self):
1246  if self.__uvw is None:
1247  self.__uvw = pose.vectorRotateInertialToBody(self.v['nedDot'], self.v['euler'])
1248  if self.__rotate[0] != 0 or self.__rotate[1] != 0 or self.__rotate[2] != 0:
1249  self.uvw = pose.vectorRotateInertialToBody2(self.uvw, self.__rotate)
1250  return self.__uvw
1251 
1252 
1253 class cRGPS:
1254  def __init__(self, _v):
1255  global refLla
1256 
1257  self.v = _v
1258  self.__ned = None
1259  self.__acc = cObj()
1260  self.__acc.ned = None
1261 
1262  def ned(self):
1263  if self.__ned is None:
1264  self.__ned = pose.lla2ned(refLla, self.v['lla'])
1265  return self.__ned
1266 
1267  def accNed(self):
1268  if self.__acc.ned is None:
1269  # Create Accelerations from GPS velocities
1270  # self.__acc.ned = ft.meanDerivative(self.v['time'], self.v['vel.ned'], 5, 3)
1271  self.__acc.ned = ft.meanDerivative(self.v['time'], self.v['vel.ned'], 2, 2)
1272  return self.__acc.ned
1273 
1274 
1275 class cGPS:
1276  def __init__(self, _v):
1277  global refLla
1278  global refLla
1279  global gpsWeek
1280  self.v = _v
1281 
1282  self.time = gpsTimeToUTC(self.v['week'], (_v['timeOfWeekMs'] * 0.001))
1283  self.ned = pose.lla2ned(refLla, _v['lla'])
1284 
1285  self.satsUsed = (_v['status'] >> 0) & 0xFF
1286  self.fixType = (_v['status'] >> 8) & 0xFF
1287  self.rtkMode = (_v['status'] >> 20) & 0x01
1288 
1289  # self.vectorToBase = _v['vectorToBase']
1290  # self.distanceToBase = _v['distanceToBase']
1291 
1292 
1293 class cGPSRaw:
1294  def __init__(self, _v):
1295  self.count = _v['count']
1296  self.type = _v['type']
1297  self.receiverIndex = _v['receiverIndex']
1298  self.corruptCount = int(_v['corrupt_data'])
1299 
1300  if 'obs' in _v.keys():
1301  self.obs = _v['obs']
1302  try:
1303  self.obstime = np.array([np.datetime64(int(np.round((t['time'] + t['sec'])*1000000)), 'us') for t in _v['obs']['time']])
1304  except OverflowError as e:
1305  debug = 1
1306 
1307 
1308 class cRTKMisc:
1309  def __init__(self, _v):
1310  self.v = _v
1311  self.time = gpsTimeToUTC(_v['week'], (_v['timeOfWeekMs'] * 0.001))
1312 
1313  self.slipCounter = _v['cycleSlipCount']
1314  self.arThreshold = _v['arThreshold']
1315  self.baseLla = _v['baseLla']
1316  self.heading = _v['rtkCompassHeading']
1317 
1318 
1319 class cGpsVel:
1320  def __init__(self, _v):
1321  global gpsWeek
1322  self.v = _v
1323 
1324  def acc(self):
1325  if self.__acc is None:
1326  self.__acc = cObj()
1327  self.__acc.time = self.time
1328  # self.__acc.ned = ft.meanDerivative(self.vel.time, self.v['ned'], 5, 3)
1329  self.__acc.ned = ft.meanDerivative(self.time, self.v['ned'], 2, 2)
1330  return self.__acc
1331 
1332 
1333 class cGpsAcc:
1334  def __init__(self, _v):
1335  self.v = _v
1336  # self.time = _v['timeMs'] * 0.001
1337  self.time = gpsTimeToUTC(self.v['week'], (_v['timeOfWeekMs'] * 0.001))
1338 
1339 
1340 class cBias:
1341  def __init__(self, _v):
1342  global gpsWeek
1343  self.v = _v
1344  # self.time = _v['timeMs'] * 0.001
1345  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1346 
1347 
1348 class cInsRes:
1349  def __init__(self, _v):
1350  global gpsWeek
1351  self.v = _v
1352  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1353 
1354 
1355 class cDevInfo:
1356  def __init__(self, _v):
1357  self.v = _v
1358 
1359 
1361  def __init__(self, _v):
1362  global gpsWeek
1363  self.v = _v
1364  self.__istatus = None
1365  self.__hstatus = None
1366 
1367  if 'tow' in _v.dtype.names:
1368  # self.time = _v['time']
1369  self.time = gpsTimeToUTC(gpsWeek, _v['tow'])
1370  if 'towMs' in _v.dtype.names:
1371  # self.time = (_v['timeMs']) * 0.001
1372  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1373 
1374  def iStatus(self):
1375  if self.__istatus is None:
1376  self.__istatus = insStatus(self.v['iStatus'])
1377  return self.__istatus
1378 
1379  def hStatus(self):
1380  if self.__istatus is None:
1381  self.__hstatus = hdwStatus(self.v['hStatus'])
1382  return self.__hstatus
1383 
1384 
1386  def __init__(self, _v):
1387  global refLla
1388  self.v = _v
1389  self.accNed = cObj()
1390  self.velNed = cObj()
1391  self.lla = cObj()
1392  self.uvw = cObj()
1393 
1394  # self.time = _v['timeMs'] * 0.001
1395  # self.accNed.time = _v['accNed.timeMs'] * 0.001
1396  # self.velNed.time = _v['velNed.timeMs'] * 0.001
1397  # self.lla.time = _v['lla.timeMs'] * 0.001
1398  # self.uvw.time = _v['uvw.timeMs'] * 0.001
1399  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1400  self.accNed.time = gpsTimeToUTC(gpsWeek, (_v['accNed']['towMs'] * 0.001))
1401  self.velNed.time = gpsTimeToUTC(gpsWeek, (_v['velNed']['towMs'] * 0.001))
1402  self.lla.time = gpsTimeToUTC(gpsWeek, (_v['lla']['towMs'] * 0.001))
1403 
1404  self.accNed.refHdg = np.arctan2(self.v['accNed']['ref'][:, 1], self.v['accNed']['ref'][:, 0])
1405  self.accNed.insHdg = np.arctan2(self.v['accNed']['ins'][:, 1], self.v['accNed']['ins'][:, 0])
1406 
1407  self.lla.refNed = pose.lla2ned(refLla, _v['lla']['ref'])
1408  self.lla.insNed = pose.lla2ned(refLla, _v['lla']['ins'])
1409 
1410 
1411 # self.v['mslBar'] += 86;
1412 
1414  def __init__(self, _v):
1415  global gpsWeek
1416  self.v = _v
1417 
1418  # self.time = _v['timeMs'] * 0.001
1419  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1420  if 'magTowMs' in _v.dtype.names:
1421  # self.magTime = (_v['magTowMs']) * 0.001
1422  self.magTime = gpsTimeToUTC(gpsWeek, (_v['magTowMs'] * 0.001))
1423 
1424 
1425 def lla2kml(time, lla, serialNumber, kmlFileName="log.kml", **kwargs):
1426  kml = simplekml.Kml()
1427 
1428  color = kwargs.pop('color', simplekml.Color.yellow)
1429  altitudeMode = kwargs.pop('altitudeMode', simplekml.constants.AltitudeMode.absolute)
1430  timeStep = kwargs.pop('timeStep', 0)
1431 
1432  latLon = []
1433  tNext = 0
1434  lNext = 0
1435  for i in range(0, np.shape(lla)[0]):
1436  latLon.append((lla[i, 1], lla[i, 0], lla[i, 2]))
1437 
1438  # Add timestamp
1439  if timeStep:
1440  # if timeStep == -1:
1441  # pt = kml.newpoint(name="%.1f" % time[i], coords=[latLon[i]])
1442  # pt.style.iconstyle.color = color
1443  # pt.style.iconstyle.scale = 0.5
1444  # pt.style.labelstyle.scale = 0.7
1445  if time[i] >= tNext:
1446  tNext += timeStep
1447  # round(tNext, timeStep)
1448  if time[i] >= lNext:
1449  if timeStep > lNext:
1450  lNext += timeStep
1451  else:
1452  lNext += 1
1453  pt = kml.newpoint(name="%.2f" % time[i], coords=[latLon[i]])
1454  else:
1455  pt = kml.newpoint(coords=[latLon[i]])
1456  pt.style.iconstyle.color = color
1457  pt.style.iconstyle.scale = 0.4
1458  pt.style.labelstyle.scale = 0.6
1459  pt.altitudemode = altitudeMode
1460 
1461  # Add path
1462  ls = kml.newlinestring(name="Tracks", description=serialNumber + " tracks", coords=latLon)
1463 
1464  # Style
1465  ls.extrude = 1
1466  ls.altitudemode = altitudeMode
1467  ls.style.linestyle.width = 2
1468  ls.style.linestyle.color = color
1469  kml.save(kmlFileName)
1470 
1471  return kmlFileName
1472 
1473 
1474 
1475 def insStatus(istatus):
1476  result = cObj()
1477 
1478  result.align = cObj()
1479  result.align.coarse = cObj()
1480  result.align.good = cObj()
1481  result.align.fine = cObj()
1482 
1483  # 0-3
1484  result.align.coarse.att = (istatus >> 0) & 1
1485  result.align.coarse.vel = (istatus >> 1) & 1
1486  result.align.coarse.pos = (istatus >> 2) & 1
1487 
1488  # 4-7
1489  result.align.good.att = (istatus >> 4) & 1
1490  result.align.good.vel = (istatus >> 5) & 1
1491  result.align.good.pos = (istatus >> 6) & 1
1492  result.align.fine.att = (istatus >> 7) & 1
1493 
1494  # 8-11
1495  result.usingGps = (istatus >> 8) & 1
1496  result.usingMag = (istatus >> 11) & 1
1497 
1498  # 12-15
1499  result.navMode = (istatus >> 12) & 1
1500 
1501  # 16-23
1502  result.solutionStatus = (istatus >> 16) & 0x7
1503 
1504  # 20-23
1505  result.magActiveCalSet = (istatus >> 20) & 1
1506  result.magRecalibrating = (istatus >> 22) & 1
1507  result.magInterOrBadCal = ((istatus >> 23) & 1) != 1
1508 
1509  # 24-27
1510 
1511  # 28-31
1512  result.rtosTaskPeriodOverrun = (istatus >> 29) & 1
1513  result.generalFault = (istatus >> 31) & 1
1514 
1515  return result
1516 
1517 
1518 
1519 def hdwStatus(hstatus):
1520  result = cObj()
1521 
1522  # 0-3
1523  result.motionGyrSig = (hstatus >> 0) & 0x1
1524  result.motionAccSig = (hstatus >> 1) & 0x1
1525  result.motionGyrDev = (hstatus >> 2) & 0x1
1526  result.motionAccDev = (hstatus >> 3) & 0x1
1527 
1528  # 4-7
1529  result.satellite_rx = (hstatus >> 4) & 0x1
1530 
1531  # 8-11
1532  result.saturationGyr = (hstatus >> 8) & 0x1
1533  result.saturationAcc = (hstatus >> 9) & 0x1
1534  result.saturationMag = (hstatus >> 10) & 0x1
1535  result.saturationBaro = (hstatus >> 11) & 0x1
1536 
1537  # 12-15
1538  result.saturationHistory = (hstatus >> 12) & 0x1
1539 
1540  # 16-19
1541  result.errComTxLimited = (hstatus >> 16) & 0x1
1542  result.errComRxOverrun = (hstatus >> 17) & 0x1
1543  result.errGpsTxLimited = (hstatus >> 18) & 0x1
1544  result.errGpsRxOverrun = (hstatus >> 19) & 0x1
1545 
1546  # 20-23
1547  result.comParseErrCount = (hstatus >> 20) & 0xF
1548 
1549  # 24-27
1550  result.selfTestFault = (hstatus >> 24) & 0x1
1551  result.errTemperature = (hstatus >> 25) & 0x1
1552 
1553  # 28-31
1554  result.faultWatchdogReset = (hstatus >> 28) & 0x1
1555  result.faultBODReset = (hstatus >> 29) & 0x1
1556  result.faultPORReset = (hstatus >> 30) & 0x1
1557  result.faultCPUErrReset = (hstatus >> 31) & 0x1
1558 
1559  return result
1560 
def __init__(self, _v, accBias=np.r_[0, pqrBias=np.r_[0, rotate=np.r_[0)
GeneratorWrapper< T > range(T const &start, T const &end, T const &step)
Definition: catch.hpp:4141
def lla2kml(time, lla, serialNumber, kmlFileName="log.kml", kwargs)
def hdwStatus(hstatus)
Hardware Status #####.
def gpsTimeToUTC(gpsWeek, gpsSOW, leapSecs=14)
def parse_raw_gps(self, f, did, dati, sHdr, cHdr)
def __init__(self, _v, rotate=np.r_[0)
def __init__(self, index, directory, serialNumber, refIns=None)
def insStatus(istatus)
INS Status #####.
def __init__(self, name='', dtype=0)
def loadData(self, directory=None, serialNumbers=None, refIns=None, startDev=0, devCount=-1)


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:57