2 from typing
import List, Any, Union
5 import matplotlib.pyplot
as plt
9 from os.path
import expanduser
14 YELLOW =
r"\u001b[33m" 16 MAGENTA =
r"\u001b[35m" 21 RAD2DEG = 180.0 / 3.14159
22 DEG2RAD = 3.14159 / 180.0
25 from logReader
import Log
26 from pylib.ISToolsDataSorted
import refLla, getTimeFromTowMs, getTimeFromTow, setGpsWeek, getTimeFromGTime
27 from pylib.data_sets
import *
28 from pylib.pose
import quat2eulerArray, lla2ned, rotate_ecef2ned, quatRotVectArray
48 for d, ser
in enumerate(self.
log.serials):
58 fsize = fig.get_size_inches()
60 fig.set_size_inches(20, 20)
61 directory = os.path.dirname(self.
directory +
'/figures/')
62 if not os.path.exists(directory):
63 os.makedirs(directory)
64 fig.savefig(os.path.join(directory +
"/" + name +
'.' + self.
format), bbox_inches=
'tight')
65 fig.set_size_inches(fsize)
69 return self.
log.data[dev, DID][field][::self.
d]
75 yspn = np.max( [ylim[1] - ylim[0], limit] )
76 ylim = (np.mean(ylim)-yspn/2, np.mean(ylim)+yspn/2)
82 ax = fig.subplots(3,1, sharex=
True)
86 fig.suptitle(
'INS NED - ' + os.path.basename(os.path.normpath(self.
log.directory)))
90 refLla = self.
getData(d, DID_INS_2,
'lla')[0]
93 ax[0].plot(time, ned[:,0], label=self.
log.serials[d])
94 ax[1].plot(time, ned[:,1])
95 ax[2].plot(time, ned[:,2])
100 ax[0].plot(timeGPS, nedGps[:, 0], label=
'GPS')
101 ax[1].plot(timeGPS, nedGps[:, 1])
102 ax[2].plot(timeGPS, nedGps[:, 2])
116 len = np.shape(heading)[0]
117 for i
in range(1, len, downsample):
119 ax.plot(ned[i,1], ned[i,0], marker=(3, 0, -heading[i]*(180.0/np.pi)), color=
'g', markersize=markersize, linestyle=
'None')
120 ax.plot(ned[i,1], ned[i,0], marker=(2, 0, -heading[i]*(180.0/np.pi)), color=
'k', markersize=markersize, linestyle=
'None')
125 ax = fig.subplots(1,1)
126 ax.set_xlabel(
'East (m)')
127 ax.set_ylabel(
'North (m)')
128 fig.suptitle(
'NED Map - ' + os.path.basename(os.path.normpath(self.
log.directory)))
132 refLla = self.
getData(d, DID_INS_2,
'lla')[0]
135 ax.plot(ned[:,1], ned[:,0], label=self.
log.serials[d])
141 ax.plot(nedGps[:, 1], nedGps[:, 0], label=
'GPS')
144 ax.set_aspect(
'equal',
'datalim')
151 ax = fig.subplots(3,1, sharex=
True)
155 fig.suptitle(
'INS LLA - ' + os.path.basename(os.path.normpath(self.
log.directory)))
158 ax[0].plot(time, self.
getData(d, DID_INS_2,
'lla')[:,0], label=self.
log.serials[d])
159 ax[1].plot(time, self.
getData(d, DID_INS_2,
'lla')[:,1])
160 ax[2].plot(time, self.
getData(d, DID_INS_2,
'lla')[:,2], label=self.
log.serials[d])
164 ax[0].plot(timeGPS, self.
getData(d, DID_GPS1_POS,
'lla')[:, 0], label=
'GPS')
165 ax[1].plot(timeGPS, self.
getData(d, DID_GPS1_POS,
'lla')[:, 1])
166 ax[2].plot(timeGPS, self.
getData(d, DID_GPS1_POS,
'lla')[:, 2], label=
'GPS')
169 ax[2].plot(timeBaro, self.
getData(d, DID_BAROMETER,
'mslBar'), label=
'Baro')
180 ax = fig.subplots(3,1, sharex=
True)
184 fig.suptitle(
'GPS LLA - ' + os.path.basename(os.path.normpath(self.
log.directory)))
187 ax[0].plot(time, self.
getData(d, DID_GPS1_POS,
'lla')[:,0], label=self.
log.serials[d])
188 ax[1].plot(time, self.
getData(d, DID_GPS1_POS,
'lla')[:,1])
189 ax[2].plot(time, self.
getData(d, DID_GPS1_POS,
'lla')[:,2])
198 ax = fig.subplots(3,1, sharex=
True)
202 fig.suptitle(
'NED Vel - ' + os.path.basename(os.path.normpath(self.
log.directory)))
206 ax[0].plot(time, insVelNed[:,0], label=self.
log.serials[d])
207 ax[1].plot(time, insVelNed[:,1])
208 ax[2].plot(time, insVelNed[:,2])
212 gpsVelEcef = self.
getData(d, DID_GPS1_VEL,
'velEcef')
214 gpsVelNed = R.dot(gpsVelEcef.T).T
215 ax[0].plot(timeGPS, gpsVelNed[:, 0], label=
'GPS')
216 ax[1].plot(timeGPS, gpsVelNed[:, 1])
217 ax[2].plot(timeGPS, gpsVelNed[:, 2])
227 ax = fig.subplots(3,1, sharex=
True)
231 fig.suptitle(
'INS uvw - ' + os.path.basename(os.path.normpath(self.
log.directory)))
234 ax[0].plot(time, self.
getData(d, DID_INS_2,
'uvw')[:,0], label=self.
log.serials[d])
235 ax[1].plot(time, self.
getData(d, DID_INS_2,
'uvw')[:,1])
236 ax[2].plot(time, self.
getData(d, DID_INS_2,
'uvw')[:,2])
245 ax = fig.subplots(3, 1, sharex=
True)
246 fig.suptitle(
'INS Attitude - ' + os.path.basename(os.path.normpath(self.
log.directory)))
253 ax[0].plot(time, euler[:,0]*RAD2DEG, label=self.
log.serials[d])
254 ax[1].plot(time, euler[:,1]*RAD2DEG)
255 ax[2].plot(time, euler[:,2]*RAD2DEG)
264 ax = fig.subplots(3, 1, sharex=
True)
265 fig.suptitle(
'Heading - ' + os.path.basename(os.path.normpath(self.
log.directory)))
273 magHdg = self.
getData(d, DID_INL2_MAG_OBS_INFO,
'magHdg')
274 gpsHdg = self.
getData(d, DID_GPS1_RTK_CMP_REL,
'baseToRoverHeading')
277 ax[0].plot(magTime, magHdg * RAD2DEG)
279 ax[1].plot(gpsTime, gpsHdg*RAD2DEG)
280 ax[2].plot(insTime, euler[:,2]*RAD2DEG, label=self.
log.serials[d])
290 ax = fig.subplots(1, 1, sharex=
True)
291 fig.suptitle(
'INS Status - ' + os.path.basename(os.path.normpath(self.
log.directory)))
297 iStatus = self.
getData(d, DID_INS_2,
'insStatus')
299 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000001) != 0))
300 p1 = ax.get_xlim()[0] + 0.02 * (ax.get_xlim()[1] - ax.get_xlim()[0])
301 if r: ax.text(p1, -cnt * 1.5,
'Att Coarse')
303 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000010) != 0))
304 if r: ax.text(p1, -cnt * 1.5,
'Att Fine')
306 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000002) != 0))
307 if r: ax.text(p1, -cnt * 1.5,
'Vel Coarse')
309 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000020) != 0))
310 if r: ax.text(p1, -cnt * 1.5,
'Vel Fine')
312 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000004) != 0))
313 if r: ax.text(p1, -cnt * 1.5,
'Pos Coarse')
315 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000040) != 0))
316 if r: ax.text(p1, -cnt * 1.5,
'Pos Fine')
323 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000100) != 0))
324 if r: ax.text(p1, -cnt * 1.5,
'GPS aiding Pos/Vel')
326 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000080) != 0))
327 if r: ax.text(p1, -cnt * 1.5,
'GPS aiding Hdg')
329 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00000800) != 0))
330 if r: ax.text(p1, -cnt * 1.5,
'MAG aiding Hdg')
333 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00001000) != 0))
334 if r: ax.text(p1, -cnt * 1.5,
'Nav Mode')
336 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x000F0000) >> 16) / 4.0)
337 if r: ax.text(p1, -cnt * 1.5,
'Solution Status')
341 ax.plot(instime, -cnt * 1.5 + (((iStatus & 0x03000000) >> 24) == 3))
342 if r: ax.text(p1, -cnt * 1.5,
'RTK: Precision Position Valid')
344 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x04000000) != 0))
345 if r: ax.text(p1, -cnt * 1.5,
'RTK: Compassing Valid (fix & hold)')
349 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00100000) != 0))
350 if r: ax.text(p1, -cnt * 1.5,
'RTK: Compassing Baseline UNSET')
352 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00200000) != 0))
353 if r: ax.text(p1, -cnt * 1.5,
'RTK: Compassing Baseline BAD')
355 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x08000000) != 0))
356 if r: ax.text(p1, -cnt * 1.5,
'RTK: No Observ.')
358 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x10000000) != 0))
359 if r: ax.text(p1, -cnt * 1.5,
'RTK: Base No Pos.')
361 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x20000000) != 0))
362 if r: ax.text(p1, -cnt * 1.5,
'RTK: Base Pos. Moving')
366 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00400000) != 0))
367 if r: ax.text(p1, -cnt * 1.5,
'Mag: Recalibrating')
369 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x00800000) != 0))
370 if r: ax.text(p1, -cnt * 1.5,
'Mag: Inter. or Bad Cal')
374 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x40000000) != 0))
375 if r: ax.text(p1, -cnt * 1.5,
'RTOS Task Period Overrun')
377 ax.plot(instime, -cnt * 1.5 + ((iStatus & 0x80000000) != 0))
378 if r: ax.text(p1, -cnt * 1.5,
'General Fault')
384 print(RED +
"problem plotting insStatus: " + sys.exc_info()[0] + RESET)
390 ax = fig.subplots(1, 1, sharex=
True)
391 fig.suptitle(
'Hardware Status - ' + os.path.basename(os.path.normpath(self.
log.directory)))
397 hStatus = self.
getData(d, DID_INS_2,
'hdwStatus')
399 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000001) != 0))
400 p1 = ax.get_xlim()[0] + 0.02 * (ax.get_xlim()[1] - ax.get_xlim()[0])
401 if r: ax.text(p1, -cnt * 1.5,
'Motion Gyr Sig')
403 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000002) != 0))
404 if r: ax.text(p1, -cnt * 1.5,
'Motion Acc Sig')
406 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000004) != 0))
407 if r: ax.text(p1, -cnt * 1.5,
'Motion Gyr Dev')
409 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000005) != 0))
410 if r: ax.text(p1, -cnt * 1.5,
'Motion Acc Dev')
414 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000010) != 0))
415 if r: ax.text(p1, -cnt * 1.5,
'Satellite Rx')
419 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000100) != 0))
420 if r: ax.text(p1, -cnt * 1.5,
'Saturation Gyr')
422 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000200) != 0))
423 if r: ax.text(p1, -cnt * 1.5,
'Saturation Acc')
425 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000400) != 0))
426 if r: ax.text(p1, -cnt * 1.5,
'Saturation Mag')
428 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00000800) != 0))
429 if r: ax.text(p1, -cnt * 1.5,
'Saturation Baro')
433 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00010000) != 0))
434 if r: ax.text(p1, -cnt * 1.5,
'Err Com Tx Limited')
436 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00020000) != 0))
437 if r: ax.text(p1, -cnt * 1.5,
'Err Com Rx Overrun')
439 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00040000) != 0))
440 if r: ax.text(p1, -cnt * 1.5,
'Err GPS Tx Limited')
442 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00080000) != 0))
443 if r: ax.text(p1, -cnt * 1.5,
'Err GPS Rx Overrun')
447 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x00F00000) >> 20) / 4)
448 if r: ax.text(p1, -cnt * 1.5,
'Com Parse Error Count')
450 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x01000000) != 0))
451 if r: ax.text(p1, -cnt * 1.5,
'BIT Self Test Fault')
453 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x02000000) != 0))
454 if r: ax.text(p1, -cnt * 1.5,
'Temperature error')
458 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x10000000) != 0))
459 if r: ax.text(p1, -cnt * 1.5,
'Reset Backup Mode')
461 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x20000000) != 0))
462 if r: ax.text(p1, -cnt * 1.5,
'Watchdog Reset')
464 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x30000000) != 0))
465 if r: ax.text(p1, -cnt * 1.5,
'Software Reset')
467 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x40000000) != 0))
468 if r: ax.text(p1, -cnt * 1.5,
'Hardware Reset')
470 ax.plot(instime, -cnt * 1.5 + ((hStatus & 0x80000000) != 0))
471 if r: ax.text(p1, -cnt * 1.5,
'Critical Sys Fault')
476 self.
saveFig(fig,
'Hardware Status')
478 print(RED +
"problem plotting hdwStatus: " + sys.exc_info()[0] + RESET)
480 def gpsStats(self, fig=None, did_gps_pos=DID_GPS1_POS):
485 ax = fig.subplots(4, 1, sharex=
True)
486 if did_gps_pos==DID_GPS1_POS:
490 fig.suptitle(
'GPS ' + str(gps_num) +
' Stats - ' + os.path.basename(os.path.normpath(self.
log.directory)))
499 gStatus = self.
getData(d, did_gps_pos,
'status')
501 ax[0].plot(time, gStatus & 0xFF, label=self.
log.serials[d])
502 ax[1].plot(time, self.
getData(d, did_gps_pos,
'pDop'),
'm', label=
"pDop")
503 ax[1].plot(time, self.
getData(d, did_gps_pos,
'hAcc'),
'r', label="hAcc") 504 ax[1].plot(time, self.getData(d, did_gps_pos, 'vAcc'),
'b', label=
"vAcc")
505 if self.
log.data[d, DID_GPS1_RTK_POS]
is not []:
507 ax[1].plot(rtktime, self.
getData(d, DID_GPS1_RTK_POS,
'vAcc'),
'g', label=
"rtkHor")
510 ax[2].plot(time, self.
getData(d, did_gps_pos,
'cnoMean'))
513 ax[3].plot(time, -cnt * 1.5 + ((gStatus & 0x04000000) != 0))
514 p1 = ax[3].get_xlim()[0] + 0.02 * (ax[3].get_xlim()[1] - ax[3].get_xlim()[0])
515 if r: ax[3].text(p1, -cnt * 1.5,
'RTK Positioning Valid')
517 ax[3].plot(time, -cnt * 1.5 + ((gStatus & 0x08000000) != 0))
518 if r: ax[3].text(p1, -cnt * 1.5,
'RTK Compassing Valid (fix & hold)')
520 ax[3].plot(time, -cnt * 1.5 + ((gStatus & 0x00002000) != 0))
521 if r: ax[3].text(p1, -cnt * 1.5,
'GPS Compass Baseline BAD')
523 ax[3].plot(time, -cnt * 1.5 + ((gStatus & 0x00004000) != 0))
524 if r: ax[3].text(p1, -cnt * 1.5,
'GPS Compass Baseline UNSET')
537 self.
gpsStats(fig=fig, did_gps_pos=DID_GPS2_POS)
540 self.
rtkStats(
"Position", DID_GPS1_RTK_POS_REL, fig=fig)
543 self.
rtkStats(
"Compassing", DID_GPS1_RTK_CMP_REL, fig=fig)
551 ax = fig.subplots(n_plots, 1, sharex=
True)
552 fig.suptitle(
'RTK ' + name +
' Stats - ' + os.path.basename(os.path.normpath(self.
log.directory)))
553 self.
configureSubplot(ax[0],
'GPS Fix Type: 2=2D, 3=3D, 10=Single, 11=Float, 12=Fix',
'')
563 if not self.
log.compassing:
565 fixType = self.
getData(d, DID_GPS1_POS,
'status') >> 8 & 0x1F
566 ax[0].plot(gps1PosTime, fixType, label=self.
log.serials[d])
568 fixType = self.
getData(d, relDid,
'arRatio').copy()
569 fixType[(fixType > 3)] = 12
570 fixType[(fixType > 0) & (fixType < 3)] = 11
571 fixType[fixType == 0] = 10
572 ax[0].plot(rtkRelTime, fixType, label=self.
log.serials[d])
573 ax[1].plot(rtkRelTime, self.
getData(d, relDid,
'differentialAge'))
575 ax[2].semilogy(rtkRelTime, np.ones_like(rtkRelTime)*3.0,
'k--')
576 ax[2].semilogy(rtkRelTime, self.
getData(d, relDid,
'arRatio'))
577 dist2base = self.
getData(d, relDid,
'baseToRoverDistance')
578 dist2base[dist2base > 1e5] = np.nan
579 ax[3].plot(rtkRelTime, dist2base)
580 ax[4].plot(rtkRelTime, self.
getData(d, relDid,
'baseToRoverHeading')*180.0/np.pi)
581 ax[5].plot(rtkRelTime, self.
getData(d, relDid,
'baseToRoverHeadingAcc')*180.0/np.pi)
589 self.
saveFig(fig,
'rtk'+name+
'Stats')
594 self.
rtkMisc(
"Position", DID_GPS1_RTK_POS_MISC, fig=fig)
597 self.
rtkMisc(
"Position", DID_GPS1_RTK_CMP_MISC, fig=fig)
605 ax = fig.subplots(5, 2, sharex=
True)
606 fig.suptitle(
'RTK ' + name +
' Misc - ' + os.path.basename(os.path.normpath(self.
log.directory)))
621 ax[0,0].plot(rtkMiscTime, self.
getData(d, miscDid,
'correctionChecksumFailures'))
622 ax[1,0].plot(rtkMiscTime, self.
getData(d, miscDid,
'timeToFirstFixMs')*0.001)
623 ax[2,0].plot(rtkMiscTime, self.
getData(d, miscDid,
'roverGpsObservationCount'))
624 ax[3,0].plot(rtkMiscTime, self.
getData(d, miscDid,
'baseGpsObservationCount'))
625 ax[4,0].plot(rtkMiscTime, self.
getData(d, miscDid,
'roverGlonassObservationCount'))
626 ax[0,1].plot(rtkMiscTime, self.
getData(d, miscDid,
'baseGlonassObservationCount'))
627 ax[1,1].plot(rtkMiscTime, self.
getData(d, miscDid,
'roverGalileoObservationCount'))
628 ax[2,1].plot(rtkMiscTime, self.
getData(d, miscDid,
'baseGalileoObservationCount'))
629 ax[3,1].plot(rtkMiscTime, self.
getData(d, miscDid,
'baseSbasCount'))
630 ax[4,1].plot(rtkMiscTime, self.
getData(d, miscDid,
'baseAntennaCount'))
645 self.
saveFig(fig,
'rtk'+name+
'Misc')
655 ax = fig.subplots(3, 1, sharex=
True)
656 fig.suptitle(
'RTK Rel - ' + os.path.basename(os.path.normpath(self.
log.directory)))
662 ax[0].plot(rtkRelTime, self.
getData(d, DID_GPS1_RTK_POS_REL,
'baseToRoverHeading')*RAD2DEG)
663 ax[1].plot(rtkRelTime, self.
getData(d, DID_GPS1_RTK_POS_REL,
'baseToRoverDistance'))
673 ax = fig.subplots(6, 1, sharex=
True)
680 fig.suptitle(
'PQR - ' + os.path.basename(os.path.normpath(self.
log.directory)))
689 I1 = self.
getData(d, DID_DUAL_IMU,
'I')[:,0]
690 I2 = self.
getData(d, DID_DUAL_IMU,
'I')[:,1]
697 if np.shape(I1)[0] != 0:
698 time = self.
getData(d, DID_DUAL_IMU,
'time')
699 for i
in range(0, len(I1)):
700 p0.append(I1[i][0][0]*RAD2DEG)
701 q0.append(I1[i][0][1]*RAD2DEG)
702 r0.append(I1[i][0][2]*RAD2DEG)
703 p1.append(I2[i][0][0]*RAD2DEG)
704 q1.append(I2[i][0][1]*RAD2DEG)
705 r1.append(I2[i][0][2]*RAD2DEG)
707 time = self.
getData(d, DID_PREINTEGRATED_IMU,
'time')
708 dt = self.
getData(d, DID_PREINTEGRATED_IMU,
'dt')
709 pqr0 = self.
getData(d, DID_PREINTEGRATED_IMU,
'theta1')
710 pqr1 = self.
getData(d, DID_PREINTEGRATED_IMU,
'theta2')
711 p0 = pqr0[:,0] / dt*RAD2DEG
712 q0 = pqr0[:,1] / dt*RAD2DEG
713 r0 = pqr0[:,2] / dt*RAD2DEG
714 p1 = pqr1[:,0] / dt*RAD2DEG
715 q1 = pqr1[:,1] / dt*RAD2DEG
716 r1 = pqr1[:,2] / dt*RAD2DEG
718 ax[0].plot(time, p0, label=self.
log.serials[d])
719 ax[1].plot(time, p1, label=self.
log.serials[d])
732 ax = fig.subplots(6, 1, sharex=
True)
739 fig.suptitle(
'Accelerometer - ' + os.path.basename(os.path.normpath(self.
log.directory)))
741 I1 = self.
getData(d, DID_DUAL_IMU,
'I')[:,0]
742 I2 = self.
getData(d, DID_DUAL_IMU,
'I')[:,1]
750 if np.shape(I1)[0] != 0:
751 if len(self.
getData(d, DID_GPS1_POS,
'towOffset')) == 0:
752 time = self.
getData(d, DID_DUAL_IMU,
'time')
754 time = self.
getData(d, DID_DUAL_IMU,
'time') + self.
getData(d, DID_GPS1_POS,
'towOffset')[-1]
755 for i
in range(0, len(I1)):
756 acc0x.append(I1[i][1][0])
757 acc0y.append(I1[i][1][1])
758 acc0z.append(I1[i][1][2])
759 acc1x.append(I2[i][1][0])
760 acc1y.append(I2[i][1][1])
761 acc1z.append(I2[i][1][2])
763 if len(self.
getData(d, DID_GPS1_POS,
'towOffset')) == 0:
764 time = self.
getData(d, DID_PREINTEGRATED_IMU,
'time')
766 time = self.
getData(d, DID_PREINTEGRATED_IMU,
'time') + self.
getData(d, DID_GPS1_POS,
'towOffset')[-1]
767 dt = self.
getData(d, DID_PREINTEGRATED_IMU,
'dt')
768 acc0 = self.
getData(d, DID_PREINTEGRATED_IMU,
'vel1')
769 acc1 = self.
getData(d, DID_PREINTEGRATED_IMU,
'vel2')
770 acc0x = acc0[:,0] / dt
771 acc0y = acc0[:,1] / dt
772 acc0z = acc0[:,2] / dt
773 acc1x = acc1[:,0] / dt
774 acc1y = acc1[:,1] / dt
775 acc1z = acc1[:,2] / dt
777 ax[0].plot(time, acc0x, label=self.
log.serials[d])
778 ax[1].plot(time, acc1x)
779 ax[2].plot(time, acc0y)
780 ax[3].plot(time, acc1y)
781 ax[4].plot(time, acc0z)
782 ax[5].plot(time, acc1z)
791 ax = fig.subplots(3, 2, sharex=
True)
802 fig.suptitle(
'Power Spectrum Density - ' + os.path.basename(os.path.normpath(self.
log.directory)))
804 I1 = self.
getData(d, DID_DUAL_IMU,
'I')[:,0]
805 I2 = self.
getData(d, DID_DUAL_IMU,
'I')[:,1]
813 if np.shape(I1)[0] != 0:
814 time = self.
getData(d, DID_DUAL_IMU,
'time')
816 for i
in range(0, len(I1)):
817 acc0x.append(I1[i][1][0])
818 acc0y.append(I1[i][1][1])
819 acc0z.append(I1[i][1][2])
820 acc1x.append(I2[i][1][0])
821 acc1y.append(I2[i][1][1])
822 acc1z.append(I2[i][1][2])
824 sp = np.fft.fft(acc0x)
825 freq = np.fft.fftfreq(time.shape[-1])
829 time = self.
getData(d, DID_PREINTEGRATED_IMU,
'time')
830 dt = self.
getData(d, DID_PREINTEGRATED_IMU,
'dt')
831 acc0 = self.
getData(d, DID_PREINTEGRATED_IMU,
'vel1')
832 acc1 = self.
getData(d, DID_PREINTEGRATED_IMU,
'vel2')
833 acc0x = acc0[:,0] / dt
834 acc0y = acc0[:,1] / dt
835 acc0z = acc0[:,2] / dt
836 acc1x = acc1[:,0] / dt
837 acc1y = acc1[:,1] / dt
838 acc1z = acc1[:,2] / dt
840 psd0 = np.zeros((N//2, 3))
841 psd1 = np.zeros((N//2, 3))
844 f = np.linspace(0, 0.5*Fs, N // 2)
847 sp0 = np.fft.fft(acc0[:,i] / dt / 9.8)
852 psd0[:,i] = 1/N/Fs * np.abs(sp0)**2
853 psd0[1:-1,i] = 2 * psd0[1:-1,i]
854 sp1 = np.fft.fft(acc1[:,i] / dt / 9.8)
859 psd1[:,i] = 1/N/Fs * np.abs(sp1)**2
860 psd1[1:-1,i] = 2 * psd1[1:-1,i]
865 ax[0,0].loglog(f, psd0[:,0])
866 ax[1,0].loglog(f, psd0[:,1])
867 ax[2,0].loglog(f, psd0[:,2])
868 ax[0,1].loglog(f, psd1[:,0])
869 ax[1,1].loglog(f, psd1[:,1])
870 ax[2,1].loglog(f, psd1[:,2])
874 ax[0,0].set_xlim(xlim)
875 ax[1,0].set_xlim(xlim)
876 ax[2,0].set_xlim(xlim)
877 ax[0,1].set_xlim(xlim)
878 ax[1,1].set_xlim(xlim)
879 ax[2,1].set_xlim(xlim)
887 ax[0,0].legend(ncol=2)
896 ax = fig.subplots(6, 1, sharex=
True)
904 fig.suptitle(
'Magnetometer - ' + os.path.basename(os.path.normpath(self.
log.directory)))
906 time0 = self.
getData(d, DID_MAGNETOMETER_1,
'time') + self.
getData(d, DID_GPS1_POS,
'towOffset')[-1]
907 mag0 = self.
getData(d, DID_MAGNETOMETER_1,
'mag')
911 ax[0].plot(time0, mag0x, label=self.
log.serials[d])
912 ax[2].plot(time0, mag0y)
913 ax[4].plot(time0, mag0z)
918 self.
saveFig(fig,
'magnetometer')
925 ax = fig.subplots(2, 1, sharex=
True)
926 fig.suptitle(
'Temperature - ' + os.path.basename(os.path.normpath(self.
log.directory)))
930 ax[0].plot(time, self.
getData(d, DID_SYS_PARAMS,
'imuTemp'), label=self.
log.serials[d])
931 ax[1].plot(time, self.
getData(d, DID_SYS_PARAMS,
'baroTemp'))
936 print(RED +
"problem plotting temp: " + sys.exc_info()[0] + RESET)
941 ax = fig.subplots(5,2, sharex=
True)
942 fig.suptitle(
'Debug float Array - ' + os.path.basename(os.path.normpath(self.
log.directory)))
944 debug_f = self.
getData(d, DID_DEBUG_ARRAY,
'f')
946 ax[i%5, i//5].set_ylabel(
'f[' + str(i) +
']')
947 ax[i%5, i//5].plot(debug_f[:,i], label=self.
log.serials[d])
948 ax[0,0].legend(ncol=2)
956 ax = fig.subplots(5,2, sharex=
True)
957 fig.suptitle(
'Debug int array - ' + os.path.basename(os.path.normpath(self.
log.directory)))
959 debug_i = self.
getData(d, DID_DEBUG_ARRAY,
'i')
961 ax[i%5, i//5].set_ylabel(
'i[' + str(i) +
']')
962 ax[i%5, i//5].plot(debug_i[:,i], label=self.
log.serials[d])
963 ax[0,0].legend(ncol=2)
971 ax = fig.subplots(3,1, sharex=
True)
972 fig.suptitle(
'Debug double Array - ' + os.path.basename(os.path.normpath(self.
log.directory)))
974 debug_lf = self.
getData(d, DID_DEBUG_ARRAY,
'lf')
976 ax[i].set_ylabel(
'lf[' + str(i) +
']')
977 ax[i].plot(debug_lf[:,i], label=self.
log.serials[d])
986 ax = fig.subplots(2, 1, sharex=
True)
987 fig.suptitle(
'Magnetometer Declination - ' + os.path.basename(os.path.normpath(self.
log.directory)))
993 declination = 180.0/np.pi * self.
getData(d, DID_INL2_STATES,
'magDec')
994 inclination = 180.0/np.pi * self.
getData(d, DID_INL2_STATES,
'magInc')
995 ax[0].plot(time, declination, label=self.
log.serials[d])
996 ax[1].plot(time, inclination)
1006 ax = fig.subplots(3, 1, sharex=
True)
1007 fig.suptitle(
'Timestamps - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1013 dtIns = self.
getData(d, DID_INS_2,
'timeOfWeek')[1:] - self.
getData(d, DID_INS_2,
'timeOfWeek')[0:-1]
1014 dtIns = dtIns / self.
d 1017 dtGps = 0.001*(self.
getData(d, DID_GPS1_POS,
'timeOfWeekMs')[1:] - self.
getData(d, DID_GPS1_POS,
'timeOfWeekMs')[0:-1])
1018 dtGps = dtGps / self.
d 1021 dtImu = self.
getData(d, DID_PREINTEGRATED_IMU,
'time')[1:] - self.
getData(d, DID_PREINTEGRATED_IMU,
'time')[0:-1]
1022 dtImu = dtImu / self.
d 1025 ax[0].plot(timeIns, dtIns, label=self.
log.serials[d])
1026 ax[1].plot(timeGps, dtGps)
1027 ax[2].plot(timeImu, dtImu)
1033 ax[0].legend(ncol=2)
1036 self.
saveFig(fig,
'deltatime')
1042 ax = fig.subplots(6, 1, sharex=
True)
1043 fig.suptitle(
'Timestamps - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1047 self.
configureSubplot(ax[3],
'GPS1 Raw Number of Satellites Observed',
's')
1048 self.
configureSubplot(ax[4],
'GPS2 Raw Number of Satellites Observed',
's')
1049 self.
configureSubplot(ax[5],
'GPS Base Raw Number of Satellites Observed',
's')
1052 N1 = len(self.
log.data[d, DID_GPS1_RAW][0])
1053 N2 = len(self.
log.data[d, DID_GPS2_RAW][0])
1054 NB = len(self.
log.data[d, DID_GPS_BASE_RAW][0])
1055 tgps1 = np.zeros(N1)
1056 nsat1 = np.zeros(N1)
1057 tgps2 = np.zeros(N2)
1058 nsat2 = np.zeros(N2)
1059 tgpsB = np.zeros(NB)
1060 nsatB = np.zeros(NB)
1062 for iobs
in range(N1):
1063 ns = round(len(self.
log.data[d, DID_GPS1_RAW][0][iobs]) * 0.5)
1064 t0 = self.
log.data[d, DID_GPS1_RAW][0][iobs][
'time'][
'time'][-1] + \
1065 self.
log.data[d, DID_GPS1_RAW][0][iobs][
'time'][
'sec'][-1]
1066 nsat1[cnt] = nsat1[cnt] + ns
1069 t1 = self.
log.data[d, DID_GPS1_RAW][0][iobs + 1][
'time'][
'time'][-1] + \
1070 self.
log.data[d, DID_GPS1_RAW][0][iobs + 1][
'time'][
'sec'][-1]
1073 tgps1 = tgps1[0: cnt + 1]
1074 nsat1 = nsat1[0: cnt + 1]
1076 for iobs
in range(N2):
1077 ns = round(len(self.
log.data[d, DID_GPS2_RAW][0][iobs]) * 0.5)
1078 t0 = self.
log.data[d, DID_GPS2_RAW][0][iobs][
'time'][
'time'][-1] + \
1079 self.
log.data[d, DID_GPS2_RAW][0][iobs][
'time'][
'sec'][-1]
1080 nsat2[cnt] = nsat2[cnt] + ns
1083 t1 = self.
log.data[d, DID_GPS2_RAW][0][iobs + 1][
'time'][
'time'][-1] + \
1084 self.
log.data[d, DID_GPS2_RAW][0][iobs + 1][
'time'][
'sec'][-1]
1087 tgps2 = tgps2[0: cnt + 1]
1088 nsat2 = nsat2[0: cnt + 1]
1090 for iobs
in range(NB):
1091 ns = round(len(self.
log.data[d, DID_GPS_BASE_RAW][0][iobs]) * 0.5)
1092 t0 = self.
log.data[d, DID_GPS_BASE_RAW][0][iobs][
'time'][
'time'][-1] + \
1093 self.
log.data[d, DID_GPS_BASE_RAW][0][iobs][
'time'][
'sec'][-1]
1094 nsatB[cnt] = nsatB[cnt] + ns
1097 t1 = self.
log.data[d, DID_GPS_BASE_RAW][0][iobs + 1][
'time'][
'time'][-1] + \
1098 self.
log.data[d, DID_GPS_BASE_RAW][0][iobs + 1][
'time'][
'sec'][-1]
1101 tgpsB = tgpsB[0: cnt + 1]
1102 nsatB = nsatB[0: cnt + 1]
1103 dtGps1 = tgps1[1:] - tgps1[0:-1]
1105 dtGps2 = tgps2[1:] - tgps2[0:-1]
1107 dtGpsB = tgpsB[1:] - tgpsB[0:-1]
1109 ax[0].plot(tgps1[1:], dtGps1, label=self.
log.serials[d])
1110 ax[1].plot(tgps2[1:], dtGps2)
1111 ax[2].plot(tgpsB[1:], dtGpsB)
1112 ax[3].plot(tgps1, nsat1, label=self.
log.serials[d])
1113 ax[4].plot(tgps2, nsat2)
1114 ax[5].plot(tgpsB, nsatB)
1123 ax[0].legend(ncol=2)
1126 self.
saveFig(fig,
'gpsRawTime')
1131 ax = fig.subplots(4, 2, sharex=
True)
1140 fig.suptitle(
'EKF Biases - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1143 ax[0,0].plot(time, self.
getData(d, DID_INL2_STATES,
'biasPqr')[:, 0]*180.0/np.pi, label=self.
log.serials[d])
1144 ax[1,0].plot(time, self.
getData(d, DID_INL2_STATES,
'biasPqr')[:, 1]*180.0/np.pi)
1145 ax[2,0].plot(time, self.
getData(d, DID_INL2_STATES,
'biasPqr')[:, 2]*180.0/np.pi)
1146 ax[3,0].plot(time, self.
getData(d, DID_INL2_STATES,
'biasBaro'), label=self.
log.serials[d])
1148 ax[0,1].plot(time, self.
getData(d, DID_INL2_STATES,
'biasAcc')[:, 0], label=self.
log.serials[d])
1149 ax[1,1].plot(time, self.
getData(d, DID_INL2_STATES,
'biasAcc')[:, 1])
1150 ax[2,1].plot(time, self.
getData(d, DID_INL2_STATES,
'biasAcc')[:, 2])
1152 ax[0,0].legend(ncol=2)
1156 self.
saveFig(fig,
'ekfBiases')
1163 did = DID_RTK_PHASE_RESIDUAL
1164 elif type ==
'code':
1165 did = DID_RTK_CODE_RESIDUAL
1167 sat_ids = np.unique(self.
log.data[0, did][
'sat_id_j'])
1168 sat_ids = sat_ids[sat_ids != 0][page*6:(page+1)*6]
1170 ax = fig.subplots(6, 1, sharex=
True)
1171 fig.suptitle(type +
' Residuals Page ' + str(page+1) +
' - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1173 for i, id
in enumerate(sat_ids):
1174 if id == 0:
continue 1175 ax[i].set_ylabel(str(id))
1177 idx = np.where(self.
getData(d, did,
'sat_id_j') == id)
1179 sat_state_idx = idx[1]
1181 residuals = self.
getData(d, did,
'v')[time_idx, sat_state_idx]
1182 residuals[np.abs(residuals) > 1e6] = np.nan
1183 ax[i].plot(time, residuals, label=self.
log.serials[d])
1184 ax[0].legend(ncol=2)
1190 fields = list(self.
log.data[0, DID_RTK_DEBUG].dtype.names)
1191 fields.remove(
'time')
1193 for field
in fields:
1194 dat = self.
log.data[0, DID_RTK_DEBUG][field][0]
1195 if isinstance(dat, np.ndarray):
1196 num_plots += len(dat)
1201 rows = math.ceil(num_plots/float(cols))
1202 ax = fig.subplots(rows, cols, sharex=
True)
1203 fig.suptitle(
'RTK Debug Counters - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1207 valid = time > datetime.datetime.strptime(
'2017',
"%Y")
1211 time = np.arange(0, len(time))
1214 for field
in fields:
1215 data = self.
getData(d, DID_RTK_DEBUG, field)[valid]
1216 if (len(data) == 0):
1218 if isinstance(data[0], np.ndarray):
1219 for j
in range(len(data[0])):
1220 ax[ i%rows, i//rows].set_title(field +
"_" + str(j))
1221 ax[ i % rows, i // rows ].plot(time[valid], data[:,j], label=self.
log.serials[d])
1224 ax[i % rows, i // rows].set_title(field)
1225 ax[i % rows, i // rows].title.set_fontsize(8)
1228 ax[i % rows, i // rows].plot(time[valid], data, label=self.
log.serials[d])
1230 ax[0,0].legend(ncol=2)
1236 ax = fig.subplots(6, 4, sharex=
True)
1239 max_num_biases = self.
getData(0, DID_RTK_DEBUG_2,
'num_biases')[-1]
1240 for r
in range(0,6):
1241 for c
in range(0,4):
1244 fig.suptitle(
'RTK Debug2 - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1248 for r
in range(0, 6):
1249 for c
in range(0, 4):
1250 if ib < max_num_biases:
1251 ax[r,c].plot(time, self.
getData(d, DID_RTK_DEBUG_2,
'satBiasFloat')[:, c + r * 4], label=self.
log.serials[d])
1257 ax[r1,c1].legend(ncol=2)
1267 ax = fig.subplots(6, 4, sharex=
True)
1269 max_num_biases = self.
getData(0, DID_RTK_DEBUG_2,
'num_biases')[-1]
1270 for r
in range(0,6):
1271 for c
in range(0,4):
1274 fig.suptitle(
'RTK Debug2 - Sat# - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1278 for r
in range(0, 6):
1279 for c
in range(0, 4):
1280 if ib < max_num_biases:
1281 ax[r,c].plot(time, self.
getData(d, DID_RTK_DEBUG_2,
'sat')[:, c + r * 4], label=self.
log.serials[d])
1287 ax[r1,c1].legend(ncol=2)
1297 ax = fig.subplots(6, 4, sharex=
True)
1299 max_num_biases = self.
getData(0, DID_RTK_DEBUG_2,
'num_biases')[-1]
1300 for r
in range(0,6):
1301 for c
in range(0,4):
1304 fig.suptitle(
'RTK Debug 2 - Sat Bias Std - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1308 for r
in range(0, 6):
1309 for c
in range(0, 4):
1310 if ib < max_num_biases:
1311 ax[r,c].plot(time, self.
getData(d, DID_RTK_DEBUG_2,
'satBiasStd')[:, c + r * 4], label=self.
log.serials[d])
1317 ax[r1,c1].legend(ncol=2)
1327 ax = fig.subplots(6, 4, sharex=
True)
1329 max_num_biases = self.
getData(0, DID_RTK_DEBUG_2,
'num_biases')[-1]
1330 for r
in range(0,6):
1331 for c
in range(0,4):
1334 fig.suptitle(
'RTK Debug 2 - Lock Count - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1338 for r
in range(0, 6):
1339 for c
in range(0, 4):
1340 if ib < max_num_biases:
1341 ax[r,c].plot(time, self.
getData(d, DID_RTK_DEBUG_2,
'satLockCnt')[:, c + r * 4], label=self.
log.serials[d])
1347 ax[r1,c1].legend(ncol=2)
1357 fig.suptitle(
'Wheel Encoder - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1358 ax = fig.subplots(4, 1, sharex=
True)
1359 titles = [
'Left Wheel Angle',
'Right Wheel Angle',
'Left Wheel Velocity',
'Right Wheel Velocity']
1360 fields = [
'theta_l',
'theta_r',
'omega_l',
'omega_r']
1364 for i, a
in enumerate(ax):
1365 a.plot(time, self.
getData(d, DID_WHEEL_ENCODER, fields[i]), label=self.
log.serials[d])
1369 for i, a
in enumerate(ax):
1370 a.set_ylabel(fields[i])
1371 a.set_title(titles[i])
1382 if __name__ ==
'__main__':
1383 np.set_printoptions(linewidth=200)
1384 home = expanduser(
"~")
1385 file = open(home +
"/Documents/Inertial_Sense/config.yaml",
'r') 1386 config = yaml.load(file) 1387 directory = config["directory"]
1388 directory =
"/home/superjax/Code/IS-src/cpp/SDK/CLTool/build/IS_logs" 1389 directory =
r"C:\Users\quaternion\Downloads\20181218_Compass_Drive\20181218 Compass Drive\20181218_101023" 1390 serials = config[
'serials']
1393 log2.load(directory, serials)
1396 plotter.setDownSample(5)
def insStatus(self, fig=None)
def rtkCmpStats(self, fig=None)
def velUVW(self, fig=None)
def debuglfArr(self, fig=None)
def quatRotVectArray(q, v)
def rtkResiduals(self, type, page, fig=None)
def deltatime(self, fig=None)
def attitude(self, fig=None)
def rtkDebug2Std(self, fig=None)
def setActiveSerials(self, serials)
def setPlotYSpanMin(self, ax, limit)
def rtkPosMisc(self, fig=None)
def imuPQR(self, fig=None)
def imuPSD(self, fig=None)
def getData(self, dev, DID, field)
def rtkPosStats(self, fig=None)
def rtkMisc(self, name, miscDid, fig=None)
GeneratorWrapper< T > range(T const &start, T const &end, T const &step)
def debugfArr(self, fig=None)
def imuAcc(self, fig=None)
def rtkDebug2Lock(self, fig=None)
def magnetometer(self, fig=None)
def hdwStatus(self, fig=None)
def rtkDebug2Sat(self, fig=None)
def posNED(self, fig=None)
def gpsStats(self, fig=None, did_gps_pos=DID_GPS1_POS)
def __init__(self, show, save, format, log)
def rotate_ecef2ned(latlon)
def llaGps(self, fig=None)
def rtkStats(self, name, relDid, fig=None)
def configureSubplot(self, ax, title, xlabel)
def drawNEDMapArrow(self, ax, ned, heading)
def wheelEncoder(self, fig=None)
def rtkCmpMisc(self, fig=None)
def debugiArr(self, fig=None)
def saveFig(self, fig, name)
def magDec(self, fig=None)
def posNEDMap(self, fig=None)
def rtkDebug(self, fig=None)
def posLLA(self, fig=None)
def ekfBiases(self, fig=None)
def setDownSample(self, dwns)
def velNED(self, fig=None)
def rtkDebug2(self, fig=None)
def gpsRawTime(self, fig=None)
def gps2Stats(self, fig=None)
def heading(self, fig=None)
def rtkRel(self, fig=None)