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'))
680 I1 = self.
getData(d, DID_DUAL_IMU,
'I')[:, 0]
681 I2 = self.
getData(d, DID_DUAL_IMU,
'I')[:, 1]
682 time = self.
getData(d, DID_DUAL_IMU,
'time')
683 if np.shape(I1)[0] == 0:
684 I1 = self.
getData(d, DID_DUAL_IMU_RAW,
'I')[:, 0]
685 I2 = self.
getData(d, DID_DUAL_IMU_RAW,
'I')[:, 1]
686 time = self.
getData(d, DID_DUAL_IMU_RAW,
'time')
688 if np.shape(I1)[0] != 0:
689 dt = time[1:] - time[:-1]
690 dt = np.append(dt, dt[-1])
691 for i
in range(0, len(I1)):
692 imu0.append(I1[i][index])
693 imu1.append(I2[i][index])
694 imu0 = np.array(imu0)
695 imu1 = np.array(imu1)
698 imu0 = self.
getData(d, DID_PREINTEGRATED_IMU,
'theta1')
699 imu1 = self.
getData(d, DID_PREINTEGRATED_IMU,
'theta2')
701 imu0 = self.
getData(d, DID_PREINTEGRATED_IMU,
'vel1')
702 imu1 = self.
getData(d, DID_PREINTEGRATED_IMU,
'vel2')
703 time = self.
getData(d, DID_PREINTEGRATED_IMU,
'time')
705 dt = time[1:] - time[:-1]
706 dt = np.append(dt, dt[-1])
711 return (imu0, imu1, time, dt)
716 ax = fig.subplots(3, 2, sharex=
True)
723 fig.suptitle(
'PQR - ' + os.path.basename(os.path.normpath(self.
log.directory)))
725 (pqr0, pqr1, time, dt) = self.
loadGyros(d)
728 ax[i, 0].plot(time, pqr0[:, 0], label=self.
log.serials[d])
729 ax[i, 1].plot(time, pqr1[:, 1], label=self.
log.serials[d])
731 ax[0,0].legend(ncol=2)
740 ax = fig.subplots(3, 2, sharex=
True)
747 fig.suptitle(
'Accelerometer - ' + os.path.basename(os.path.normpath(self.
log.directory)))
752 ax[i, 0].plot(time, acc0[:, 0], label=self.
log.serials[d])
753 ax[i, 1].plot(time, acc1[:, 1], label=self.
log.serials[d])
755 ax[0,0].legend(ncol=2)
764 ax = fig.subplots(3, 2, sharex=
True)
771 fig.suptitle(
'Power Spectral Density - ' + os.path.basename(os.path.normpath(self.
log.directory)))
776 psd0 = np.zeros((N//2, 3))
777 psd1 = np.zeros((N//2, 3))
780 f = np.linspace(0, 0.5*Fs, N // 2)
783 sp0 = np.fft.fft(acc0[:,i] / 9.8)
788 psd0[:,i] = 1/N/Fs * np.abs(sp0)**2
789 psd0[1:-1,i] = 2 * psd0[1:-1,i]
790 sp1 = np.fft.fft(acc1[:,i] / 9.8)
795 psd1[:,i] = 1/N/Fs * np.abs(sp1)**2
796 psd1[1:-1,i] = 2 * psd1[1:-1,i]
801 ax[i, 0].plot(f, 10*np.log10(psd0[:, i]))
802 ax[i, 1].plot(f, 10*np.log10(psd1[:, i]))
804 ax[0,0].legend(ncol=2)
813 ax = fig.subplots(3, 2, sharex=
True)
820 fig.suptitle(
'Power Spectral Density - ' + os.path.basename(os.path.normpath(self.
log.directory)))
822 (pqr0, pqr1, time, dt) = self.
loadGyros(d)
826 psd0 = np.zeros((Nhalf, 3))
827 psd1 = np.zeros((Nhalf, 3))
830 f = np.linspace(0, 0.5*Fs, Nhalf)
833 sp0 = np.fft.fft(pqr0[:,i] * 180.0/np.pi)
838 psd0[:,i] = 1/N/Fs * np.abs(sp0)**2
839 psd0[1:-1,i] = 2 * psd0[1:-1,i]
841 sp1 = np.fft.fft(pqr1[:,i] * 180.0/np.pi)
846 psd1[:,i] = 1/N/Fs * np.abs(sp1)**2
847 psd1[1:-1,i] = 2 * psd1[1:-1,i]
850 ax[i, 0].plot(f, 10*np.log10(psd0[:, i]))
851 ax[i, 1].plot(f, 10*np.log10(psd1[:, i]))
853 ax[0,0].legend(ncol=2)
862 ax = fig.subplots(6, 1, sharex=
True)
870 fig.suptitle(
'Magnetometer - ' + os.path.basename(os.path.normpath(self.
log.directory)))
872 time0 = self.
getData(d, DID_MAGNETOMETER_1,
'time') + self.
getData(d, DID_GPS1_POS,
'towOffset')[-1]
873 mag0 = self.
getData(d, DID_MAGNETOMETER_1,
'mag')
877 ax[0].plot(time0, mag0x, label=self.
log.serials[d])
878 ax[2].plot(time0, mag0y)
879 ax[4].plot(time0, mag0z)
884 self.
saveFig(fig,
'magnetometer')
891 ax = fig.subplots(2, 1, sharex=
True)
892 fig.suptitle(
'Temperature - ' + os.path.basename(os.path.normpath(self.
log.directory)))
896 ax[0].plot(time, self.
getData(d, DID_SYS_PARAMS,
'imuTemp'), label=self.
log.serials[d])
897 ax[1].plot(time, self.
getData(d, DID_SYS_PARAMS,
'baroTemp'))
902 print(RED +
"problem plotting temp: " + sys.exc_info()[0] + RESET)
907 ax = fig.subplots(5,2, sharex=
True)
908 fig.suptitle(
'Debug float Array - ' + os.path.basename(os.path.normpath(self.
log.directory)))
910 debug_f = self.
getData(d, DID_DEBUG_ARRAY,
'f')
912 ax[i%5, i//5].set_ylabel(
'f[' + str(i) +
']')
913 ax[i%5, i//5].plot(debug_f[:,i], label=self.
log.serials[d])
914 ax[0,0].legend(ncol=2)
922 ax = fig.subplots(5,2, sharex=
True)
923 fig.suptitle(
'Debug int array - ' + os.path.basename(os.path.normpath(self.
log.directory)))
925 debug_i = self.
getData(d, DID_DEBUG_ARRAY,
'i')
927 ax[i%5, i//5].set_ylabel(
'i[' + str(i) +
']')
928 ax[i%5, i//5].plot(debug_i[:,i], label=self.
log.serials[d])
929 ax[0,0].legend(ncol=2)
937 ax = fig.subplots(3,1, sharex=
True)
938 fig.suptitle(
'Debug double Array - ' + os.path.basename(os.path.normpath(self.
log.directory)))
940 debug_lf = self.
getData(d, DID_DEBUG_ARRAY,
'lf')
942 ax[i].set_ylabel(
'lf[' + str(i) +
']')
943 ax[i].plot(debug_lf[:,i], label=self.
log.serials[d])
952 ax = fig.subplots(2, 1, sharex=
True)
953 fig.suptitle(
'Magnetometer Declination - ' + os.path.basename(os.path.normpath(self.
log.directory)))
959 declination = 180.0/np.pi * self.
getData(d, DID_INL2_STATES,
'magDec')
960 inclination = 180.0/np.pi * self.
getData(d, DID_INL2_STATES,
'magInc')
961 ax[0].plot(time, declination, label=self.
log.serials[d])
962 ax[1].plot(time, inclination)
972 ax = fig.subplots(3, 1, sharex=
True)
973 fig.suptitle(
'Timestamps - ' + os.path.basename(os.path.normpath(self.
log.directory)))
979 dtIns = self.
getData(d, DID_INS_2,
'timeOfWeek')[1:] - self.
getData(d, DID_INS_2,
'timeOfWeek')[0:-1]
980 dtIns = dtIns / self.
d 983 dtGps = 0.001*(self.
getData(d, DID_GPS1_POS,
'timeOfWeekMs')[1:] - self.
getData(d, DID_GPS1_POS,
'timeOfWeekMs')[0:-1])
984 dtGps = dtGps / self.
d 987 dtImu = self.
getData(d, DID_PREINTEGRATED_IMU,
'time')[1:] - self.
getData(d, DID_PREINTEGRATED_IMU,
'time')[0:-1]
988 dtImu = dtImu / self.
d 990 towOffset = self.
getData(d, DID_GPS1_POS,
'towOffset')
991 if np.size(towOffset) > 0:
992 towOffset = towOffset[-1]
997 ax[0].plot(timeIns, dtIns, label=self.
log.serials[d])
998 ax[1].plot(timeGps, dtGps)
999 ax[2].plot(timeImu, dtImu)
1005 ax[0].legend(ncol=2)
1008 self.
saveFig(fig,
'deltatime')
1014 ax = fig.subplots(6, 1, sharex=
True)
1015 fig.suptitle(
'Timestamps - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1019 self.
configureSubplot(ax[3],
'GPS1 Raw Number of Satellites Observed',
's')
1020 self.
configureSubplot(ax[4],
'GPS2 Raw Number of Satellites Observed',
's')
1021 self.
configureSubplot(ax[5],
'GPS Base Raw Number of Satellites Observed',
's')
1024 N1 = len(self.
log.data[d, DID_GPS1_RAW][0])
1025 N2 = len(self.
log.data[d, DID_GPS2_RAW][0])
1026 NB = len(self.
log.data[d, DID_GPS_BASE_RAW][0])
1027 tgps1 = np.zeros(N1)
1028 nsat1 = np.zeros(N1)
1029 tgps2 = np.zeros(N2)
1030 nsat2 = np.zeros(N2)
1031 tgpsB = np.zeros(NB)
1032 nsatB = np.zeros(NB)
1034 for iobs
in range(N1):
1035 ns = round(len(self.
log.data[d, DID_GPS1_RAW][0][iobs]) * 0.5)
1036 t0 = self.
log.data[d, DID_GPS1_RAW][0][iobs][
'time'][
'time'][-1] + \
1037 self.
log.data[d, DID_GPS1_RAW][0][iobs][
'time'][
'sec'][-1]
1038 nsat1[cnt] = nsat1[cnt] + ns
1041 t1 = self.
log.data[d, DID_GPS1_RAW][0][iobs + 1][
'time'][
'time'][-1] + \
1042 self.
log.data[d, DID_GPS1_RAW][0][iobs + 1][
'time'][
'sec'][-1]
1045 tgps1 = tgps1[0: cnt + 1]
1046 nsat1 = nsat1[0: cnt + 1]
1048 for iobs
in range(N2):
1049 ns = round(len(self.
log.data[d, DID_GPS2_RAW][0][iobs]) * 0.5)
1050 t0 = self.
log.data[d, DID_GPS2_RAW][0][iobs][
'time'][
'time'][-1] + \
1051 self.
log.data[d, DID_GPS2_RAW][0][iobs][
'time'][
'sec'][-1]
1052 nsat2[cnt] = nsat2[cnt] + ns
1055 t1 = self.
log.data[d, DID_GPS2_RAW][0][iobs + 1][
'time'][
'time'][-1] + \
1056 self.
log.data[d, DID_GPS2_RAW][0][iobs + 1][
'time'][
'sec'][-1]
1059 tgps2 = tgps2[0: cnt + 1]
1060 nsat2 = nsat2[0: cnt + 1]
1062 for iobs
in range(NB):
1063 ns = round(len(self.
log.data[d, DID_GPS_BASE_RAW][0][iobs]) * 0.5)
1064 t0 = self.
log.data[d, DID_GPS_BASE_RAW][0][iobs][
'time'][
'time'][-1] + \
1065 self.
log.data[d, DID_GPS_BASE_RAW][0][iobs][
'time'][
'sec'][-1]
1066 nsatB[cnt] = nsatB[cnt] + ns
1069 t1 = self.
log.data[d, DID_GPS_BASE_RAW][0][iobs + 1][
'time'][
'time'][-1] + \
1070 self.
log.data[d, DID_GPS_BASE_RAW][0][iobs + 1][
'time'][
'sec'][-1]
1073 tgpsB = tgpsB[0: cnt + 1]
1074 nsatB = nsatB[0: cnt + 1]
1075 dtGps1 = tgps1[1:] - tgps1[0:-1]
1077 dtGps2 = tgps2[1:] - tgps2[0:-1]
1079 dtGpsB = tgpsB[1:] - tgpsB[0:-1]
1081 ax[0].plot(tgps1[1:], dtGps1, label=self.
log.serials[d])
1082 ax[1].plot(tgps2[1:], dtGps2)
1083 ax[2].plot(tgpsB[1:], dtGpsB)
1084 ax[3].plot(tgps1, nsat1, label=self.
log.serials[d])
1085 ax[4].plot(tgps2, nsat2)
1086 ax[5].plot(tgpsB, nsatB)
1095 ax[0].legend(ncol=2)
1098 self.
saveFig(fig,
'gpsRawTime')
1103 ax = fig.subplots(4, 2, sharex=
True)
1112 fig.suptitle(
'EKF Biases - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1115 ax[0,0].plot(time, self.
getData(d, DID_INL2_STATES,
'biasPqr')[:, 0]*180.0/np.pi, label=self.
log.serials[d])
1116 ax[1,0].plot(time, self.
getData(d, DID_INL2_STATES,
'biasPqr')[:, 1]*180.0/np.pi)
1117 ax[2,0].plot(time, self.
getData(d, DID_INL2_STATES,
'biasPqr')[:, 2]*180.0/np.pi)
1118 ax[3,0].plot(time, self.
getData(d, DID_INL2_STATES,
'biasBaro'), label=self.
log.serials[d])
1120 ax[0,1].plot(time, self.
getData(d, DID_INL2_STATES,
'biasAcc')[:, 0], label=self.
log.serials[d])
1121 ax[1,1].plot(time, self.
getData(d, DID_INL2_STATES,
'biasAcc')[:, 1])
1122 ax[2,1].plot(time, self.
getData(d, DID_INL2_STATES,
'biasAcc')[:, 2])
1124 ax[0,0].legend(ncol=2)
1128 self.
saveFig(fig,
'ekfBiases')
1135 did = DID_RTK_PHASE_RESIDUAL
1136 elif type ==
'code':
1137 did = DID_RTK_CODE_RESIDUAL
1139 sat_ids = np.unique(self.
log.data[0, did][
'sat_id_j'])
1140 sat_ids = sat_ids[sat_ids != 0][page*6:(page+1)*6]
1142 ax = fig.subplots(6, 1, sharex=
True)
1143 fig.suptitle(type +
' Residuals Page ' + str(page+1) +
' - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1145 for i, id
in enumerate(sat_ids):
1146 if id == 0:
continue 1147 ax[i].set_ylabel(str(id))
1149 idx = np.where(self.
getData(d, did,
'sat_id_j') == id)
1151 sat_state_idx = idx[1]
1153 residuals = self.
getData(d, did,
'v')[time_idx, sat_state_idx]
1154 residuals[np.abs(residuals) > 1e6] = np.nan
1155 ax[i].plot(time, residuals, label=self.
log.serials[d])
1156 ax[0].legend(ncol=2)
1162 fields = list(self.
log.data[0, DID_RTK_DEBUG].dtype.names)
1163 fields.remove(
'time')
1165 for field
in fields:
1166 dat = self.
log.data[0, DID_RTK_DEBUG][field][0]
1167 if isinstance(dat, np.ndarray):
1168 num_plots += len(dat)
1173 rows = math.ceil(num_plots/float(cols))
1174 ax = fig.subplots(rows, cols, sharex=
True)
1175 fig.suptitle(
'RTK Debug Counters - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1179 valid = time > datetime.datetime.strptime(
'2017',
"%Y")
1183 time = np.arange(0, len(time))
1186 for field
in fields:
1187 data = self.
getData(d, DID_RTK_DEBUG, field)[valid]
1188 if (len(data) == 0):
1190 if isinstance(data[0], np.ndarray):
1191 for j
in range(len(data[0])):
1192 ax[ i%rows, i//rows].set_title(field +
"_" + str(j))
1193 ax[ i % rows, i // rows ].plot(time[valid], data[:,j], label=self.
log.serials[d])
1196 ax[i % rows, i // rows].set_title(field)
1197 ax[i % rows, i // rows].title.set_fontsize(8)
1200 ax[i % rows, i // rows].plot(time[valid], data, label=self.
log.serials[d])
1202 ax[0,0].legend(ncol=2)
1208 ax = fig.subplots(6, 4, sharex=
True)
1211 max_num_biases = self.
getData(0, DID_RTK_DEBUG_2,
'num_biases')[-1]
1212 for r
in range(0,6):
1213 for c
in range(0,4):
1216 fig.suptitle(
'RTK Debug2 - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1220 for r
in range(0, 6):
1221 for c
in range(0, 4):
1222 if ib < max_num_biases:
1223 ax[r,c].plot(time, self.
getData(d, DID_RTK_DEBUG_2,
'satBiasFloat')[:, c + r * 4], label=self.
log.serials[d])
1229 ax[r1,c1].legend(ncol=2)
1239 ax = fig.subplots(6, 4, sharex=
True)
1241 max_num_biases = self.
getData(0, DID_RTK_DEBUG_2,
'num_biases')[-1]
1242 for r
in range(0,6):
1243 for c
in range(0,4):
1246 fig.suptitle(
'RTK Debug2 - Sat# - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1250 for r
in range(0, 6):
1251 for c
in range(0, 4):
1252 if ib < max_num_biases:
1253 ax[r,c].plot(time, self.
getData(d, DID_RTK_DEBUG_2,
'sat')[:, c + r * 4], label=self.
log.serials[d])
1259 ax[r1,c1].legend(ncol=2)
1269 ax = fig.subplots(6, 4, sharex=
True)
1271 max_num_biases = self.
getData(0, DID_RTK_DEBUG_2,
'num_biases')[-1]
1272 for r
in range(0,6):
1273 for c
in range(0,4):
1276 fig.suptitle(
'RTK Debug 2 - Sat Bias Std - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1280 for r
in range(0, 6):
1281 for c
in range(0, 4):
1282 if ib < max_num_biases:
1283 ax[r,c].plot(time, self.
getData(d, DID_RTK_DEBUG_2,
'satBiasStd')[:, c + r * 4], label=self.
log.serials[d])
1289 ax[r1,c1].legend(ncol=2)
1299 ax = fig.subplots(6, 4, sharex=
True)
1301 max_num_biases = self.
getData(0, DID_RTK_DEBUG_2,
'num_biases')[-1]
1302 for r
in range(0,6):
1303 for c
in range(0,4):
1306 fig.suptitle(
'RTK Debug 2 - Lock Count - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1310 for r
in range(0, 6):
1311 for c
in range(0, 4):
1312 if ib < max_num_biases:
1313 ax[r,c].plot(time, self.
getData(d, DID_RTK_DEBUG_2,
'satLockCnt')[:, c + r * 4], label=self.
log.serials[d])
1319 ax[r1,c1].legend(ncol=2)
1329 fig.suptitle(
'Wheel Encoder - ' + os.path.basename(os.path.normpath(self.
log.directory)))
1330 ax = fig.subplots(4, 1, sharex=
True)
1331 titles = [
'Left Wheel Angle',
'Right Wheel Angle',
'Left Wheel Velocity',
'Right Wheel Velocity']
1332 fields = [
'theta_l',
'theta_r',
'omega_l',
'omega_r']
1336 for i, a
in enumerate(ax):
1337 a.plot(time, self.
getData(d, DID_WHEEL_ENCODER, fields[i]), label=self.
log.serials[d])
1341 for i, a
in enumerate(ax):
1342 a.set_ylabel(fields[i])
1343 a.set_title(titles[i])
1354 if __name__ ==
'__main__':
1355 np.set_printoptions(linewidth=200)
1356 home = expanduser(
"~")
1357 file = open(home +
"/Documents/Inertial_Sense/config.yaml",
'r') 1358 config = yaml.load(file) 1359 directory = config["directory"]
1360 directory =
"/home/superjax/Code/IS-src/cpp/SDK/CLTool/build/IS_logs" 1361 directory =
r"C:\Users\quaternion\Downloads\20181218_Compass_Drive\20181218 Compass Drive\20181218_101023" 1362 serials = config[
'serials']
1365 log2.load(directory, serials)
1368 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 accelPSD(self, fig=None)
def deltatime(self, fig=None)
def attitude(self, fig=None)
def rtkDebug2Std(self, fig=None)
def setActiveSerials(self, serials)
def loadIMU(self, d, index)
def setPlotYSpanMin(self, ax, limit)
def rtkPosMisc(self, fig=None)
def imuPQR(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 gyroPSD(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)