# -*- coding: utf-8 -*-
############################################################################
# OpenMMS PCAP Check #
############################################################################
# Version: 1.3.0 #
# Date: June 2020 #
# Author: Ryan Brazeal #
# Email: ryan.brazeal@ufl.edu #
# #
# OPEN-SOURCE LICENSE INFO: #
# #
# This file is part of OpenMMS_OSS. #
# #
# OpenMMS_OSS is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# OpenMMS_OSS is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with OpenMMS_OSS. If not, see . #
# #
############################################################################
import time
import sys
import numpy as np
import os
import struct
import binascii
import matplotlib.pyplot as plt
from datetime import datetime
from tqdm import tqdm
from pathlib import Path
import multiprocessing as mp
totalpacs = 0
badpacs = 0
def iHeartLidar2(logFile):
print("\n XXX XXX ")
time.sleep(0.1)
print(" IIIII X XX XX X L DDDD AAAA RRRRR")
time.sleep(0.1)
print(" I X X X L i D D A A R R")
time.sleep(0.1)
print(" I X X L D D A A R R")
time.sleep(0.1)
print(" I XX XX L i D D AAAAAA RRRRR")
time.sleep(0.1)
print(" I XX XX L i D D A A R R")
time.sleep(0.1)
print(" I XX XX L i D D A A R R")
time.sleep(0.1)
print(" IIIII XXX LLLLLL i DDDD A A R R")
time.sleep(0.1)
print(" X \n\n")
logFile.write("\n XXX XXX \n")
logFile.write(" IIIII X XX XX X L DDDD AAAA RRRRR\n")
logFile.write(" I X X X L i D D A A R R\n")
logFile.write(" I X X L D D A A R R\n")
logFile.write(" I XX XX L i D D AAAAAA RRRRR\n")
logFile.write(" I XX XX L i D D A A R R\n")
logFile.write(" I XX XX L i D D A A R R\n")
logFile.write(" IIIII XXX LLLLLL i DDDD A A R R\n")
logFile.write(" X \n\n")
def OpenMMS1():
print(" _________ _______ _____ ______ ______ ________")
time.sleep(0.1)
print("|\\ ___ \\ ________ ________ ________ |\\ __ \\ __ \\|\\ __ \\ __ \\|\\ ____\\")
time.sleep(0.1)
print("\\|\\ \\_|\\ \\|\\ __ \\|\\ __ \\|\\ ___ \\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\___|_")
time.sleep(0.1)
print(" \\|\\ \\\\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\\\|\\ \\|\\ \\|\\__\\|\\ \\|\\ \\|\\__\\|\\ \\|\\_____ \\")
time.sleep(0.1)
print(" \\|\\ \\\\|\\ \\|\\ ____\\|\\ ____\\|\\ \\\\|\\ \\|\\ \\|__|\\|\\ \\|\\ \\|__|\\|\\ \\|____|\\ \\")
time.sleep(0.1)
print(" \\|\\ \\\\_\\ \\|\\ \\___|\\|\\ \\___|\\|\\ \\\\|\\ \\|\\ \\ \\|\\ \\|\\ \\ \\|\\ \\ __\\_\\ \\")
time.sleep(0.1)
print(" \\|\\________\\|\\__\\ \\|\\______\\\\|\\__\\\\|\\__\\|\\__\\ \\|\\__\\|\\__\\ \\|\\__\\|\\_______\\")
time.sleep(0.1)
print(" \\|________|\\|___| \\|_______|\\|___|\\|__|\\|___| \\|__|\\|___| \\|__|\\|________|\n\n")
def OpenMMS1_log(logFile):
logFile.write(" _________ _______ _____ ______ ______ ________\n")
logFile.write("|\\ ___ \\ ________ ________ ________ |\\ __ \\ __ \\|\\ __ \\ __ \\|\\ ____\\\n")
logFile.write("\\|\\ \\_|\\ \\|\\ __ \\|\\ __ \\|\\ ___ \\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\___|_\n")
logFile.write(" \\|\\ \\\\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\|\\ \\\\|\\ \\|\\ \\|\\__\\|\\ \\|\\ \\|\\__\\|\\ \\|\\_____ \\\n")
logFile.write(" \\|\\ \\\\|\\ \\|\\ ____\\|\\ ____\\|\\ \\\\|\\ \\|\\ \\|__|\\|\\ \\|\\ \\|__|\\|\\ \\|____|\\ \\\n")
logFile.write(" \\|\\ \\\\_\\ \\|\\ \\___|\\|\\ \\___|\\|\\ \\\\|\\ \\|\\ \\ \\|\\ \\|\\ \\ \\|\\ \\ __\\_\\ \\\n")
logFile.write(" \\|\\________\\|\\__\\ \\|\\______\\\\|\\__\\\\|\\__\\|\\__\\ \\|\\__\\|\\__\\ \\|\\__\\|\\_______\\\n")
logFile.write(" \\|________|\\|___| \\|_______|\\|___|\\|__|\\|___| \\|__|\\|___| \\|__|\\|________|\n\n")
def LL2NE(lat1,lon1,lat2,lon2):
lat1 = np.radians(lat1)
lon1 = np.radians(lon1)
lat2 = np.radians(lat2)
lon2 = np.radians(lon2)
R = 6378000.0
dLat = lat2 - lat1
dLon = lon2 - lon1
scR1 = np.cos(lat1) * R
scR2 = np.cos(lat2) * R
scR = (scR1 + scR2) / 2.0
dN = dLat * R
dE = dLon * scR
return dN, dE
#PCAP FILE HEADER (24 bytes)
def readPcapFileHeader(pcap, bytesRead):
b = bytearray(pcap.read(24))
bytesRead += 24
return bytesRead
#PCAP PACKET HEADER (16 bytes)
def readPcapPacketHeader(pcap, bytesRead, numDataPackets, skippedDataPackets, numPosPackets, badPosPackets, numUnrecPackets, foundGoodPos, unpackL, unpackB):
#check to make sure that 16 bytes of data exist before the end of the file
global debug
checkData = bytearray(pcap.read(16))
continueReading = True
packetType = 0
packetData = None
byteSize = 0
if len(checkData) != 16:
continueReading = False
else:
b = checkData[8:12]
incl_length = struct.unpack(' 8:
if GPRMCi[2].upper() == "A":
hh = int(GPRMCi[1][:2]) * 3600
mimi = int(GPRMCi[1][2:4]) * 60
ss = int(GPRMCi[1][4:6])
nmeaTime = np.floor(hh + mimi + ss)
timeStamp1 = np.round((hh + float(unpackL(packetData[240:244])[0]) / 1000000.0),1)
if not foundGoodPos:
if np.floor(timeStamp1) == nmeaTime and pps_statusi == 2:
packetType = 1
foundGoodPos = True
# debug.write("\nFound First Time Match\n\n")
else:
# debug.write("*\n")
pass
else:
if np.abs(timeStamp1 - nmeaTime) < 2 and pps_statusi == 2:
packetType = 1
# debug.write(str(nmeaTime) + " " + str(timeStamp1) + "\n")
else:
# debug.write("-\n")
foundGoodPos = False
else:
badPosPackets += 1
else:
badPosPackets += 1
byteSize = 554
numPosPackets += 1
elif incl_length == 1248: #Data packet
packetData = pcap.read(1248)
# timeStamp = float(unpackL(packetData[1242:1246])[0])
byteSize = 1248
numDataPackets += 1
if foundGoodPos:
packetType = 2
else:
skippedDataPackets += 1
else:
numUnrecPackets += 1
except:
print("\n\n **********************************************************")
print(" ***** AN ERROR OCCURRED WHILE READING THE .PCAP FILE *****")
print(" **********************************************************\n")
continueReading = False
bytesRead += 16
return continueReading, packetType, byteSize, bytesRead, packetData, numDataPackets, skippedDataPackets, numPosPackets, badPosPackets, numUnrecPackets, foundGoodPos
def parseChunk(statusD, lock, chunkID, packetOrder, miscD, epochD, latD, lonD, pps_statusD, timeStamp1D, NMEAdataIndexD, timeStampD, returnModeD, sensorTypeD, goodPtsD):
hemiEmun = {"N":1, "S":-1, "E":1, "W":-1}
NMEAdataIndex = -1
pps_status = [0,0,0,0]
num_points = 0
num_bad_point_blocks = 0
unpackL = struct.Struct(' 9:
descStr += " "
else:
descStr += " "
lock.acquire()
pbar = tqdm(total=len(packetOrder),unit=" packets",desc=descStr,position=chunkID)
lock.release()
for i in range(0,len(packetOrder)):
lock.acquire()
pbar.update()
lock.release()
data = packetOrder[i][1]
#position packet
if packetOrder[i][0] == 1:
timeStamp1 = float(unpackL(data[240:244])[0])
pps_statusi = unpackB(data[244:245])[0]
pps_status[pps_statusi] += 1
GPRMCs = str(data[248:512], 'utf-8').rstrip(' \t\r\n\0')
GPRMCi = GPRMCs.split(",")
if len(GPRMCi) > 8:
yyyy = int(GPRMCi[9][-2:]) + 2000
mm = int(GPRMCi[9][2:4])
dd = int(GPRMCi[9][:2])
hh = int(GPRMCi[1][:2])
mimi = int(GPRMCi[1][2:4])
ss = int(GPRMCi[1][4:6])
epoch = datetime(yyyy,mm,dd,hh,mimi,ss)
lat = hemiEmun[GPRMCi[4]] * (np.float32(GPRMCi[3][:2]) + np.float32(GPRMCi[3][2:]) / 60.0)
lon = hemiEmun[GPRMCi[6]] * (np.float32(GPRMCi[5][:3]) + np.float32(GPRMCi[5][3:]) / 60.0)
epochL.append(epoch)
latL.append(lat)
lonL.append(lon)
timeStamp1L.append(timeStamp1)
NMEAdataIndex += 1
#points (data) packet
elif packetOrder[i][0] == 2:
if NMEAdataIndex > -1:
dataPacketCount += 1
goodPts = 0
timeStamp = float(unpackL(data[1242:1246])[0])
returnMode = unpackB(data[1246:1247])[0] #55 = Single Return(Strongest), 56 = Single Return (Last), 57 = Dual Returns (Strongest and Last)
sensorType = unpackB(data[1247:1248])[0] #33 = Velodyne HDL-32E, 34 = Velodyne VLP-16/Puck Lite
if rotRate == -1.0:
if dataPacketCount > 8000: #calc rot rate after ~ 10 seconds of data collection
azi = float(unpackH(data[44:46])[0])
rotDiff = azi - previousAzi
if rotDiff > 0.0:
dt = timeStamp - previousTime
if dt > 0:
rotRate = (rotDiff * 10000.0) / (dt * 360.0) #in Hertz (Hz))
else:
previousTime = timeStamp
previousAzi = azi
else:
previousTime = timeStamp
previousAzi = azi
for j in range(0,12):
o1 = int(j*100)
if binascii.hexlify(data[42+o1:44+o1]).decode('utf-8').upper() == "FFEE":
for k in range(0,2):
o2 = o1 + int(k*48)
for m in range(0,16):
o3 = o2 + int(m*3)
dist,intensity = unpackHB(data[46+o3:49+o3])
if not dist:
goodPts += 1
num_points += 1
else:
num_bad_point_blocks += 1
NMEAdataIndexL.append(NMEAdataIndex)
timeStampL.append(timeStamp)
returnModeL.append(returnMode)
sensorTypeL.append(sensorType)
goodPtsL.append(goodPts)
miscD[chunkID] = [num_points, 0, num_bad_point_blocks, rotRate]
epochD[chunkID] = epochL
latD[chunkID] = latL
lonD[chunkID] = lonL
pps_statusD[chunkID] = pps_status
timeStamp1D[chunkID] = timeStamp1L
NMEAdataIndexD[chunkID] = NMEAdataIndexL
timeStampD[chunkID] = timeStampL
returnModeD[chunkID] = returnModeL
sensorTypeD[chunkID] = sensorTypeL
goodPtsD[chunkID] = goodPtsL
statusD[chunkID] = 1
shouldStop = False
numProcesses = len(statusD)
while not shouldStop:
shouldStop = True
for i in range(0,numProcesses):
if statusD[i] == 0:
shouldStop = False
break
if shouldStop:
shouldStop = False
if chunkID == 0:
statusD[chunkID] = 2
shouldStop = True
else:
if statusD[chunkID-1] == 2:
statusD[chunkID] = 2
shouldStop = True
lock.acquire()
pbar.close()
lock.release()
debug = None
def main(pcap_filename):
print()
global debug
numCores = mp.cpu_count() - 1
#for debugging
# numCores = 1
pcapPath = Path(pcap_filename)
pcapName = pcapPath.name
filePath = pcapPath.parents[0]
OpenMMS1()
timeStart = time.time()
timeNow = time.localtime()
timeStr = str(timeNow[0]) + "_" + str(timeNow[1]) + "_" + str(timeNow[2]) + "_" + str(timeNow[3]) + "_" + str(timeNow[4]) + "_" + str(timeNow[5])
log_filename = "PCAP CHECK RESULTS - " + timeStr + ".log"
print("*** Note: Results written to file --> '" + log_filename + "' ***")
log_filename = filePath / log_filename
bytesRead = 0
pcapSize = os.path.getsize(pcap_filename)
pcapfile = open(pcap_filename, 'rb')
bytesRead = readPcapFileHeader(pcapfile, bytesRead)
numDataPackets = 0
numPosPackets = 0
numUnrecPackets = 0
skippedDataPackets = 0
badPosPackets = 0
foundGoodPos = False
safeToRead = True
packetOrder = []
unpackL = struct.Struct(' 100000:
# break
pbar.update(pcapSize - pbar.n)
pbar.close()
#for debugging purposes
# numDataPackets = 0
designNum = 0
foundStuff = False
if numDataPackets == 0 or numPosPackets == 0:
print("\n\n****************************************************************")
print("**************** NO DATA FOUND IN THE PCAP FILE ****************")
print("****************************************************************\n\n")
else:
foundStuff = True
if numCores > 0:
run = True
while run:
designNum = (numDataPackets - skippedDataPackets) // numCores
if designNum < 10000:
numCores -= 1
if numCores == 0:
numCores = 1
run = False
else:
run = False
else:
print("\n\n****************************************************************")
print("************* COULD NOT READ CPU INFORMATION, ODD? *************")
print("****************************************************************\n\n")
foundStuff = False
if foundStuff:
NMEAdataIndex = -1
NMEAdata = []
pps_status = [0,0,0,0]
pointData = []
distData = []
num_points = 0
num_bad_point_blocks = 0
previousAzi = 36100.0
previousTime = 0.0
rotRate = -1.0
if numCores == 1:
print("\n\nParsing observations from binary packet data using 1 CPU core\n")
pbar = tqdm(total=len(packetOrder),unit=' packets')
for i in range(0,len(packetOrder)):
pbar.update(1)
data = packetOrder[i][1]
#position packet
if packetOrder[i][0] == 1:
timeStamp1 = float(unpackL(data[240:244])[0])
pps_statusi = unpackB(data[244:245])[0]
pps_status[pps_statusi] += 1
GPRMCs = str(data[248:512], 'utf-8').rstrip(' \t\r\n\0')
GPRMCi = GPRMCs.split(",")
if len(GPRMCi) > 8:
yyyy = int(GPRMCi[9][-2:]) + 2000
mm = int(GPRMCi[9][2:4])
dd = int(GPRMCi[9][:2])
hh = int(GPRMCi[1][:2])
mimi = int(GPRMCi[1][2:4])
ss = int(GPRMCi[1][4:6])
epoch = datetime(yyyy,mm,dd,hh,mimi,ss)
lat = hemiEmun[GPRMCi[4]] * (np.float32(GPRMCi[3][:2]) + np.float32(GPRMCi[3][2:]) / 60.0)
lon = hemiEmun[GPRMCi[6]] * (np.float32(GPRMCi[5][:3]) + np.float32(GPRMCi[5][3:]) / 60.0)
NMEAdata.append([epoch,lat,lon,timeStamp1])
NMEAdataIndex += 1
#points (data) packet
elif packetOrder[i][0] == 2:
if NMEAdataIndex > -1:
goodPts = 0
timeStamp = float(unpackL(data[1242:1246])[0])
returnMode = unpackB(data[1246:1247])[0] #55 = Single Return(Strongest), 56 = Single Return (Last), 57 = Dual Returns (Strongest and Last)
sensorType = unpackB(data[1247:1248])[0] #33 = Velodyne HDL-32E, 34 = Velodyne VLP-16/Puck Lite
if rotRate == -1.0:
if len(pointData) > 8000: #calc rot rate after ~ 10 seconds of data collection
azi = float(unpackH(data[44:46])[0])
rotDiff = azi - previousAzi
if rotDiff > 0.0:
dt = timeStamp - previousTime
if dt > 0:
rotRate = (rotDiff * 10000.0) / (dt * 360.0) #in Hertz (Hz))
else:
previousTime = timeStamp
previousAzi = azi
else:
previousTime = timeStamp
previousAzi = azi
for j in range(0,12):
o1 = int(j*100)
if binascii.hexlify(data[42+o1:44+o1]).decode('utf-8').upper() == "FFEE":
for k in range(0,2):
o2 = o1 + int(k*48)
for m in range(0,16):
o3 = o2 + int(m*3)
dist,intensity = unpackHB(data[46+o3:49+o3])
if not dist:
goodPts += 1
num_points += 1
distData.append(dist)
else:
num_bad_point_blocks += 1
pointData.append([NMEAdataIndex,timeStamp,returnMode,sensorType,goodPts])
pbar.close()
#multiprocessing
else:
chunkIndex = []
foundFirstPos = False
numSoFar = 0
i = 0
run = True
while run:
if packetOrder[i][0] == 1:
if not foundFirstPos:
chunkIndex.append(i)
foundFirstPos = True
elif packetOrder[i][0] == 2:
if foundFirstPos:
numSoFar += 1
if numSoFar == designNum:
for j in range(i+1,len(packetOrder)):
if packetOrder[j][0] == 1:
numSoFar = 0
i = j-1
foundFirstPos = False
break
i += 1
if i == len(packetOrder):
chunkIndex.append(i)
run = False
print("\n\nParsing observations from binary packet data using " + str(len(chunkIndex)-1) + " CPU cores, please wait...\n")
procs = []
manager = mp.Manager()
epochD = manager.dict()
latD = manager.dict()
lonD = manager.dict()
pps_statusD = manager.dict()
timeStamp1D = manager.dict()
NMEAdataIndexD = manager.dict()
timeStampD = manager.dict()
returnModeD = manager.dict()
sensorTypeD = manager.dict()
goodPtsD = manager.dict()
miscD = manager.dict()
statusD = manager.dict()
lock = mp.Lock()
for i in range(0,len(chunkIndex)-1):
statusD[i] = 0
for i in range(0,len(chunkIndex)-1):
proc1 = mp.Process(target=parseChunk,args=(statusD, lock, i, packetOrder[chunkIndex[i]:chunkIndex[i+1]][:], miscD, epochD, latD, lonD, pps_statusD, timeStamp1D, NMEAdataIndexD, timeStampD, returnModeD, sensorTypeD, goodPtsD))
procs.append(proc1)
for iproc in procs:
iproc.start()
procs[len(procs)-1].join()
denom = 0
for miscData in miscD.values():
num_points += miscData[0]
# num_bad_position_packets += miscData[1]
num_bad_point_blocks += miscData[2]
if miscData[3] != -1.0:
rotRate += miscData[3]
denom += 1
if denom != 0:
rotRate /= denom
epochL = []
latL = []
lonL = []
timeStamp1L = []
NMEAdataIndexL = []
timeStampL = []
returnModeL = []
sensorTypeL = []
goodPtsL = []
indexOffset = 0
for i in range(0,len(epochD)):
epochL.extend(epochD[i])
latL.extend(latD[i])
lonL.extend(lonD[i])
timeStamp1L.extend(timeStamp1D[i])
for i in range(0,len(NMEAdataIndexD)):
NMEAdataIndexL.extend((np.asarray(NMEAdataIndexD[i]) + indexOffset))
indexOffset = NMEAdataIndexL[len(NMEAdataIndexL)-1]
timeStampL.extend(timeStampD[i])
returnModeL.extend(returnModeD[i])
sensorTypeL.extend(sensorTypeD[i])
goodPtsL.extend(goodPtsD[i])
for i in range(0,len(pps_statusD)):
pps_status[0] += pps_statusD[i][0]
pps_status[1] += pps_statusD[i][1]
pps_status[2] += pps_statusD[i][2]
pps_status[3] += pps_statusD[i][3]
NMEAdata = list(zip(epochL,latL,lonL,timeStamp1L))
pointData = list(zip(NMEAdataIndexL,timeStampL,returnModeL,sensorTypeL,goodPtsL))
#done single core or multiprocessing (common code)
if rotRate == -1.0:
rotRate = 0.0
rotTimeLimit = 0.0
if rotRate != 0.0:
rotTimeLimit = (1.0 / rotRate) #time (sec) for 1 rotation of the scanner head
NMEAdata = np.asarray(NMEAdata)
if len(pointData) > 1 and len(NMEAdata) > 0:
index1 = pointData[len(pointData)-2][0]
index2 = pointData[0][0]
firstPosEpoch = (NMEAdata[0][0].hour * 3600.0) + (NMEAdata[0][3] / 1000000.0)
firstDataEpoch = (NMEAdata[index2][0].hour * 3600.0) + (pointData[0][1] / 1000000.0)
timeDiffd = ((NMEAdata[index1][0].hour * 3600.0) + (pointData[len(pointData)-2][1] / 1000000.0)) - firstDataEpoch
if timeDiffd < 0:
timeDiffd += 86400.0
pointsPerRot = 0
rotDataTimes = [0]
rotDataPoints = [0]
# debug = open("debug.txt","w")
for i in range(0,len(pointData)-1):
epochIndex = pointData[i][0]
currentDataEpoch = (NMEAdata[epochIndex][0].hour * 3600.0) + (pointData[i][1] / 1000000.0)
# debug.write(str(i) + " " + str(currentDataEpoch - firstDataEpoch) + "\n")
if currentDataEpoch - firstDataEpoch < -5400:
currentDataEpoch += 86400.0
if currentDataEpoch - firstDataEpoch < rotTimeLimit:
pointsPerRot += pointData[i][4]
else:
rotDataTimes.append((currentDataEpoch - firstPosEpoch) / 60.0)
if pointsPerRot == 0:
pointsPerRot = 1 #for log scale plotting
rotDataPoints.append(pointsPerRot)
firstDataEpoch = currentDataEpoch
pointsPerRot = 0
# debug.close()
timeEnd = time.time()
print("\n *** COMPLETED PCAP CHECK IN " + str(round((timeEnd - timeStart) / 60.,2)) + " mins ***")
badPosPercent = np.round((badPosPackets / numPosPackets) * 100,1)
skippedDataPercent = np.round((skippedDataPackets / numDataPackets) * 100,1)
logFile = open(log_filename, 'w')
OpenMMS1_log(logFile)
stats = ("\n ********************* PCAP CHECK RESULTS ********************\n\n")
stats += (" INPUT: "+ pcapName +" at "+"{:,}".format(pcapSize)+" bytes\n\n")
stats += (" Approx. Rotation Rate: " + str(np.round(rotRate,1)) + " Hz\n\n")
stats += (" First Position Time: " + str(NMEAdata[0][0]) + " UTC\n")
stats += (" Last Position Time: " + str(NMEAdata[len(NMEAdata)-1][0]) + " UTC\n")
stats += (" First Data Time: " + str(NMEAdata[index2][0]) + " UTC\n")
stats += (" Last Data Time: " + str(NMEAdata[index1][0]) + " UTC\n\n")
stats += (" Data Duration: " + str(np.round(timeDiffd / 60.0,1)) + " minutes\n")
stats += (" Data Packets: " + "{:,}".format(numDataPackets) + "\n")
stats += (" Skipped Data Packets: " + "{:,}".format(skippedDataPackets) + " (" + str(skippedDataPercent) + "% of total)\n")
stats += (" Non-zero Range Observations: " + "{:,}".format(num_points) + "\n")
stats += ("\n Bad Data Blocks: " + "{:,}".format(num_bad_point_blocks) + "\n")
stats += (" Bad NMEA Messages: " + "{:,}".format(badPosPackets) + " (" + str(badPosPercent) + "% of total)\n")
stats += ("\n No PPS Detected: " + "{:,}".format(pps_status[0]) + "\n")
stats += (" Synchronizing to PPS: " + "{:,}".format(pps_status[1]) + "\n")
stats += (" PPS Locked: " + "{:,}".format(pps_status[2]) + "\n")
stats += (" PPS Error: " + "{:,}".format(pps_status[3]) + "\n\n")
stats += (" ***************************************************************\n")
logFile.write(stats)
print(stats)
dist_x = [0.0]
dist_y = [0.0]
for i in range(1,len(NMEAdata)):
n,e = LL2NE(NMEAdata[0,1],NMEAdata[0,2],NMEAdata[i,1],NMEAdata[i,2])
dist_y.append(n)
dist_x.append(e)
min_x = np.min(dist_x)
min_y = np.min(dist_y)
dist_x -= min_x
dist_y -= min_y
plt.figure(figsize=(7,7))
plt.axis('equal')
plt.xlabel('Easting [m]')
plt.ylabel('Northing [m]')
plt.title('2D Flight Path (' + pcapName + ')')
plt.plot(dist_x,dist_y)
plt.savefig(filePath / ("Flight Path - " + timeStr + ".jpg"))
plt.show()
print("\n *** Note: Flight Path plot saved as image ***\n")
plt.figure(figsize=(10,5))
plt.yscale("log")
plt.xlabel('Mission Time (mins)')
plt.ylabel('Points Per Rotation (logarithmic scale)')
plt.title('Collected Points during Mission (' + pcapName + ')')
plt.plot(rotDataTimes, rotDataPoints, 'g.', ms=1) #'g,')
plt.ylim(bottom=1)
plt.savefig(filePath / ("Collected Points - " + timeStr + ".jpg"))
plt.show()
print(" *** Note: Collected Points plot saved as image ***\n")
iHeartLidar2(logFile)
logFile.close()
else:
print("\n\n****************************************************************")
print("*********** NO DATA AND/OR POSITION INFO WAS FOUND *************")
print("****************************************************************\n\n")
### command line start
if __name__ == "__main__":
print("\nVLP-16 PCAP File Check Started...")
pcap_filename = sys.argv[1]
main(pcap_filename)