def read_logger_file(file, verbose=False): # init gps container gps = gps_data() if isinstance(file, list): for f in file: gps = gps + read_logger_file(f) else: print('Reads ' + file) gpsfile = pynmea2.NMEAFile(file) data = pd.DataFrame() for d in gpsfile: if verbose: print(d) time = datetime.datetime.combine(d.datestamp, d.timestamp) data = data.append({'lon': d.longitude, 'lat': d.latitude, 'time': time}, ignore_index=True) # gps.d = data.set_index('time') return gps
def read_gps_alees(file, label='gps', verbose=False): # init gps container gp = gps(label=label) if isinstance(file, list): for f in file: gp = gp + read_gps_alees(f, verbose=verbose) else: print('Reads ' + file) gpsfile = pynmea2.NMEAFile(file) data = pd.DataFrame() for d in gpsfile: if verbose: print(d) if all([d.datestamp, d.timestamp]): time = datetime.datetime.combine(d.datestamp, d.timestamp) data = data.append({'lon': d.longitude, 'lat': d.latitude, 'time': time }, ignore_index=True) # gp.d = data.set_index('time') return gp
def test_file(): nmeafile = pynmea2.NMEAFile(StringIO(TEST_DATA)) nmea_strings = nmeafile.read() assert len(nmea_strings) == 10 assert all([isinstance(s, pynmea2.NMEASentence) for s in nmea_strings]) del nmeafile with pynmea2.NMEAFile(StringIO(TEST_DATA)) as _f: nmea_strings = [_f.readline() for i in range(10)] assert len(nmea_strings) == 10 assert all([isinstance(s, pynmea2.NMEASentence) for s in nmea_strings]) with pynmea2.NMEAFile(StringIO(TEST_DATA)) as _f: nmea_strings = [s for s in _f] assert len(nmea_strings) == 10 assert all([isinstance(s, pynmea2.NMEASentence) for s in nmea_strings]) with pynmea2.NMEAFile(StringIO(TEST_DATA)) as _f: nmea_strings = [_f.next() for i in range(10)] assert len(nmea_strings) == 10 assert all([isinstance(s, pynmea2.NMEASentence) for s in nmea_strings])
def load_nmea(file: Path, in_cols: Optional[Sequence[str]] = None) -> pd.DataFrame: """ NMEA to DataFrame convertor :param file: NMEA file Path :param in_cols: attributes to search in pynmea2 NMEASentences (corresponded to needed data in NMEA strings) :return: pandas DataFrame with in_cols columns (except columns for which no data found) with 'datetime' index """ if in_cols is None: search_fields = ( 'latitude', 'longitude', 'spd_over_grnd', 'true_course', 'depth_meters' ) # not includes index. Also Magnetic Variation ('mag_variation') may be useful for ADCP proc index = 'datetime' # todo: also try 'timestamp' if 'datetime' not found, will requre to add date else: index, *search_fields = in_cols rows = [] d = {} b_have_time = False with pynmea2.NMEAFile(file.open(mode='r')) as _f: while True: # to continue on error try: for nmea_sentence in _f: # best method because with _f.readline() need to check for EOF, nmea_sentences = _f.read() fails when tries to read all at once try: t = getattr(nmea_sentence, index) if b_have_time: rows.append(d) d = {index: t} # new time row begin else: d[index] = t b_have_time = True except AttributeError: pass for f in search_fields: # all except index try: d[f] = getattr(nmea_sentence, f) except AttributeError: continue except pynmea2.ParseError: continue break if not rows: # from_records() gets strange output on empty input so we force returning empty dataframe: return pd.DataFrame() df = pd.DataFrame.from_records(rows, index=[index], coerce_float=True) # arg columns=search_fields not works, coerce_float is needed because eliminates objects that we can not write to HDF5 return df
def read(filename): records = [] #解析列表 gga_sumcount = 0 #gga语句总统计值 gga_validcount = 0 #gga有效语句统计值(固定且差分延迟小于20秒) hgts = [] #高程值列表 hgt_sum = 0.0 #高程累加值 hgt_min = 0.0 #高程最小值 hgt_max = 0.0 #高程最大值 hgt_ud2cm_count = 0 #±2cm数据条数 hgt_ud1cm_count = 0 #±1cm数据条数 print('Parse file path:',filename) start_time = time.time() with pynmea2.NMEAFile(filename) as nmea_file: for record in nmea_file: records.append(record) if(record.sentence_type == 'GGA'):#统计GGA语句条数 gga_sumcount += 1 if((record.gps_qual == 4) and (float(record.age_gps_data) < 20)):#固定解且差分延迟小于20秒,累加高程值 hgts.append(float(record.altitude))#将固定解高程值添加至列表 hgt_sum += float(record.altitude) gga_validcount += 1 end_time = time.time() print('Parse used time:%.2f(s)' % (end_time - start_time)) print('1.Total counts of records:', len(records)) print('2.GGA total counts: %d, fixed counts: %d, fixed percent:%.2f(%%)' % (gga_sumcount, gga_validcount, (gga_validcount / gga_sumcount)*100 )) if gga_validcount != 0: hgt_avg = hgt_sum / gga_validcount print('3.Hgt average:%.4f(m),' % hgt_avg, end = ' ') detla_1cm = 0.01 detla_2cm = 0.02 for i in range(len(hgts)): if (hgts[i] <= hgt_avg + detla_2cm) and (hgts[i] >= hgt_avg - detla_2cm): hgt_ud2cm_count += 1 if (hgts[i] <= hgt_avg + detla_1cm) and (hgts[i] >= hgt_avg - detla_1cm): hgt_ud1cm_count += 1 else: print('3.Hgt average:Invalid,' , end = ' ') if len(hgts) != 0: print('range ±2cm percent:%.2f(%%), range ±1cm percent:%.2f(%%), max-min:%.4f(m)' % ((hgt_ud2cm_count / len(hgts)) * 100, (hgt_ud1cm_count / len(hgts)) * 100, max(hgts) - min(hgts))) else: print('range ±2cm percent:Invalid, range ±1cm percent:Invalid, max-min:Invalid')
def read_gps_lops(file, label='gps', verbose=False): # init gps container gp = gps(label=label) if isinstance(file, list): for f in file: gp = gp + read_gps_lops(f, verbose=verbose) else: print('Reads ' + file) gpsfile = pynmea2.NMEAFile(file) data = pd.DataFrame() t = None for s in gpsfile: if verbose: print(s) if len(s.fields)>0 and hasattr(s, 'is_valid') and s.is_valid: d = parse_nmea_sentence(s, t=t) data = data.append(d, ignore_index=True) t = d['time'] # gp.d = data.set_index('time') return gp
def load_nmea(file, cfg): with pynmea2.NMEAFile(file) as _f: nmea_sentences = _f.read() #nmea_strings = [_f.readline() for i in range(10)] #msg = pynmea2.ptarse('$SDDBT,665.4,f,202.8,M,110.9,F*06') return nmea_sentences
def read(filename): records = [] #解析列表 gga_sumcount = 0 #gga语句总统计值 gga_validcount = 0 #gga有效语句统计值(固定且差分延迟小于20秒) hgts = [] #高程值列表 hgt_sum = 0.0 #高程累加值 hgt_min = 0.0 #高程最小值 hgt_max = 0.0 #高程最大值 hgt_ud2cm_count = 0 #±2cm数据条数 hgt_ud1cm_count = 0 #±1cm数据条数 lat_list = [] #lat列表(有效数据) lon_list = [] #lon列表(有效数据) print('Parse file path:', filename) start_time = time.time() #使用上下文解析nmea文本数据 with pynmea2.NMEAFile(filename) as nmea_file: for record in nmea_file: records.append(record) if (record.sentence_type == 'GGA'): #统计GGA语句条数 gga_sumcount += 1 if ((record.gps_qual == 4) and (float(record.age_gps_data) < 20)): #固定解且差分延迟小于20秒,累加高程值 hgts.append(float(record.altitude)) #将固定解高程值添加至列表 lon_list.append(record.longitude) #将固定解经度值添加至列表 lat_list.append(record.latitude) #将固定解纬度值添加至列表 hgt_sum += float(record.altitude) gga_validcount += 1 end_time = time.time() print('Parse used time:%.2f(s)' % (end_time - start_time)) print('1.Total counts of records:', len(records)) print('2.GGA total counts: %d, fixed counts: %d, fixed percent:%.2f(%%)' % (gga_sumcount, gga_validcount, (gga_validcount / gga_sumcount) * 100)) if gga_validcount != 0: hgt_avg = hgt_sum / gga_validcount print('3.Hgt average:%.4f(m),' % hgt_avg, end=' ') detla_1cm = 0.01 detla_2cm = 0.02 for i in range(len(hgts)): if (hgts[i] <= hgt_avg + detla_2cm) and (hgts[i] >= hgt_avg - detla_2cm): hgt_ud2cm_count += 1 if (hgts[i] <= hgt_avg + detla_1cm) and (hgts[i] >= hgt_avg - detla_1cm): hgt_ud1cm_count += 1 else: print('3.Hgt average:Invalid,', end=' ') if len(hgts) != 0: print( 'range ±2cm percent:%.2f(%%), range ±1cm percent:%.2f(%%), max-min:%.4f(m)' % ((hgt_ud2cm_count / len(hgts)) * 100, (hgt_ud1cm_count / len(hgts)) * 100, max(hgts) - min(hgts))) else: print( 'range ±2cm percent:Invalid, range ±1cm percent:Invalid, max-min:Invalid' ) ''' 绘制高程值趋势图(实际变化值/平均值/平均值+2cm/平均值-2cm四条曲线) ''' if (gga_validcount != 0) and (len(hgts) != 0): print('4.Draw plot') hgt_avg_list = [] hgt_u2cm_list = [] hgt_d2cm_list = [] for i in range(len(hgts)): hgt_avg_list.append(hgt_avg) hgt_u2cm_list.append(hgt_avg + detla_2cm) hgt_d2cm_list.append(hgt_avg - detla_2cm) avg_y = hgt_avg_list u2cm_y = hgt_u2cm_list d2cm_y = hgt_d2cm_list #WGS84经纬度转米勒投影XY坐标系 miller_x = [] miller_y = [] for i in range(len(lon_list)): millerToXY(lon_list[i], lat_list[i]) #经纬度转换为米勒投影坐标xy miller_x.append(xy_coordinate[i][0]) #x miller_y.append(xy_coordinate[i][1]) #y #WGS84经纬度转CGCS2000坐标系 ''' Beijing 1954 / Gauss-Kruger CM 117E EPSG:21460 with transformation: 15921 Area of use: China - onshore between 114°E and 120°E ''' cgcs2000_x = [] cgcs2000_y = [] transformer = Transformer.from_crs( 'epsg:4326', 'epsg:4479' ) #WGS84转CGCS2000坐标系(epsg:4326为WGS84坐标系编号,epsg:4479为CGCS2000坐标系编号) for i in range(len(lon_list)): cgc_x, cgc_y, cgc_z = transformer.transform( lat_list[i], lon_list[i], hgts[i]) cgcs2000_xy.append((cgc_x, cgc_y, cgc_z)) #形成多个元组坐标组成的列表 cgcs2000_x.append(cgc_x) cgcs2000_y.append(cgc_y) # print('cgcs2000:',cgcs2000_xy) #打印转换后的cgcs2000坐标点集 x = range(0, len(hgts)) hgt_y = hgts plt.figure(num=1) plt.subplot(311) #3行1列 第1行 plt.title('Position Chart') plt.plot(x, miller_x, label='E-W(m)', linestyle=':') #绘制longitude实际值趋势 plt.xlabel('X-Points') plt.ylabel('Y') plt.grid() plt.legend() plt.subplot(312) #3行1列 第2行 plt.plot(x, miller_y, label='N-S(m)', linestyle=':') #绘制latitude实际值趋势 plt.xlabel('X-Points') plt.ylabel('Y') plt.grid() plt.legend() plt.subplot(313) #3行1列 第3行 plt.plot(x, hgt_y, label='rt hgt', linestyle=':') #绘制实际值趋势 plt.plot(x, avg_y, label='avg hgt') #绘制平均值直线 plt.plot(x, u2cm_y, label='avg+2cm hgt') #绘制平均值+2cm直线 plt.plot(x, d2cm_y, label='avg-2cm hgt') #绘制平均值-2cm直线 plt.xlabel('X-Points') plt.ylabel('Y-Height(m)') plt.grid() plt.legend() plt.figure(num=2) plt.plot(lon_list, lat_list, linestyle=':') #绘制经纬度分布图 plt.xlabel('X-Longitude') plt.ylabel('Y-Latitude') plt.title('Lon-Lat Chart') plt.grid() plt.figure(num=3) plt.plot(miller_x, miller_y, linestyle=':') #绘制米勒投影XY分布图 plt.xlabel('X(m)') plt.ylabel('Y(m)') plt.title('Miller_XY Chart') plt.grid() plt.figure(num=4) plt.plot(cgcs2000_x, cgcs2000_y, linestyle=':') #绘制CGCS2000坐标系XY分布图 plt.xlabel('X(m)') plt.ylabel('Y(m)') plt.title('CGCS2000_XY Chart') plt.grid() plt.show() else: print('4.Data invalid,do not draw plot')
def read(filename): records = [] #解析列表 gga_count = [0, 0, 0, 0, 0, 0] #GGA总数/固定解点数/浮动解点数/差分解点数/单点解点数/未定位点数 hgts = [] #高程值列表 hgt_sum = 0.0 #高程累加值 hgt_min = 0.0 #高程最小值 hgt_max = 0.0 #高程最大值 hgt_ud2cm_count = 0 #±2cm数据条数 hgt_ud1cm_count = 0 #±1cm数据条数 lat_list = [] #lat列表(有效数据) lon_list = [] #lon列表(有效数据) sv_list = [] #可用卫星颗数(有效数据) diff_delay_list = [] #差分延迟列表(有效数据) print('Parse file path:', filename) start_time = time.time() #使用上下文解析nmea文本数据 with pynmea2.NMEAFile(filename) as nmea_file: for record in nmea_file: records.append(record) if (record.sentence_type == 'GGA'): #统计GGA语句条数 gga_count[0] += 1 if (record.gps_qual == 4): #if(float(record.age_gps_data) < 20)): #差分延迟小于20秒,累加高程值 hgts.append(float(record.altitude)) #将固定解高程值添加至列表 lon_list.append(record.longitude) #将固定解经度值添加至列表 lat_list.append(record.latitude) #将固定解纬度值添加至列表 sv_list.append(int(record.num_sats)) #将固定解可用卫星颗数添加至列表 diff_delay_list.append(float( record.age_gps_data)) #将固定解差分延迟添加至列表 hgt_sum += float(record.altitude) gga_count[1] += 1 elif (record.gps_qual == 5): #浮动解 gga_count[2] += 1 elif (record.gps_qual == 2): #差分解 gga_count[3] += 1 elif (record.gps_qual == 1): #单点解 gga_count[4] += 1 else: #未定位 gga_count[5] += 1 end_time = time.time() print('Parse used time:%.2f(s)' % (end_time - start_time)) print('1.Total counts of records:', len(records)) if gga_count[0] != 0: print( '2.GGA total counts:%d, Fixed:%d(%.2f%%), Float:%d(%.2f%%), DGPS:%d(%.2f%%), Single:%d(%.2f%%), NoPos:%d(%.2f%%)' % (gga_count[0], gga_count[1], (gga_count[1] / gga_count[0]) * 100, gga_count[2], (gga_count[2] / gga_count[0]) * 100, gga_count[3], (gga_count[3] / gga_count[0]) * 100, gga_count[4], (gga_count[4] / gga_count[0]) * 100, gga_count[5], (gga_count[5] / gga_count[0]) * 100)) else: print('2.Not parsed any GGA sentence') if gga_count[1] != 0: hgt_avg = hgt_sum / gga_count[1] print('3.Hgt average:%.4f(m),' % hgt_avg, end=' ') detla_1cm = 0.01 detla_2cm = 0.02 for i in range(len(hgts)): if (hgts[i] <= hgt_avg + detla_2cm) and (hgts[i] >= hgt_avg - detla_2cm): hgt_ud2cm_count += 1 if (hgts[i] <= hgt_avg + detla_1cm) and (hgts[i] >= hgt_avg - detla_1cm): hgt_ud1cm_count += 1 print( 'range ±2cm percent:%.2f(%%), range ±1cm percent:%.2f(%%), max-min:%.4f(m)' % ((hgt_ud2cm_count / len(hgts)) * 100, (hgt_ud1cm_count / len(hgts)) * 100, max(hgts) - min(hgts))) else: print('3.Hgt average:Invalid,', end=' ') print( 'range ±2cm percent:Invalid, range ±1cm percent:Invalid, max-min:Invalid' ) ''' 绘制高程值趋势图(实际变化值/平均值/平均值+2cm/平均值-2cm四条曲线) ''' if gga_count[1] != 0: print('4.Draw plot') hgt_avg_list = [] hgt_u2cm_list = [] hgt_d2cm_list = [] for i in range(len(hgts)): hgt_avg_list.append(hgt_avg) hgt_u2cm_list.append(hgt_avg + detla_2cm) hgt_d2cm_list.append(hgt_avg - detla_2cm) avg_y = hgt_avg_list u2cm_y = hgt_u2cm_list d2cm_y = hgt_d2cm_list #WGS84经纬度转米勒投影XY坐标系 miller_x = [] miller_y = [] for i in range(len(lon_list)): millerToXY(lon_list[i], lat_list[i]) #经纬度转换为米勒投影坐标xy miller_x.append(xy_coordinate[i][0]) #x miller_y.append(xy_coordinate[i][1]) #y #WGS84经纬度转CGCS2000坐标系 ''' Beijing 1954 / Gauss-Kruger CM 117E EPSG:21460 with transformation: 15921 Area of use: China - onshore between 114°E and 120°E ''' cgcs2000_x = [] cgcs2000_y = [] transformer = Transformer.from_crs( 'epsg:4326', 'epsg:4479' ) #WGS84转CGCS2000坐标系(epsg:4326为WGS84坐标系编号,epsg:4479为CGCS2000坐标系编号) for i in range(len(lon_list)): cgc_x, cgc_y, cgc_z = transformer.transform( lat_list[i], lon_list[i], hgts[i]) cgcs2000_xy.append((cgc_x, cgc_y, cgc_z)) #形成多个元组坐标组成的列表 cgcs2000_x.append(cgc_x) cgcs2000_y.append(cgc_y) # print('cgcs2000:',cgcs2000_xy) #打印转换后的cgcs2000坐标点集 x = range(0, len(hgts)) hgt_y = hgts print('gga_count', gga_count) GGAPercentN = 5 percent = [0 for i in range(GGAPercentN)] percent[0] = gga_count[1] / gga_count[0] percent[1] = gga_count[2] / gga_count[0] percent[2] = gga_count[3] / gga_count[0] percent[3] = gga_count[4] / gga_count[0] percent[4] = gga_count[5] / gga_count[0] #print('GGAPercentN',GGAPercentN) #绘制解状态占比及Avg±2cm Avg±1cm占比条形图 fig = plt.figure(num=0) #fig.subplots_adjust(bottom=0.025, left=0.025, top = 0.975, right=0.975) fig.subplots_adjust(bottom=0.1, left=0.025, top=0.975, right=0.975) plt.title('Summary Chart') plt.subplot(211) #1行2列 第1列 X1 = np.arange(GGAPercentN) Y1 = percent * np.ones(GGAPercentN) #plt.axes([0.025,0.025,0.95,0.95]) #设置坐标轴 plt.bar(X1, Y1, width=0.5, facecolor='#9999ff', edgecolor='black', label='Solution Percent') #绘制条形码 plt.legend(loc='upper right') solution_text = [ 'Fix(4)', 'Float(5)', 'DGPS(2)', 'Single(1)', 'NoPos(0)' ] for x1, y1 in zip(X1, Y1): plt.text(x1, y1 + 0.1, '%.2f(%%)' % float(y1 * 100.00), ha='center', va='top') #在对应条形码上方放置条形码数值 for i in range(GGAPercentN): plt.text(i, -0.15, solution_text[i], ha='center', va='bottom') #在对应条形码下方放置类型 # 设置横纵坐标上下限及记号 #plt.xlim(-.5,GGAPercentN), plt.xticks([]) plt.ylim(-.2, +1.15), plt.yticks([]) plt.xticks([]), plt.yticks([]) plt.subplot(212) #1行2列 第2列 HgtPercentN = 2 hgtpercent = [0 for i in range(HgtPercentN)] hgtpercent[0] = hgt_ud2cm_count / len(hgts) hgtpercent[1] = hgt_ud1cm_count / len(hgts) X2 = np.arange(HgtPercentN) Y2 = hgtpercent * np.ones(HgtPercentN) # plt.axes([0.025,0.025,0.95,0.95]) #设置坐标轴 plt.bar(X2, Y2, width=0.3, facecolor='#ff9999', edgecolor='black', label='Avg Percent') #绘制条形码 plt.legend(loc='upper right') range_text = ['Avg±2cm', 'Avg±1cm'] for x2, y2 in zip(X2, Y2): plt.text(x2, y2 + 0.1, '%.2f(%%)' % float(y2 * 100.00), ha='center', va='top') #在对应条形码上方放置条形码数值 for i in range(HgtPercentN): plt.text(i, -0.15, range_text[i], ha='center', va='bottom') #在对应条形码下方放置类型 # 设置横纵坐标上下限及记号 #plt.xlim(-.5,HgtPercentN), plt.xticks([]) plt.ylim(-.2, +1.15), plt.yticks([]) plt.xticks([]), plt.yticks([]) plt.figure(num=1) plt.subplot(211) #2行1列 第1行 plt.title('Position Chart') plt.plot(x, miller_x, linewidth=1.0, color="blue", label='E-W(m)', linestyle=':') #绘制longitude实际值趋势 plt.xlabel('Points') plt.ylabel('Longitude') plt.grid() plt.legend() plt.subplot(212) #2行1列 第2行 plt.plot(x, miller_y, linewidth=1.0, color="red", label='N-S(m)', linestyle=':') #绘制latitude实际值趋势 plt.xlabel('Points') plt.ylabel('Latitude') plt.grid() plt.legend() plt.figure(num=2) plt.title('Height Chart') plt.plot(x, hgt_y, linewidth=1.0, color="blue", label='rt hgt', linestyle=':') #绘制实际值趋势 plt.plot(x, avg_y, linewidth=1.0, color="green", label='avg hgt') #绘制平均值直线 plt.plot(x, u2cm_y, linewidth=1.0, color="red", label='avg+2cm hgt') #绘制平均值+2cm直线 plt.plot(x, d2cm_y, linewidth=1.0, color="magenta", label='avg-2cm hgt') #绘制平均值-2cm直线 plt.xlabel('Points') plt.ylabel('Height(m)') plt.grid() plt.legend() plt.figure(num=3) plt.plot(x, sv_list, linewidth=1.0, color="green", linestyle='-') #绘制可用卫星颗数分布图 plt.xlabel('Points') plt.ylabel('SV') plt.title('Satellite In Used Chart') plt.grid() plt.figure(num=4) plt.plot(x, diff_delay_list, linewidth=1.0, color="red", linestyle='-') #绘制差分延迟分布图 plt.xlabel('Points') plt.ylabel('Diff Age(s)') plt.title('Diff Age Chart') plt.grid() plt.figure(num=5) plt.plot(lon_list, lat_list, linewidth=1.0, linestyle=':') #绘制经纬度分布图 plt.xlabel('Longitude') plt.ylabel('Latitude') plt.xticks(rotation='45') #x轴标签旋转45度 plt.title('Lon-Lat Chart') plt.grid() plt.figure(num=6) plt.plot(miller_x, miller_y, linewidth=1.0, linestyle=':') #绘制米勒投影XY分布图 plt.xlabel('Miller-X(m)') plt.ylabel('Miller-Y(m)') plt.title('Miller_XY Chart') plt.grid() plt.figure(num=7) plt.plot(cgcs2000_x, cgcs2000_y, linewidth=1.0, linestyle=':') #绘制CGCS2000坐标系XY分布图 plt.xlabel('CGCS2000-X(m)') plt.ylabel('CGCS2000-Y(m)') plt.title('CGCS2000_XY Chart') plt.grid() plt.show() else: print('4.Data invalid,do not draw plot')
#使用pynmea2库对nmea数据文件进行解析,然后打印每一条数据. ''' 参考网址:http://gnss.help/2018/03/01/pynmea2-readme/index.html 1.安装pynmea2模块 pip install pynmea2 2.导入pynmea2 import pynmea2 3.使用NMEAFile()解析文件 修改文件目录('H:/python study/gps_line.txt')即可解析不同NMEA文件 ''' import pynmea2 records = [] nmeafilepath = 'H:/python study/gps_line.txt' with pynmea2.NMEAFile(nmeafilepath) as nmea_file: for record in nmea_file: records.append(record) print('Parse nmea file path:', nmeafilepath) print('Count of records:', len(records)) for i in range(len(records)): print('\n%d nmea sentence:' % i) print(repr(records[i]))
def read(filename): records = [] #解析列表 gga_sumcount = 0 #gga语句总统计值 gga_validcount = 0 #gga有效语句统计值(固定且差分延迟小于20秒) hgts = [] #高程值列表 hgt_sum = 0.0 #高程累加值 hgt_min = 0.0 #高程最小值 hgt_max = 0.0 #高程最大值 hgt_ud2cm_count = 0 #±2cm数据条数 hgt_ud1cm_count = 0 #±1cm数据条数 lat_list = [] #lat列表(有效数据) lon_list = [] #lon列表(有效数据) print('Parse file path:', filename) start_time = time.time() #使用上下文解析nmea文本数据 with pynmea2.NMEAFile(filename) as nmea_file: for record in nmea_file: records.append(record) if (record.sentence_type == 'GGA'): #统计GGA语句条数 gga_sumcount += 1 if ((record.gps_qual == 4) and (float(record.age_gps_data) < 20)): #固定解且差分延迟小于20秒,累加高程值 hgts.append(float(record.altitude)) #将固定解高程值添加至列表 lon_list.append(record.longitude) #将固定解经度值添加至列表 lat_list.append(record.latitude) #将固定解纬度值添加至列表 hgt_sum += float(record.altitude) gga_validcount += 1 end_time = time.time() print('Parse used time:%.2f(s)' % (end_time - start_time)) print('1.Total counts of records:', len(records)) print('2.GGA total counts: %d, fixed counts: %d, fixed percent:%.2f(%%)' % (gga_sumcount, gga_validcount, (gga_validcount / gga_sumcount) * 100)) if gga_validcount != 0: hgt_avg = hgt_sum / gga_validcount print('3.Hgt average:%.4f(m),' % hgt_avg, end=' ') detla_1cm = 0.01 detla_2cm = 0.02 for i in range(len(hgts)): if (hgts[i] <= hgt_avg + detla_2cm) and (hgts[i] >= hgt_avg - detla_2cm): hgt_ud2cm_count += 1 if (hgts[i] <= hgt_avg + detla_1cm) and (hgts[i] >= hgt_avg - detla_1cm): hgt_ud1cm_count += 1 else: print('3.Hgt average:Invalid,', end=' ') if len(hgts) != 0: print( 'range ±2cm percent:%.2f(%%), range ±1cm percent:%.2f(%%), max-min:%.4f(m)' % ((hgt_ud2cm_count / len(hgts)) * 100, (hgt_ud1cm_count / len(hgts)) * 100, max(hgts) - min(hgts))) else: print( 'range ±2cm percent:Invalid, range ±1cm percent:Invalid, max-min:Invalid' ) ''' 绘制高程值趋势图(实际变化值/平均值/平均值+2cm/平均值-2cm四条曲线) ''' if (gga_validcount != 0) and (len(hgts) != 0): print('4.Draw plot') hgt_avg_list = [] hgt_u2cm_list = [] hgt_d2cm_list = [] for i in range(len(hgts)): hgt_avg_list.append(hgt_avg) hgt_u2cm_list.append(hgt_avg + detla_2cm) hgt_d2cm_list.append(hgt_avg - detla_2cm) avg_y = hgt_avg_list u2cm_y = hgt_u2cm_list d2cm_y = hgt_d2cm_list miller_x = [] miller_y = [] for i in range(len(lon_list)): millerToXY(lon_list[i], lat_list[i]) #经纬度转换为米勒投影坐标xy miller_x.append(xy_coordinate[i][0]) #x miller_y.append(xy_coordinate[i][1]) #y x = range(0, len(hgts)) hgt_y = hgts plt.figure(num=1) plt.plot(x, hgt_y) #绘制实际值趋势 plt.plot(x, avg_y) #绘制平均值直线 plt.plot(x, u2cm_y) #绘制平均值+2cm直线 plt.plot(x, d2cm_y) #绘制平均值-2cm直线 plt.figure(num=2) plt.plot(lon_list, lat_list) #绘制经纬度分布图 plt.figure(num=3) plt.plot(miller_x, miller_y) #绘制XY分布图 plt.show() else: print('4.Data invalid,do not draw plot')
def dump_file(filename): with pynmea2.NMEAFile(filename) as file: for msg in file: print("%r\n" % msg)