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  ]))
396 
397  self.di[13].set('gps1Pos', dtypeGpsPos)
398  self.di[14].set('gps2Pos', dtypeGpsPos)
399 
400  # 15 'gps1Cno'
401  # 16 'gps2Cno'
402  # 17 'gps2Version'
403  # 18 'gps2Version'
404  # 19 'magCal'
405 
406  self.di[20].set('insResources', np.dtype([
407  ('dataSerNum', u32), # Indicates serial order in time
408  ('towMs', u32),
409  ('x_dot', dtStartVars),
410  ('magYawOffset', f32),
411  ]))
412 
413  self.di[21].set('gps1RtkPosRel', np.dtype([
414  ('dataSerNum', u32), # Indicates serial order in time
415  ('timeOfWeekMs', u32 ),
416  ('differentialAge', f32 ),
417  ('arRatio', f32 ),
418  ('vectorToBase', (f32, 3)),
419  ('distanceToBase', f32 ),
420  ('headingToBase', f32 ),
421  ]))
422 
423  self.di[22].set('gps1RtkPosMisc', np.dtype([
424  ('dataSerNum', u32), # Indicates serial order in time
425  ('timeOfWeekMs', u32),
426  ('accuracyPos', (f32, 3)),
427  ('accuracyCov', (f32, 3)),
428  ('arThreshold', f32),
429  ('gDop', f32),
430  ('hDop', f32),
431  ('vDop', f32),
432  ('baseLla', (f64, 3)),
433  ('cycleSlipCount', u32),
434  ('roverGpsObservationCount', u32),
435  ('baseGpsObservationCount', u32),
436  ('roverGlonassObservationCount', u32),
437  ('baseGlonassObservationCount', u32),
438  ('roverGalileoObservationCount', u32),
439  ('baseGalileoObservationCount', u32),
440  ('roverBeidouObservationCount', u32),
441  ('baseBeidouObservationCount', u32),
442  ('roverQzsObservationCount', u32),
443  ('baseQzsObservationCount', u32),
444  ('roverGpsEphemerisCount', u32),
445  ('baseGpsEphemerisCount', u32),
446  ('roverGlonassEphemerisCount', u32),
447  ('baseGlonassEphemerisCount', u32),
448  ('roverGalileoEphemerisCount', u32),
449  ('baseGalileoEphemerisCount', u32),
450  ('roverBeidouEphemerisCount', u32),
451  ('baseBeidouEphemerisCount', u32),
452  ('roverQzsEphemerisCount', u32),
453  ('baseQzsEphemerisCount', u32),
454  ('roverSbasCount', u32),
455  ('baseSbasCount', u32),
456  ('baseAntennaCount', u32),
457  ('ionUtcAlmCount', u32)
458  ]))
459 
460  # 23 'Feature Bits'
461 
462  dtypeSensorsMpuWTemp = np.dtype([
463  ('pqr', (f32, 3)),
464  ('acc', (f32, 3)),
465  ('mag', (f32, 3)),
466  ('temp', f32),
467  ])
468 
469  self.di[24].set('sensorsIs1', np.dtype([
470  ('dataSerNum', u32), # Indicates serial order in time
471  ('mpu', (dtypeSensorsMpuWTemp, 2)),
472  ]))
473 
474  # 25 'Sensor IS2'
475  # 26 'Sensor TC Bias'
476 
477  self.di[27].set('sensorBias', np.dtype([
478  ('dataSerNum', u32), # Indicates serial order in time
479  ('towMs', u32),
480  ('pqr', (f32, 3)),
481  ('acc', (f32, 3)),
482  ('mslBar', f32),
483  ('magI', (f32, 3)),
484  ('magB', (f32, 3)),
485  ]))
486 
487  # 28 'Sensor ADC'
488  # 29 'SCOMP'
489 
490  dtypeGpsVel = np.dtype([
491  ('dataSerNum', u32), # Indicates serial order in time
492  ('timeOfWeekMs', u32),
493  ('velEcef', (f32, 3)),
494  ('sAcc', f32)
495  ])
496 
497  self.di[30].set('gps1Vel', dtypeGpsVel)
498  self.di[31].set('gps2Vel', dtypeGpsVel)
499 
500  # 32 'HDW params'
501  # 33-37 Flash
502  # 38 'RTOS Info'
503 
504  self.di[39].set('debugArray', np.dtype([
505  ('dataSerNum', u32), # Indicates serial order in time
506  ('i', (i32, 9)),
507  ('f', (f32, 9)),
508  ('lf', (f64, 3)),
509  ]))
510 
511  self.di[47].set('insDev1', np.dtype([
512  ('dataSerNum', u32), # Indicates serial order in time
513  ('week', u32),
514  ('tow', f64),
515  ('iStatus', u32),
516  ('hStatus', u32),
517  ('euler', (f32, 3)),
518  ('uvw', (f32, 3)),
519  ('lla', (f64, 3)),
520  ('ned', (f32, 3)),
521  ('eulerErr', (f32, 3)),
522  ('uvwErr', (f32, 3)),
523  ('nedErr', (f32, 3)),
524  ]))
525 
526  self.di[48].set('ekfStates', np.dtype([
527  ('dataSerNum', u32), # Indicates serial order in time
528  ('time', f64),
529  ('qe2b', (f32, 4)),
530  ('ve', (f32, 3)),
531  ('ecef', (f64, 3)),
532  ('biasPqr', (f32, 3)),
533  ('biasAcc', (f32, 3)),
534  ('biasBaro', f32),
535  ('magDec', f32),
536  ('magInc', f32),
537  ]))
538 
539  # 49 'EKF Covariance'
540  # 50 'EKF Innovations'
541  # 51 'EKF Innovations Var'
542 
543  self.di[52].set('magnetometer1', np.dtype([
544  ('dataSerNum', u32), # Indicates serial order in time
545  ('time', f64),
546  ('mag', (f32, 3)),
547  ]))
548 
549  self.di[53].set('barometer', np.dtype([
550  ('dataSerNum', u32), # Indicates serial order in time
551  ('time', f64),
552  ('bar', f32),
553  ('mslBar', f32),
554  ('barTemp', f32),
555  ('humidity', f32),
556  ]))
557 
558  self.di[54].set('gps1RtkPos', dtypeGpsPos)
559 
560  self.di[55].set('gps1RtkCmpRel', np.dtype([
561  ('dataSerNum', u32), # Indicates serial order in time
562  ('timeOfWeekMs', u32 ),
563  ('differentialAge', f32 ),
564  ('arRatio', f32 ),
565  ('vectorToBase', (f32, 3)),
566  ('distanceToBase', f32 ),
567  ('headingToBase', f32 ),
568  ]))
569 
570  self.di[56].set('gpsVersion', np.dtype([
571  ('dataSerNum', u32), # Indicates serial order in time
572  ('swVersion', np.dtype((str, 30))),
573  ('hwVersion', np.dtype((str, 10))),
574  ('extension', np.dtype((str, 30))),
575  ('reserved', (u32, 2)),
576  ]))
577 
578  # 57 'Communications Loopback'
579 
580  self.di[58].set('dualImu', np.dtype([
581  ('dataSerNum', u32), # Indicates serial order in time
582  ('time', f64),
583  ('I', (dtypeImu, 2)),
584  ]))
585 
586  self.di[59].set('inl2MagObs', np.dtype([
587  ('dataSerNum', u32), # Indicates serial order in time
588  ('towMs', u32),
589  ('Ncal_samples', u32),
590  ('ready', u32),
591  ('calibrated', u32),
592  ('auto-recal', u32),
593  ('outlier', u32),
594  ('magHeading', f32),
595  ('insHeading', f32),
596  ('magInsHdgDelta', f32),
597  ('nis', f32),
598  ('nis_threshold', f32),
599  ('Wcal', (f32, 9)),
600  ('activeCalSet', u32),
601  ('magHeadingOffset', f32),
602  ]))
603 
604  # 60 - Raw GPS Ephemeris and Observation from Base
605  self.di[60].set('GPSBaseRaw', dtypeGpsRaw)
606 
607  # 61 - RTK Options
608  # 62 - Internal User page Info
609  # 63 - Manufacturing Info
610  # 64 - Self Test
611  # 65 - INS - 3 - ECEF Position & Quaternions NED
612  # 66 - INS - 4 - ECEF Position & Quaternions ECEF
613 
614  self.di[67].set('inl2Variance', np.dtype([
615  ('dataSerNum', u32), # Indicates serial order in time
616  ('towMs', u32),
617  ('PxyxNED', (f32, 3)),
618  ('PvelNED', (f32, 3)),
619  ('PattNED', (f32, 3)),
620  ('PABias', (f32, 3)),
621  ('PWBias', (f32, 3)),
622  ('PBaroBias', f32),
623  ('PDeclination', f32),
624  ]))
625 
626  # 68 - Strobe input time
627 
628  self.di[69].set('GPS1Raw', dtypeGpsRaw)
629  self.di[70].set('GPS2Raw', dtypeGpsRaw)
630 
631  self.di[91].set('gps1RtkCmpMisc', np.dtype([
632  ('dataSerNum', u32), # Indicates serial order in time
633  ('timeOfWeekMs', u32),
634  ('accuracyPos', (f32, 3)),
635  ('accuracyCov', (f32, 3)),
636  ('arThreshold', f32),
637  ('gDop', f32),
638  ('hDop', f32),
639  ('vDop', f32),
640  ('baseLla', (f64, 3)),
641  ('cycleSlipCount', u32),
642  ('roverGpsObservationCount', u32),
643  ('baseGpsObservationCount', u32),
644  ('roverGlonassObservationCount', u32),
645  ('baseGlonassObservationCount', u32),
646  ('roverGalileoObservationCount', u32),
647  ('baseGalileoObservationCount', u32),
648  ('roverBeidouObservationCount', u32),
649  ('baseBeidouObservationCount', u32),
650  ('roverQzsObservationCount', u32),
651  ('baseQzsObservationCount', u32),
652  ('roverGpsEphemerisCount', u32),
653  ('baseGpsEphemerisCount', u32),
654  ('roverGlonassEphemerisCount', u32),
655  ('baseGlonassEphemerisCount', u32),
656  ('roverGalileoEphemerisCount', u32),
657  ('baseGalileoEphemerisCount', u32),
658  ('roverBeidouEphemerisCount', u32),
659  ('baseBeidouEphemerisCount', u32),
660  ('roverQzsEphemerisCount', u32),
661  ('baseQzsEphemerisCount', u32),
662  ('roverSbasCount', u32),
663  ('baseSbasCount', u32),
664  ('baseAntennaCount', u32),
665  ('ionUtcAlmCount', u32)
666  ]))
667 
668  # Profiling
669  timeStart = systime.time()
670  self.loadTime = 0
671  self.unknownId = {}
672  self.directory = directory
673  self.serialNumber = serialNumber
674  self.rdat = {} # Raw data in python list format
675  self.data = {} # data in numpy format
676  self.index = index # index in all serial numbers
677  self.refLla = refLla
678  # self.version = []
679  # self.units = []
680 
681  if refIns is not None:
682  print("#%2d Opening: Ref INS %s" % (index, directory))
683 
684  fileMask = "LOG_REF_INS*.dat"
685  # Use first file in directory if not defined
686  else:
687  print("#%2d Opening: %s %s" % (index, serialNumber, directory))
688 
689  fileMask = "LOG_" + serialNumber + "*.sdat"
690 
691  if not os.path.isdir(directory):
692  print("Directory doesn't exist!")
693  sys.exit()
694  os.chdir(directory)
695  self.fileNames = glob.glob(fileMask)
696 
697  if not self.fileNames:
698  # print(" ***** Files not found! Check directory name and serial number. ***** ")
699  raise Exception('Load Error: .sdat files not found.')
700 
701  self.parse()
702  self.clean()
703 
704  # Profiling
705  self.loadTime = systime.time() - timeStart
706  print("Load time: %.2fs" % (self.loadTime))
707 
708  def clean(self):
709  for key, item in self.data.iteritems():
710  if not isinstance(item, np.ndarray):
711  continue
712 
713  for field in ['towMs', 'timeOfWeekMs', 'tow']:
714  if field in item.dtype.names:
715  if (np.diff(item[field].astype(np.int64)) < 0).any():
716  idx = np.argmin(np.diff(item[field].astype(np.int64)))
717  print("\033[93m" + "Time went backwards in ", key, r"!!!, removing all data " + ("before" if idx < len(item[field])/2.0 else "after") + "\033[0m")
718  if idx < len(item[field])/2.0:
719  self.data[key] = item[idx +1:]
720  else:
721  self.data[key] = item[:idx]
722  ms_multiplier = 1000.0 if 'Ms' in field else 1.0
723  if (np.diff(item[field]) > 3600 * ms_multiplier).any():
724  print("\033[93m" + "greater than 1 minute gap in ", key, " data, assuming GPS fix was acquired during data set, and chopping data"+ "\033[0m")
725  idx = np.argmax(np.diff(item[field])) + 1
726  self.data[key] = item[idx:]
727 
728  def parse(self):
729  self.curTime = np.r_[0]
730  self.raw_gps_keys = []
731 
732  # Iterate over files to concatenate data
733  self.fileNames.sort()
734  for fileName in self.fileNames:
735  print(fileName)
736  self.__parseFile(fileName)
737  # set the raw GPS dictionary as a datatype
738  for name in self.raw_gps_keys:
739  for key, item in self.data[name].iteritems():
740  self.data[name][key] = np.array(item)
741  if 'ins2' in self.data.keys():
742  setGpsWeek(self.data['ins2']['week'][0])
743 
744 
745  def parse_raw_gps(self, f, did, dati, sHdr, cHdr):
746 
747  valid_types = [1, 2, 3, 4, 5, 6, 123]
748  valid_receiver_indexes = [1, 2, 3, 4]
749 
750  if dati.name not in self.raw_gps_keys:
751  self.raw_gps_keys.append(dati.name)
752 
753  buf = np.fromfile(f, np.uint8, count=cHdr['dataSize'])
754  for i in range(sHdr['dCount']):
755  pointer = 0
756  hdr_size = np.dtype(dtypeGpsRaw).itemsize
757  gps_raw_header = buf[pointer:pointer + hdr_size].view(dtypeGpsRaw)
758  pointer += hdr_size
759 
760  # Pull in the header data
761  try:
762  type = gps_raw_header['type'][0]
763  count = gps_raw_header['count'][0]
764  receiverIndex = gps_raw_header['receiverIndex'][0]
765  assert (type in valid_types and receiverIndex in valid_receiver_indexes)
766  if dati.name not in self.data.keys():
767  self.data[dati.name] = {'dataSerNum': [gps_raw_header['dataSerNum'][0]],
768  'receiverIndex': [receiverIndex],
769  'type': [type],
770  'count': [count],
771  'corrupt_data': 0}
772  else:
773  self.data[dati.name]['dataSerNum'].append(gps_raw_header['dataSerNum'][0])
774  self.data[dati.name]['receiverIndex'].append(gps_raw_header['receiverIndex'][0])
775  self.data[dati.name]['type'].append(type)
776  self.data[dati.name]['count'].append(count)
777  except:
778  print("invalid raw gps header: type=", type, "count = ", count, "receiverIndex = ", receiverIndex)
779  self.data[dati.name]['corrupt_data'] += 1
780  continue
781 
782  if type == RAW_DATA_OBS:
783  try:
784  bytes_in_payload = np.dtype(dtypeObsD).itemsize * count
785  obs = buf[pointer:pointer + bytes_in_payload].view(dtypeObsD)
786  pointer += bytes_in_payload
787  if 'obs' not in self.data[dati.name]:
788  self.data[dati.name]['obs'] = np.rec.array(obs)
789  else:
790  self.data[dati.name]['obs'] = np.hstack((self.data[dati.name]['obs'], np.rec.array(obs)))
791  except:
792  print("badly formed raw gps data - DID: %d type: Obs, count: %d, actual: %f" %
793  (did, count, (len(buf) - 8) / (float(np.dtype(dtypeObsD).itemsize))))
794  self.data[dati.name]['corrupt_data'] += 1
795  continue
796 
797  def __parseFile(self, filename):
798  with open(filename, 'rb') as f:
799 
800  while 1:
801  # Read and validate chunk header
802  cHdr = np.fromfile(f, dtype=self.dtCnkHdr, count=1)
803 
804  count = cHdr['dataSize']
805 
806  if np.shape(cHdr)[0] == 0 or cHdr['marker'][0] != 0xFC05EA32:
807  # print( "Done parsing data!" )
808  break
809 
810  # Read chunk sub header
811  sHdr = np.fromfile(f, dtype=self.dtCnkSubHdr, count=1)
812 
813  # Find ID
814  did = sHdr['dHdr']['id'][0]
815  dsize = sHdr['dHdr']['size'][0]
816  # if did == 6:
817  # print( "DID: ",did )
818  if did >= self.DID_COUNT:
819  if did not in self.unknownDidDisplayed.keys():
820  self.unknownDidDisplayed[did] = True
821  print("==============================================================================")
822  print(" - ERROR - Data ID " + str(did) + " out of range " + str(
823  self.DID_COUNT) + ". Please add missing DID definitions to ISToolsDataSorted.pyx.")
824  print("==============================================================================")
825  did = 0
826  self.unknownDidDisplayed[did] = True
827  systime.sleep(0.5)
828 
829  dati = self.di[did]
830 
831  if dati.dtype:
832  if dsize == (dati.dtype.itemsize - 4):
833  # Known data type
834  # print("Found id: ", did)
835  cDat = np.fromfile(f, dati.dtype, count=sHdr['dCount'])
836 
837  if dati.name in self.data.keys():
838  # Append
839  # self.data[dati.name].append(cDat)
840  self.data[dati.name] = np.concatenate([self.data[dati.name], cDat])
841  else:
842  # Create
843  self.data[dati.name] = cDat
844 
845  # Handle Raw data differently (because it changes sizes and carries multiple messages)
846  elif dati.dtype == dtypeGpsRaw:
847  self.parse_raw_gps(f, did, dati, sHdr, cHdr)
848 
849  else:
850  # Mismatched data size
851  print("==============================================================================")
852  print(" - ERROR - Data ID", did, "(" + dati.name + ") mismatched size. Read", dsize, "expected", dati.dtype.itemsize - 4)
853  print("==============================================================================")
854  # systime.sleep(0.5)
855  # sys.exit()
856  cDat = np.fromfile(f, np.uint8, count=cHdr['dataSize'][0])
857  else:
858  # Unknown data type
859  if did not in self.unknownDidDisplayed.keys():
860  self.unknownDidDisplayed[did] = True
861  print("Undefined DID: ", did)
862  cDat = np.fromfile(f, np.uint8, count=cHdr['dataSize'][0])
863 
864 
865 class cDevices:
866  def __init__(self):
867  self.devices = []
868  self.loadTime = 0 # Profiling
869 
870  # Load data to be viewed. If the "selection.txt" file is found, the line by line contents
871  # of selection.txt specify an additional subdirectory and list of serial numbers to be loaded.
872  # If serial numbers are not specified, either in selection.txt or in the loadData() parameter,
873  # then all serial numbers and files are read.
874  # directory Directory data is loaded from. If not specified, the current directory is used. If no data found, use latest data sub directory.
875  # serialNumbers Device serial numbers to load. If not specified, all serial numbers and files found are loaded.
876  # startDev First index of found devices (serial numbers) to load.
877  # devCount Number of devices (serial numbers) to load.
878  def loadData(self, directory=None, serialNumbers=None, refIns=None, startDev=0, devCount=-1):
879 
880  # Profiling
881  self.loadTime = 0
882  timeLoadStart = systime.time()
883 
884  # We don't support reference INS right now
885  if refIns != None:
886  raise Exception('refIns not supported right now.')
887 
888  if directory is not None:
889  # Convert backslash to forward slash (Windows to Linux)
890  directory = directory.replace('\\', '/')
891 
892  if '~' in directory:
893  pass
894 
895  # Automatically open logs specified in "selection.txt"
896  os.chdir(directory)
897 
898  # Use selection file if it exists
899  selectionFileName = 'selection.txt'
900  if os.path.exists(selectionFileName):
901  with open(selectionFileName) as f:
902  lines = f.read().splitlines()
903 
904  # Convert backslash to forward slash (Windows to Linux)
905  directory += lines[0].replace('\\', '/')
906 
907  # Read serial numbers from selection.txt
908  serialNumbers = []
909  for serNum in lines[1:]:
910  # Stop if we find a blank line
911  if serNum == '':
912  break
913  serialNumbers.append(serNum)
914 
915  # If current directory has NO data, use newest sub directory containing data.
916  files = os.listdir(directory)
917  if not any(".sdat" in s for s in files):
918  dirName = None
919  dirTime = 0
920  for fname in files:
921  # Has data log directory name format
922  if len(fname) >= 15 and fname[0:2] == '20' and fname[8:9] == '_':
923  dTime = int(fname[0:8] + fname[9:15])
924  # Is latest
925  if dTime > dirTime:
926  dirTime = dTime
927  dirName = fname
928 
929  if dirName != None:
930  directory += dirName
931 
932  # Print directory
933  print("Loading Data: ", directory)
934 
935  # Add all devices in directory
936  if serialNumbers is None or serialNumbers == []:
937  # Find list of serial numbers from files in directory
938  files = os.listdir(directory)
939  serNums = []
940  for str in files:
941  if str.find('.sdat') != -1:
942  str = str.replace('.sdat', '')
943  if str.find('LOG_SN') != -1:
944  str = str[4:11]
945  if not str in serNums:
946  serNums.append(str)
947  elif str.find('LOG_PR') != -1:
948  str = str.replace('LOG_', '')
949  str = str[:str.find('_')]
950  if not str in serNums:
951  serNums.append(str)
952  serialNumbers = serNums
953 
954  count = len(serialNumbers)
955 
956  # Validate serial numbers
957  if count <= 0:
958  raise Exception('Load Error: .sdat files not found.')
959 
960  # Find size and last index
961  if devCount > 0 and devCount < count:
962  count = devCount
963  endIndex = min(startDev + count, len(serialNumbers))
964 
965  # print ("Start Index: ", startDev, " End Index: ", endIndex)
966 
967  # Add devices
968  for i in range(startDev, endIndex):
969  device = cDevice(i, directory, serialNumbers[i], refIns)
970  self.devices.append(device)
971 
972  # Profiling
973  self.loadTime = systime.time() - timeLoadStart
974  print("Total load time: %.2fs" % (self.loadTime))
975 
976 
977 def gpsTimeToUTC(gpsWeek, gpsSOW, leapSecs=14):
978  global showUtcTime
979  if showUtcTime == 0:
980  return gpsSOW
981 
982  # Search for a valid GPS week
983  size = np.shape(gpsWeek)
984  if size and size[0] > 1:
985  # if gpsWeek[0] == 0:
986  # gpsWeek = gpsWeek[-1]
987  # Use the largest value for the week
988  gpsWeek = np.max(gpsWeek)
989 
990  if gpsWeek == 0:
991  return gpsSOW
992 
993  secsInWeek = 604800
994  # secsInDay = 86400
995  gpsEpoch = (1980, 1, 6, 0, 0, 0) # (year, month, day, hh, mm, ss)
996  # secFract = gpsSOW % 1
997 
998  epochTuple = gpsEpoch + (-1, -1, 0)
999  t0 = systime.mktime(epochTuple) - systime.timezone # mktime is localtime, correct for UTC
1000  tdiff = (gpsWeek * secsInWeek) + gpsSOW - leapSecs
1001  t = t0 + tdiff
1002  return t
1003 
1004 
1006  sizes = np.array([a.itemsize for a in arrays])
1007  offsets = np.r_[0, sizes.cumsum()]
1008  n = len(arrays[0])
1009  joint = np.empty((n, offsets[-1]), dtype=np.uint8)
1010  for a, size, offset in zip(arrays, sizes, offsets):
1011  joint[:, offset:offset + size] = a.view(np.uint8).reshape(n, size)
1012  dtype = sum((a.dtype.descr for a in arrays), [])
1013  return joint.ravel().view(dtype)
1014 
1015 
1016 # Join list of structured numpy arrays into one
1018  newdtype = sum((a.dtype.descr for a in arrays), [])
1019  newrecarray = np.empty(len(arrays[0]), dtype=newdtype)
1020  for a in arrays:
1021  for name in a.dtype.names:
1022  newrecarray[name] = a[name]
1023  return newrecarray
1024 
1025 
1026 class cSIMPLE:
1027  def __init__(self, _v):
1028  self.v = _v
1029 
1030 
1031 class cIMU:
1032  def __init__(self, _v):
1033  global gpsWeek
1034  self.v = _v
1035  self.__flt = cObj()
1036  self.__flt.pqr = None
1037  self.__flt.acc = None
1038  self.__flt.pqrNoBias = None
1039  self.__flt.accNoBias = None
1040  self.__flt.barNoBias = None
1041  self.cornerFreqHz = 60
1042  # self.cornerFreqHz = 30
1043  # self.cornerFreqHz = 15
1044 
1045  self.time = gpsTimeToUTC(gpsWeek, self.v['time'])
1046 
1047  self.i = [cObj(), cObj()]
1048  for j in range(0, 2):
1049  self.i[j].pqr = None
1050  self.i[j].acc = None
1051 
1052  # Dual IMU
1053  if 'I' in self.v.dtype.names:
1054  self.i[0].pqr = self.v['I']['pqr'][:, 0, :]
1055  self.i[1].pqr = self.v['I']['pqr'][:, 1, :]
1056  self.i[0].acc = self.v['I']['acc'][:, 0, :]
1057  self.i[1].acc = self.v['I']['acc'][:, 1, :]
1058 
1059  # Preintegrated IMU
1060  if 'theta1' in self.v.dtype.names and 'theta2' in self.v.dtype.names:
1061  divDt = 1.0 / self.v['dt']
1062  self.i[0].pqr = self.v['theta1']
1063  self.i[1].pqr = self.v['theta2']
1064  self.i[0].acc = self.v['vel1']
1065  self.i[1].acc = self.v['vel2']
1066 
1067  for i in range(0, 2):
1068  for a in range(0, 3):
1069  self.i[i].pqr[:, a] *= divDt
1070  self.i[i].acc[:, a] *= divDt
1071 
1072  def fltAcc(self):
1073  if self.__flt.acc is None:
1074  self.__flt.acc = ft.lpfNoDelay(self.v['acc'], self.cornerFreqHz, time=self.v['time'])
1075  return self.__flt.acc
1076 
1077  def fltPqr(self):
1078  if self.__flt.pqr is None:
1079  self.__flt.pqr = ft.lpfNoDelay(self.v['pqr'], self.cornerFreqHz, time=self.v['time'])
1080  return self.__flt.pqr
1081 
1082  def fltPqrNoBias(self):
1083  if 'pqrNoBias' in self.v.dtype.names and self.__flt.pqrNoBias is None:
1084  self.__flt.pqrNoBias = ft.lpfNoDelay(self.v['pqrNoBias'], self.cornerFreqHz, time=self.v['time'])
1085  return self.__flt.pqrNoBias
1086 
1087  def fltAccNoBias(self):
1088  if 'accNoBias' in self.v.dtype.names and self.__flt.accNoBias is None:
1089  self.__flt.accNoBias = ft.lpfNoDelay(self.v['accNoBias'], self.cornerFreqHz, time=self.v['time'])
1090  return self.__flt.accNoBias
1091 
1092  def fltBarNoBias(self):
1093  if 'mslBarNoBias' in self.v.dtype.names and self.__flt.barNoBias is None:
1094  self.__flt.mslBarNoBias = ft.lpfNoDelay(self.v['mslBarNoBias'], self.cornerFreqHz, time=self.v['time'])
1095  return self.__flt.mslBarNoBias
1096 
1097 
1098 # self.mslBar = ft.smooth(self.v['mslBar']+72, delta=200)
1099 # self.mslBarDot = ft.derivative(self.v['time'], self.mslBar, delta=10)
1100 # self.mslBarDotLpf = ft.lpfNoDelay(self.mslBarDot, cornerFreqHz=0.5, time = self.v['time'])
1101 
1102 class cINS:
1103  def __init__(self, _v):
1104  # self.v = _v
1105  self.v = _v[:-1] # Throw out last element
1106  self.__velNED = None
1107  self.__course = None
1108  self.__ecef = None
1109  self.__ned = None
1110  self.__istatus = None
1111  self.__hstatus = None
1112  self.__size = np.shape(self.v['tow'])[0]
1113  self.time = gpsTimeToUTC(self.v['week'], self.v['tow'])
1114 
1115  if not 'euler' in self.v.dtype.names and 'q' in self.v.dtype.names:
1116  # self.v['euler'] = pose.quat2eulerArray(self.v['q'])
1117  # self.euler = pose.quat2eulerArray(self.v['q'])
1118  dtypeeuler = np.dtype([('euler', (np.float, 3))])
1119  e = pose.quat2eulerArray(self.v['q'])
1120  euler = np.ndarray(np.shape(e)[0], dtype=dtypeeuler, buffer=e)
1121  self.v = join_struct_arrays2([self.v, euler])
1122 
1123  if not 'q' in self.v.dtype.names and 'euler' in self.v.dtype.names:
1124  # self.v['q'] = pose.euler2quatArray(self.v['euler'])
1125  # self.q = pose.euler2quatArray(self.v['euler'])
1126  dtypeq = np.dtype([('q', (np.float, 4))])
1127  q = pose.euler2quatArray(self.v['euler'])
1128  quat = np.ndarray(np.shape(q)[0], dtype=dtypeq, buffer=q)
1129  self.v = join_struct_arrays2([self.v, quat])
1130 
1131  # Velocity vector in inertial frame
1132  def velNed(self):
1133  if self.__velNED is None:
1134  self.__velNED = np.zeros(np.shape(self.v['uvw']))
1135 
1136  for i in range(0, self.__size):
1137  DCM = pose.eulerDCM(self.v['euler'][i, :])
1138  velNED = np.dot(DCM.T, self.v['uvw'][i, :]) # body to inertial frame
1139  self.__velNED[i, :] = velNED
1140 
1141  return self.__velNED
1142 
1143  def course(self):
1144  if self.__course is None:
1145  self.__course = np.arctan2(self.velNED[:, 1], self.velNED[:, 0])
1146  return self.__course
1147 
1148  def ned(self):
1149  global refLla
1150  if self.__ned is None:
1151  self.__ned = pose.lla2ned(refLla, self.v['lla'])
1152  return self.__ned
1153 
1154  def ecef(self):
1155  if self.__ecef is None:
1156  self.__ecef = pose.lla2ecef(self.v['lla'])
1157  return self.__ecef
1158 
1159  def set(self, time):
1160  self.time = time
1161 
1162  def speed2D(self):
1163  return np.sqrt(np.square(self.v['uvw'][:, 0]) +
1164  np.square(self.v['uvw'][:, 1]))
1165 
1166  def speed3D(self):
1167  return np.sqrt(np.square(self.v['uvw'][:, 0]) +
1168  np.square(self.v['uvw'][:, 1]) +
1169  np.square(self.v['uvw'][:, 2]))
1170 
1171  def iStatus(self):
1172  if self.__istatus is None:
1173  self.__istatus = insStatus(self.v['iStatus'])
1174  return self.__istatus
1175 
1176  def hStatus(self):
1177  if self.__hstatus is None:
1178  self.__hstatus = hdwStatus(self.v['hStatus'])
1179  return self.__hstatus
1180 
1181 
1182 class cRIMU:
1183  def __init__(self, _v,
1184  accBias=np.r_[0, 0, 0],
1185  pqrBias=np.r_[0, 0, 0],
1186  rotate=np.r_[0, 0, 0]):
1187  self.v = _v
1188  self.cornerFreqHz = 30
1189  self.__flt = cObj()
1190  self.__flt.pqr = None
1191  self.__flt.acc = None
1192 
1193  if accBias[0] != 0 or accBias[1] != 0 or accBias[2] != 0:
1194  self.v['acc'] += accBias
1195 
1196  if pqrBias[0] != 0 or pqrBias[1] != 0 or pqrBias[2] != 0:
1197  self.v['pqr'] += pqrBias
1198 
1199  if rotate[0] != 0 or rotate[1] != 0 or rotate[2] != 0:
1200  self.v['acc'] = pose.vectorRotateInertialToBody2(self.v['acc'], rotate)
1201  self.v['pqr'] = pose.vectorRotateInertialToBody2(self.v['pqr'], rotate)
1202 
1203  def fltPqr(self):
1204  if self.__flt.pqr is None:
1205  self.__flt.pqr = ft.lpfNoDelay(self.v['pqr'], self.cornerFreqHz, time=self.v['time'])
1206  return self.__flt.pqr
1207 
1208  def fltAcc(self):
1209  if self.__flt.acc is None:
1210  self.__flt.acc = ft.lpfNoDelay(self.v['acc'], self.cornerFreqHz, time=self.v['time'])
1211  return self.__flt.acc
1212 
1213 
1214 class cRINS:
1215  def __init__(self, _v, rotate=np.r_[0, 0, 0]):
1216  global refLla
1217  self.v = _v
1218 
1219  self.__ned = None
1220  self.__nedDotDot = None
1221  self.__uvw = None
1222  self.__rotate = rotate
1223 
1224  # self.v['nedDot'] = ft.smooth(self.v['nedDot'], delta=10)
1225  # self.v['euler'] = ft.smooth(self.v['euler'], delta=10)
1226  if self.__rotate[0] != 0 or self.__rotate[1] != 0 or self.__rotate[2] != 0:
1227  self.v['euler'][:, 0] += self.__rotate[0]
1228  self.v['euler'][:, 1] += self.__rotate[1]
1229  self.v['euler'][:, 2] += self.__rotate[2]
1230 
1231  def ned(self):
1232  if self.__ned is None:
1233  self.__ned = pose.lla2ned(refLla, self.v['lla'])
1234  return self.__ned
1235 
1236  def nedDotDot(self):
1237  if self.__nedDotDot is None:
1238  self.__nedDotDot = ft.derivative(self.v['time'], self.v['nedDot'], delta=2)
1239  self.__nedDotDot[:, 2] -= 9.80665
1240  cornerFreqHz = 10
1241  self.__nedDotDot = ft.lpfNoDelay(self.__nedDotDot, cornerFreqHz, time=self.v['time'])
1242  return self.__nedDotDot
1243 
1244  def uvw(self):
1245  if self.__uvw is None:
1246  self.__uvw = pose.vectorRotateInertialToBody(self.v['nedDot'], self.v['euler'])
1247  if self.__rotate[0] != 0 or self.__rotate[1] != 0 or self.__rotate[2] != 0:
1248  self.uvw = pose.vectorRotateInertialToBody2(self.uvw, self.__rotate)
1249  return self.__uvw
1250 
1251 
1252 class cRGPS:
1253  def __init__(self, _v):
1254  global refLla
1255 
1256  self.v = _v
1257  self.__ned = None
1258  self.__acc = cObj()
1259  self.__acc.ned = None
1260 
1261  def ned(self):
1262  if self.__ned is None:
1263  self.__ned = pose.lla2ned(refLla, self.v['lla'])
1264  return self.__ned
1265 
1266  def accNed(self):
1267  if self.__acc.ned is None:
1268  # Create Accelerations from GPS velocities
1269  # self.__acc.ned = ft.meanDerivative(self.v['time'], self.v['vel.ned'], 5, 3)
1270  self.__acc.ned = ft.meanDerivative(self.v['time'], self.v['vel.ned'], 2, 2)
1271  return self.__acc.ned
1272 
1273 
1274 class cGPS:
1275  def __init__(self, _v):
1276  global refLla
1277  global refLla
1278  global gpsWeek
1279  self.v = _v
1280 
1281  self.time = gpsTimeToUTC(self.v['week'], (_v['timeOfWeekMs'] * 0.001))
1282  self.ned = pose.lla2ned(refLla, _v['lla'])
1283 
1284  self.satsUsed = (_v['status'] >> 0) & 0xFF
1285  self.fixType = (_v['status'] >> 8) & 0xFF
1286  self.rtkMode = (_v['status'] >> 20) & 0x01
1287 
1288  # self.vectorToBase = _v['vectorToBase']
1289  # self.distanceToBase = _v['distanceToBase']
1290 
1291 
1292 class cGPSRaw:
1293  def __init__(self, _v):
1294  self.count = _v['count']
1295  self.type = _v['type']
1296  self.receiverIndex = _v['receiverIndex']
1297  self.corruptCount = int(_v['corrupt_data'])
1298 
1299  if 'obs' in _v.keys():
1300  self.obs = _v['obs']
1301  try:
1302  self.obstime = np.array([np.datetime64(int(np.round((t['time'] + t['sec'])*1000000)), 'us') for t in _v['obs']['time']])
1303  except OverflowError as e:
1304  debug = 1
1305 
1306 
1307 class cRTKMisc:
1308  def __init__(self, _v):
1309  self.v = _v
1310  self.time = gpsTimeToUTC(_v['week'], (_v['timeOfWeekMs'] * 0.001))
1311 
1312  self.slipCounter = _v['cycleSlipCount']
1313  self.arThreshold = _v['arThreshold']
1314  self.baseLla = _v['baseLla']
1315  self.heading = _v['rtkCompassHeading']
1316 
1317 
1318 class cGpsVel:
1319  def __init__(self, _v):
1320  global gpsWeek
1321  self.v = _v
1322 
1323  def acc(self):
1324  if self.__acc is None:
1325  self.__acc = cObj()
1326  self.__acc.time = self.time
1327  # self.__acc.ned = ft.meanDerivative(self.vel.time, self.v['ned'], 5, 3)
1328  self.__acc.ned = ft.meanDerivative(self.time, self.v['ned'], 2, 2)
1329  return self.__acc
1330 
1331 
1332 class cGpsAcc:
1333  def __init__(self, _v):
1334  self.v = _v
1335  # self.time = _v['timeMs'] * 0.001
1336  self.time = gpsTimeToUTC(self.v['week'], (_v['timeOfWeekMs'] * 0.001))
1337 
1338 
1339 class cBias:
1340  def __init__(self, _v):
1341  global gpsWeek
1342  self.v = _v
1343  # self.time = _v['timeMs'] * 0.001
1344  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1345 
1346 
1347 class cInsRes:
1348  def __init__(self, _v):
1349  global gpsWeek
1350  self.v = _v
1351  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1352 
1353 
1354 class cDevInfo:
1355  def __init__(self, _v):
1356  self.v = _v
1357 
1358 
1360  def __init__(self, _v):
1361  global gpsWeek
1362  self.v = _v
1363  self.__istatus = None
1364  self.__hstatus = None
1365 
1366  if 'tow' in _v.dtype.names:
1367  # self.time = _v['time']
1368  self.time = gpsTimeToUTC(gpsWeek, _v['tow'])
1369  if 'towMs' in _v.dtype.names:
1370  # self.time = (_v['timeMs']) * 0.001
1371  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1372 
1373  def iStatus(self):
1374  if self.__istatus is None:
1375  self.__istatus = insStatus(self.v['iStatus'])
1376  return self.__istatus
1377 
1378  def hStatus(self):
1379  if self.__istatus is None:
1380  self.__hstatus = hdwStatus(self.v['hStatus'])
1381  return self.__hstatus
1382 
1383 
1385  def __init__(self, _v):
1386  global refLla
1387  self.v = _v
1388  self.accNed = cObj()
1389  self.velNed = cObj()
1390  self.lla = cObj()
1391  self.uvw = cObj()
1392 
1393  # self.time = _v['timeMs'] * 0.001
1394  # self.accNed.time = _v['accNed.timeMs'] * 0.001
1395  # self.velNed.time = _v['velNed.timeMs'] * 0.001
1396  # self.lla.time = _v['lla.timeMs'] * 0.001
1397  # self.uvw.time = _v['uvw.timeMs'] * 0.001
1398  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1399  self.accNed.time = gpsTimeToUTC(gpsWeek, (_v['accNed']['towMs'] * 0.001))
1400  self.velNed.time = gpsTimeToUTC(gpsWeek, (_v['velNed']['towMs'] * 0.001))
1401  self.lla.time = gpsTimeToUTC(gpsWeek, (_v['lla']['towMs'] * 0.001))
1402 
1403  self.accNed.refHdg = np.arctan2(self.v['accNed']['ref'][:, 1], self.v['accNed']['ref'][:, 0])
1404  self.accNed.insHdg = np.arctan2(self.v['accNed']['ins'][:, 1], self.v['accNed']['ins'][:, 0])
1405 
1406  self.lla.refNed = pose.lla2ned(refLla, _v['lla']['ref'])
1407  self.lla.insNed = pose.lla2ned(refLla, _v['lla']['ins'])
1408 
1409 
1410 # self.v['mslBar'] += 86;
1411 
1413  def __init__(self, _v):
1414  global gpsWeek
1415  self.v = _v
1416 
1417  # self.time = _v['timeMs'] * 0.001
1418  self.time = gpsTimeToUTC(gpsWeek, (_v['towMs'] * 0.001))
1419  if 'magTowMs' in _v.dtype.names:
1420  # self.magTime = (_v['magTowMs']) * 0.001
1421  self.magTime = gpsTimeToUTC(gpsWeek, (_v['magTowMs'] * 0.001))
1422 
1423 
1424 def lla2kml(time, lla, serialNumber, kmlFileName="log.kml", **kwargs):
1425  kml = simplekml.Kml()
1426 
1427  color = kwargs.pop('color', simplekml.Color.yellow)
1428  altitudeMode = kwargs.pop('altitudeMode', simplekml.constants.AltitudeMode.absolute)
1429  timeStep = kwargs.pop('timeStep', 0)
1430 
1431  latLon = []
1432  tNext = 0
1433  lNext = 0
1434  for i in range(0, np.shape(lla)[0]):
1435  latLon.append((lla[i, 1], lla[i, 0], lla[i, 2]))
1436 
1437  # Add timestamp
1438  if timeStep:
1439  # if timeStep == -1:
1440  # pt = kml.newpoint(name="%.1f" % time[i], coords=[latLon[i]])
1441  # pt.style.iconstyle.color = color
1442  # pt.style.iconstyle.scale = 0.5
1443  # pt.style.labelstyle.scale = 0.7
1444  if time[i] >= tNext:
1445  tNext += timeStep
1446  # round(tNext, timeStep)
1447  if time[i] >= lNext:
1448  if timeStep > lNext:
1449  lNext += timeStep
1450  else:
1451  lNext += 1
1452  pt = kml.newpoint(name="%.2f" % time[i], coords=[latLon[i]])
1453  else:
1454  pt = kml.newpoint(coords=[latLon[i]])
1455  pt.style.iconstyle.color = color
1456  pt.style.iconstyle.scale = 0.4
1457  pt.style.labelstyle.scale = 0.6
1458  pt.altitudemode = altitudeMode
1459 
1460  # Add path
1461  ls = kml.newlinestring(name="Tracks", description=serialNumber + " tracks", coords=latLon)
1462 
1463  # Style
1464  ls.extrude = 1
1465  ls.altitudemode = altitudeMode
1466  ls.style.linestyle.width = 2
1467  ls.style.linestyle.color = color
1468  kml.save(kmlFileName)
1469 
1470  return kmlFileName
1471 
1472 
1473 
1474 def insStatus(istatus):
1475  result = cObj()
1476 
1477  result.align = cObj()
1478  result.align.coarse = cObj()
1479  result.align.good = cObj()
1480  result.align.fine = cObj()
1481 
1482  # 0-3
1483  result.align.coarse.att = (istatus >> 0) & 1
1484  result.align.coarse.vel = (istatus >> 1) & 1
1485  result.align.coarse.pos = (istatus >> 2) & 1
1486 
1487  # 4-7
1488  result.align.good.att = (istatus >> 4) & 1
1489  result.align.good.vel = (istatus >> 5) & 1
1490  result.align.good.pos = (istatus >> 6) & 1
1491  result.align.fine.att = (istatus >> 7) & 1
1492 
1493  # 8-11
1494  result.usingGps = (istatus >> 8) & 1
1495  result.usingMag = (istatus >> 11) & 1
1496 
1497  # 12-15
1498  result.navMode = (istatus >> 12) & 1
1499 
1500  # 16-23
1501  result.solutionStatus = (istatus >> 16) & 0x7
1502 
1503  # 20-23
1504  result.magActiveCalSet = (istatus >> 20) & 1
1505  result.magRecalibrating = (istatus >> 22) & 1
1506  result.magInterOrBadCal = ((istatus >> 23) & 1) != 1
1507 
1508  # 24-27
1509 
1510  # 28-31
1511  result.rtosTaskPeriodOverrun = (istatus >> 29) & 1
1512  result.generalFault = (istatus >> 31) & 1
1513 
1514  return result
1515 
1516 
1517 
1518 def hdwStatus(hstatus):
1519  result = cObj()
1520 
1521  # 0-3
1522  result.motionGyrSig = (hstatus >> 0) & 0x1
1523  result.motionAccSig = (hstatus >> 1) & 0x1
1524  result.motionGyrDev = (hstatus >> 2) & 0x1
1525  result.motionAccDev = (hstatus >> 3) & 0x1
1526 
1527  # 4-7
1528  result.satellite_rx = (hstatus >> 4) & 0x1
1529 
1530  # 8-11
1531  result.saturationGyr = (hstatus >> 8) & 0x1
1532  result.saturationAcc = (hstatus >> 9) & 0x1
1533  result.saturationMag = (hstatus >> 10) & 0x1
1534  result.saturationBaro = (hstatus >> 11) & 0x1
1535 
1536  # 12-15
1537  result.saturationHistory = (hstatus >> 12) & 0x1
1538 
1539  # 16-19
1540  result.errComTxLimited = (hstatus >> 16) & 0x1
1541  result.errComRxOverrun = (hstatus >> 17) & 0x1
1542  result.errGpsTxLimited = (hstatus >> 18) & 0x1
1543  result.errGpsRxOverrun = (hstatus >> 19) & 0x1
1544 
1545  # 20-23
1546  result.comParseErrCount = (hstatus >> 20) & 0xF
1547 
1548  # 24-27
1549  result.selfTestFault = (hstatus >> 24) & 0x1
1550  result.errTemperature = (hstatus >> 25) & 0x1
1551 
1552  # 28-31
1553  result.faultWatchdogReset = (hstatus >> 28) & 0x1
1554  result.faultBODReset = (hstatus >> 29) & 0x1
1555  result.faultPORReset = (hstatus >> 30) & 0x1
1556  result.faultCPUErrReset = (hstatus >> 31) & 0x1
1557 
1558  return result
1559 
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 Sat Sep 19 2020 03:19:04