• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
MKT-porter
博客园    首页    新随笔    联系   管理    订阅  订阅
GPS开发(3)GPS python串口采集-GPRMC数据解析
 
 

 

 

多进程采集代码

 

 

 Api_GPS.py

# -*- coding: utf-8 -*
   
   
#  117.410465,31.768830
   
  
# 使用前先使用u-center设置GPS输出,去掉多余的输出
# sudo chmod 666 /dev/ttyUSB0
#打不开串口需要给于权限
 
from multiprocessing import Process,Manager
import os
import time
import serial
import serial.tools.list_ports
 
 
import numpy as np
import time
import ctypes
import os

 
 


 
 
def gps_Get_data(ShareImages,lock,gps_debug=1):
 
    os.system('cls')
    serial_portlist = list(serial.tools.list_ports.comports())
    print("如果串口打不开,请执行  sudo chmod 666 /dev/ttyUSB0  后面是可用串口号")
    if len(serial_portlist) <= 0 :
        print('未发现可用串口')
    else :
        for i in range (len(serial_portlist)):
            print("可用串口:",serial_portlist[i])
        #port_gps = '/dev/ttyUSB'+input('请输入GPS模块所在串口:')
        #port_gps = 'COM'+input('请输入GPS模块所在串口:')
        #port_gps="/dev/ttyUSB0"
      
        port_gps=serial_portlist[0][0]
        print(port_gps)
        ser = serial.Serial(port_gps,9600,timeout = 2)
     
        #----------------------------------------------
     
        os.system('cls')
        init = 3
        #数据
        weidu_xy=0.0#纬度
        jingdu_xy=0.0 #经度
        high=0.0            #海拔高
        gps_use=0    #gps是否可用
        id_=000000  #帧号
 
        while True :
              
 
            if ShareImages[9]==1:
                print("GPS 线程关闭")
                break
            if ser.in_waiting > 0 :
     
                
                
                line=""
                try:
                    MSG=ser.readline()
                    line = str(MSG.decode("utf-8"))
                  
                except Exception as e:
                    continue

    

                 
                GETSTR_List=[]
     
                GETSTR_List.append(line)
                 
                GPRMC_List = GETSTR_List[0].split(',')
                #print('$GPRMC 有 %d 个字段'%len(GPRMC_List)) #检查','分割情况   13
                #print(len(GPRMC_List))
     
                if len(GPRMC_List)!=15:#检查数据完整度
                    #if gps_debug==1: print('当前卫星定位无效,数据不完整')
                    pass
                    #经纬度维持上传一次最后的数据
                    #weidu_xy=0 #纬度
                    #jingdu_xy=0 #经度
                    #high=0            #海拔高
                    gps_use=0    #gps是否可用
                    #id_=000000  #帧号
                    time_=int(time.time())
 
                    ShareImages[1]=gps_use
                    ShareImages[2]=weidu_xy
                    ShareImages[3]=jingdu_xy
                    ShareImages[4]=high
                    ShareImages[5]=time_
                     
 
                     
                    continue#跳过本次循环
                #------------------------------------------------
                #print('')
                if GPRMC_List[6] == '0' :#0=Invalid, 1=2D/3D, 2=DGNSS, 4=Fixed RTK, 5=Float RTK, 6=Dead Reckoning
     
                    if gps_debug==1: print('当前卫星定位无效,数据完整但无效')
                    #经纬度维持上传一次最后的数据
                    weidu_xy=0 #纬度
                    jingdu_xy=0 #经度
                    high=0            #海拔高
                    gps_use=0    #gps是否可用
                    #id_=000000  #帧号
                    time_=int(time.time())
 
                    ShareImages[1]=gps_use
                    ShareImages[2]=weidu_xy
                    ShareImages[3]=jingdu_xy
                    ShareImages[4]=high
                    ShareImages[5]=time_
 
                                                                
                elif GPRMC_List[6] == '1'  or GPRMC_List[6] == '2'  or GPRMC_List[6] == '3' or GPRMC_List[6] == '4' or GPRMC_List[6] == '5' :
                    #if gps_debug==1: print('定位正常')
                    #$GNGGA,063911.10,3402.02555,N,10845.82698,E,1,06,3.41,467.0,M,-27.9,M,,*6C
                    #if gps_debug==1: print(GETSTR_List[0])
                    #print('')
 
 
                    #--------------------------------------------
                     
                    UTC = GPRMC_List[1][0:2] + ':' + GPRMC_List[1][2:4] + ':' + GPRMC_List[1][4:6]
                    #UTC = UTC +' '+ GPRMC_List[9][0:2] + '/' + GPRMC_List[9][2:4] + '/20' + GPRMC_List[9][4:6]
                    #print('卫星UTC时间:'+UTC)
                    #---------------------------------------------
                    weidu_xy = int(GPRMC_List[2][0:2])+float(GPRMC_List[2][2:11])/60
                    weidu_xy=format(weidu_xy, '.9f')
                    jingdu_xy = int(GPRMC_List[4][0:3])+float(GPRMC_List[4][3:12])/60
                    jingdu_xy=format(jingdu_xy, '.9f')
                    high = float(GPRMC_List[9]) #米
                    high=format(high, '.2f')
                    gps_use=1
 
                    time_=int(time.time())
 
 
                    ShareImages[1]=gps_use
                    ShareImages[2]=weidu_xy
                    ShareImages[3]=jingdu_xy
                    ShareImages[4]=high
                    ShareImages[5]=time_
                     
                    #高度: 467.00 经度 108.7637830 纬度 34.0337592
                    if gps_debug==1:  print("有效", gps_use,"纬度",weidu_xy,"经度", jingdu_xy ,"高度",high,"时间戳",time_)
                 
                else :
                    if gps_debug==1: print('当前卫星定位无效,数据完整但无效,数据有误,等待刷新')
                    gps_use=0 #GPS标志位可以使用为0
                    #weidu_xy=0 #纬度
                    #jingdu_xy=0 #经度
                    time_=int(time.time())
                    
 
                    ShareImages[1]=gps_use
                    ShareImages[2]=weidu_xy
                    ShareImages[3]=jingdu_xy
                    ShareImages[4]=high
                    ShareImages[5]=time_
                     
 
            else:
               # if gps_debug==1: print('当前卫星定位无效,GPS串口没有数据')
                 
                #gps_use=0 #GPS标志位可以使用为0
                #weidu_xy=0.0#纬度
                #jingdu_xy=0.0#经度
                #high=0.0       #海拔高
                #id_=000000  #帧号
                time_=int(time.time())
                #其他数据不更新 维持原样
 
                ShareImages[1]=gps_use
                ShareImages[2]=weidu_xy
                ShareImages[3]=jingdu_xy
                ShareImages[4]=high
                ShareImages[5]=time_
 
'''
if __name__ == '__main__':
   
    #1---初始化共享内存数据
     
 
     
    lock = Manager().Lock()#创建共享内存容器
    ShareImages=Manager().dict()#存str类型数据
     
    ShareImages[1]=0 #"是否可用"
    ShareImages[2]=0.0#"经度"
    ShareImages[3]=0.0#"纬度"
    ShareImages[4]=0.0#"高度"
    ShareImages[5]=0#"时间"
    ShareImages[9]=0#用于关闭所有进程
 
     
    #gps_Get_data(ShareImages,lock)
 
        #3采集GPS
    p_gps = Process(target=gps_Get_data, args=(ShareImages,lock,1))#开启进程
    p_gps.deamon=True  #伴随主进程关闭而关闭,但是有时候还是关闭不了,单独搞个标志位来控制
    p_gps.start()#开始
   
   
    t1=time.time()
    cnt=0
    while 1:
 
         
       
        #time.sleep(1)
        t2=time.time()
        if(t2-t1)>cnt:
            cnt=cnt+1
            print("有效",int(ShareImages[1]),"纬度",float(ShareImages[2]),"经度",float(ShareImages[3]),"高度",float(ShareImages[4]),"时间戳",ShareImages[5])
'''

  

 界面

from PyQt5.QtWidgets import QApplication,QMainWindow,QFileDialog
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets, QtCore, QtGui,uic
   
#导入图像库
import cv2
import numpy as np
import datetime
  
#进程测试
#import multiprocessing
  
import sys
  
#线程测试
import threading
from queue import Queue
  
from multiprocessing import Process,Manager

#视频采集和处理进程
from Api_GPS import *  
#串口进程
from Api_MP3 import *    

import time
 
 



"""
time格式 '2018-01-03 16:26:23'
"""
def compare_time(self,startTime,endTime):
    #now = datetime.datetime.now ()
    d_start = datetime.datetime.strptime (startTime, '%Y-%m-%d %H:%M:%S')
    d_end = datetime.datetime.strptime (endTime, '%Y-%m-%d %H:%M:%S')
    diff = d_end - d_start
    diff_days = -diff.days
    #result = (d_start<=now) and (d_end>=now)
    #result = (d_start==d_end)
    #print(diff_days)
    return diff_days
#result = compare_time('2018-01-03 16:26:23','2018-02-03 16:29:55')
#print(result)      
     
 
   
#一个是这个类本身的,一个是这个类继承
class Example(QMainWindow):
   
    def __init__(self,ShareImages,Lock):
        #类的初始化
        super(Example, self).__init__()
        uic.loadUi('UI.ui', self)
        #self.setupUi(self)#界面控件初始化
          
      
        #获取共享内存,外部参数数据和数据锁
        self.ShareImages=ShareImages
        self.Lock=Lock

    
  
        #相机线程初始化
        self.UI_Int()
          
                    
           
    def UI_Int(self):
      
        #self.dateTimeEdit.setDisplayFormat("yyyy-MM-dd HH:mm:ss")
         #按钮绑定函数
        self.pushButton_begin.clicked.connect(self.callback_begin)  #开始按键
          
        self.pushButton_stop.clicked.connect(self.callback_stop)
        
        self.pushButton_up.clicked.connect(self.callback_up)

        self.pushButton_down.clicked.connect(self.callback_down)
 

       
          
          
        #定时器20毫秒更新画板
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.GPS_SetImage)
        self.timer.start(1000) #单位为毫秒

    def callback_begin(self):
        print("开始播放")
        _translate = QtCore.QCoreApplication.translate
        self.label_msg.setText(_translate("Form", "开始播放"))
       
    def callback_stop(self):
        print("停止播放")
        _translate = QtCore.QCoreApplication.translate
        self.label_msg.setText(_translate("Form", "停止播放"))


    def callback_up(self):
        print("上一曲")
        _translate = QtCore.QCoreApplication.translate
        self.label_msg.setText(_translate("Form", "上一曲"))

    def callback_down(self):
        print("下一曲")
        _translate = QtCore.QCoreApplication.translate
        self.label_msg.setText(_translate("Form", "下一曲"))
    
    
        
    #配合定时器刷新图像显示
    def GPS_SetImage(self):
          
        
 
        now_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        #parsed_date = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
        _translate = QtCore.QCoreApplication.translate
        self.lineEditDate.setText(_translate("Form", now_time))
        

        self.plainTextEdit_GPS.clear()

        self.plainTextEdit_GPS.appendPlainText("经度:"+str(self.ShareImages[2]))
        self.plainTextEdit_GPS.appendPlainText("纬度:"+str(self.ShareImages[3]))
        self.plainTextEdit_GPS.appendPlainText("高度:"+str(self.ShareImages[4]))
        self.plainTextEdit_GPS.appendPlainText("时间:"+str(self.ShareImages[5]))
        self.plainTextEdit_GPS.appendPlainText("状态:"+str(self.ShareImages[1]))
        
    
         
 
  
    def closeEvent(self, event):
        self.ShareImages[9]=1#必须通过共享内存数据,强制关闭采集进程
        print("QT关闭窗口")
          
              
              
   
  
 
   
 
   
   
if __name__ == '__main__':
   
  


    lock = Manager().Lock()#创建共享内存容器
    ShareImages=Manager().dict()#存str类型数据
     
    ShareImages[1]=0 #"是否可用"
    ShareImages[2]=0.0#"经度"
    ShareImages[3]=0.0#"纬度"
    ShareImages[4]=0.0#"高度"
    ShareImages[5]=0#"时间"



    ShareImages[9]=0#用于关闭所有进程
    
    
  
   
    #3采集GPS
    p_gps = Process(target=gps_Get_data, args=(ShareImages,lock,1))#开启进程
    p_gps.deamon=True  #伴随主进程关闭而关闭,但是有时候还是关闭不了,单独搞个标志位来控制
    p_gps.start()#开始
 
    #----------------------QT界面主进程--------------------------------
    app = QApplication(sys.argv)
    ui=Example(ShareImages,lock) #ShareImages共享内存数据  lock 共享数据锁
    ui.show()
    sys.exit(app.exec_())
   

  

 

下载地址

https://www.u-blox.com/en/product/u-center

 

 

 找到网页往下翻一番

找到

 

 

 

 

 

 

 

 GPS模块设置

1使用ucenter设置gps输出

默认gps  9600  或者115200

 

 选择串口链接

 

 

2 设置波特率

 

 

 

 send之后重新连接gps模块,波特率修改成115200,send只是当前有效,断电恢复原来的.

 

 

3 修改GPS输出频率

 

 

 断电生效,保存在gps的内存里

 

 

 

 

4修改gps输出帧

 

 默认输出很多帧

有关于卫星信号质量的帧

有定位信息帧

有速度帧

其中包含gps的最全的是,但是没有关于卫星是否有效的信息

黑色的是正在输出,灰色的是没有输出

 

 

 

设置某些帧输出信息

 

 

 

 

 断电参数保存

 

2,$GPGGA语句

(Global Positioning System Fix Data-GGA,GPS定位信息, 输出1次/1秒)
    GPS定位主要数据,该语句中包括经纬度、质量因子、HDOP、高程、基准站号等字段。下表详细说明GPGGA语句中的各个字段:
$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,,<12>,,<14>
字段 $GPGGA语句意义——取值范围
<1> UTC时间:hhmmss.ss——000000.00~235959.99
<2> 纬度,格式:ddmm.mmmm ——0000.00000~8959.9999 (标准的度分格式)
<3> 南北半球——N北纬;S南纬
<4> 经度格式:dddmm.mmmm ——00000.0000~17959.9999 (标准的度分格式)
<5> 东西半球——E表示东经;W表示西经
<6> 质量因子——0=未定位,1=GPS单点定位固定解,2=差分定位,3=PPS解;4=RTK固定解;5=RTK浮点解;6=估计值;7=手工输入模式;8=模拟模式;
<7> 应用解算位置的卫星数——00~12
<8> HDOP,水平图形强度因子——0.500~99.000 ;大于6不可用
<9> 天线高程(海平面)——-9999.9~99999.9
<10> 线线高程单位(m) ——m
大地水准面起伏——地球椭球面相对大地水准面的高度
<12> 大地水准面起伏单位(m)   ——m
<13> 差分GPS数据期——差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空),不使用DGPS时为空
<14> 基准站号——0000~1023;不使用DGPS时为空
$GPGGA,074529.82,2429.6717,N,11804.6973,E,1,8,1.098,42.110,M,,M,,*76

 针对GXGGA的解析

# -*- coding: utf-8 -*
 
 
#  117.410465,31.768830
 

# 使用前先使用u-center设置GPS输出,去掉多余的输出
import os
import time
import serial
import serial.tools.list_ports
  
os.system('cls')
serial_portlist = list(serial.tools.list_ports.comports())
if len(serial_portlist) <= 0 :
    print('未发现可用串口')
else :
    for i in range (len(serial_portlist)):
        print(serial_portlist[i])
    #port_gps = '/dev/ttyUSB'+input('请输入GPS模块所在串口:')
    port_gps = 'COM'+input('请输入GPS模块所在串口:')
    
    ser = serial.Serial(port_gps,115200,timeout = 2)
  
    #----------------------------------------------
  
    os.system('cls')
    init = 3
    while True :
        if ser.in_waiting > 0 :
            '''
            time.sleep(0.6)#请在0.4-0.8范围内调试修改
            #过低数据不完整,过高数据被覆盖!
            os.system('cls')
            GETBYTES = ser.read(ser.in_waiting)
  
            if init :#跳过前三次数据
                print('稳定串口接收中 %d'%init)
                init = init - 1
                continue
  
            GETSTR = GETBYTES.decode()
            print('原始数据:')
            print(GETSTR) #检查接收情况
  
            #-------------------------------------
            
            GETSTR_List = GETSTR.split('\n')
            #print('共接收 %d 行数据'%len(GETSTR_List)) #检查换行分割情况  8
            '''

            line = str(ser.readline().decode("utf-8"))
            
            GETSTR_List=[]

            
            GETSTR_List.append(line)
            
            GPRMC_List = GETSTR_List[0].split(',')
            #print('$GPRMC 有 %d 个字段'%len(GPRMC_List)) #检查','分割情况   13

            print(len(GPRMC_List))
  
            if len(GPRMC_List)!=15:
                print('数据不完整')
                continue#检查数据完整度
            #------------------------------------------------
            print('')
            if GPRMC_List[6] == '0' :#0=Invalid, 1=2D/3D, 2=DGNSS, 4=Fixed RTK, 5=Float RTK, 6=Dead Reckoning

                print('当前卫星定位无效')

                
            elif GPRMC_List[6] == '2' :
                print('定位正常')
                print(GETSTR_List[0])
                print('')
  
                #--------------------------------------------
                  
                UTC = GPRMC_List[1][0:2] + ':' + GPRMC_List[1][2:4] + ':' + GPRMC_List[1][4:6]
                #UTC = UTC +' '+ GPRMC_List[9][0:2] + '/' + GPRMC_List[9][2:4] + '/20' + GPRMC_List[9][4:6]
                print('卫星UTC时间:'+UTC)
                  
                #---------------------------------------------
  
                weidu_xy = int(GPRMC_List[2][0:2])+float(GPRMC_List[2][2:11])/60
                jingdu_xy = int(GPRMC_List[4][0:3])+float(GPRMC_List[4][3:12])/60

                high = float(GPRMC_List[9]) #米
                print("高度:",high) 
                #---------------------------------------------
  
                weidu_du = int(GPRMC_List[2][0:2])
                weidu_fen = int(GPRMC_List[2][2:4])
                weidu_miao = float('0'+GPRMC_List[2][4:11])*60
                weidu = '%d°%d\'%.3f\"'%(weidu_du,weidu_fen,weidu_miao)
                print('')
                print('纬度:')
                print('%.6f'%weidu_xy)
                print(weidu)
                #----------------------------------------------
  
                jingdu_du = int(GPRMC_List[4][0:3])
                jingdu_fen = int(GPRMC_List[4][3:5])
                jingdu_miao = float('0'+GPRMC_List[4][5:12])*60
                jingdu = '%d°%d\'%.3f\"'%(jingdu_du,jingdu_fen,jingdu_miao)
                print('')
                print('经度:')
                print('%.6f'%jingdu_xy)
                print(jingdu)
                print('')
  
            else :
                print('数据有误,等待刷新')

  

 

 

 

另外一个GxRMC帧包含了

 

 

1,$GPRMC语句

(Recommended Minimum Specific GPS/TRANSIT Data-RMC,推荐定位信息1次/1秒)
    对于一般的GPS动态定位应用,GPRMC语句完全满足要求。该语句中包括经纬度、速度、时间和磁偏角等字段,这些数据为导航定位应用提供了充分的信息。下表详细说明GPRMC语句中的各个字段:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,,<12>
字段 $GPRMC语句意义——取值范围
<1> UTC时间:hhmmss.ss——000000.00~235959.99
<2> 状态,有效性 ——A表示有效;V表示无效
<3> 纬度格式:ddmm.mmmm——0000.00000~8959.9999 (标准的度分格式)
<4> 南北半球——N北纬;S南纬
<5> 经度格式:dddmm.mmmm——00000.0000~17959.9999 (标准的度分格式)
<6> 东西半球——E表示东经;W表示西经
<7> 地面速度——000.00~999.999
<8> 速度方向——000.00~359.99
<9> 日期格式,月日年——010100~123199
<10> 磁偏角,单位:度——00.00~99.99
磁偏角方向——E表示东;W表示西
<12> 模式指示及校验和—— A=自主定位,D=差分,E=估算,N=数据无效
例如:$GPRMC,074529.82,A,2429.6717,N,11804.6973,E,12.623,32.122,010806,,W,A*08

针对帧h解析 代码

# -*- coding: utf-8 -*
 
 
#  117.410465,31.768830
 

# 使用前先使用u-center设置GPS输出,去掉多余的输出
# GxGAA 有海拔高度
# GX


import os
import time
import serial
import serial.tools.list_ports
  
os.system('cls')
serial_portlist = list(serial.tools.list_ports.comports())
if len(serial_portlist) <= 0 :
    print('未发现可用串口')
else :
    for i in range (len(serial_portlist)):
        print(serial_portlist[i])
    #port_gps = '/dev/ttyUSB'+input('请输入GPS模块所在串口:')
    port_gps = 'COM'+input('请输入GPS模块所在串口:')
    
    ser = serial.Serial(port_gps,115200,timeout = 2)
  
    #----------------------------------------------
  
    os.system('cls')
    init = 3
    while True :
        if ser.in_waiting > 0 :
            '''
            time.sleep(0.6)#请在0.4-0.8范围内调试修改
            #过低数据不完整,过高数据被覆盖!
            os.system('cls')
            GETBYTES = ser.read(ser.in_waiting)
  
            if init :#跳过前三次数据
                print('稳定串口接收中 %d'%init)
                init = init - 1
                continue
  
            GETSTR = GETBYTES.decode()
            print('原始数据:')
            print(GETSTR) #检查接收情况
  
            #-------------------------------------
            
            GETSTR_List = GETSTR.split('\n')
            #print('共接收 %d 行数据'%len(GETSTR_List)) #检查换行分割情况  8
            '''

            line = str(ser.readline().decode("utf-8"))
            
            GETSTR_List=[]

            
            GETSTR_List.append(line)
            
            GPRMC_List = GETSTR_List[0].split(',')
            #print('$GPRMC 有 %d 个字段'%len(GPRMC_List)) #检查','分割情况   13
  
            if len(GPRMC_List)!=13:
                print('数据不完整')
                continue#检查数据完整度
            #------------------------------------------------
            print('')
            if GPRMC_List[2] == 'V' :
                print('当前卫星定位无效')

                
            elif GPRMC_List[2] == 'A' :
                print('定位正常')
                print(GETSTR_List[0])
                print('')
  
                #--------------------------------------------
                  
                UTC = GPRMC_List[1][0:2] + ':' + GPRMC_List[1][2:4] + ':' + GPRMC_List[1][4:6]
                UTC = UTC +' '+ GPRMC_List[9][0:2] + '/' + GPRMC_List[9][2:4] + '/20' + GPRMC_List[9][4:6]
                print('卫星UTC时间:'+UTC)
                  
                #---------------------------------------------
  
                weidu_xy = int(GPRMC_List[3][0:2])+float(GPRMC_List[3][2:11])/60
                jingdu_xy = int(GPRMC_List[5][0:3])+float(GPRMC_List[5][3:12])/60
                  
                #---------------------------------------------
  
                weidu_du = int(GPRMC_List[3][0:2])
                weidu_fen = int(GPRMC_List[3][2:4])
                weidu_miao = float('0'+GPRMC_List[3][4:11])*60
                weidu = '%d°%d\'%.3f\"'%(weidu_du,weidu_fen,weidu_miao)
                print('')
                print('纬度:')
                print('%.6f'%weidu_xy)
                print(weidu)
                #----------------------------------------------
  
                jingdu_du = int(GPRMC_List[5][0:3])
                jingdu_fen = int(GPRMC_List[5][3:5])
                jingdu_miao = float('0'+GPRMC_List[5][5:12])*60
                jingdu = '%d°%d\'%.3f\"'%(jingdu_du,jingdu_fen,jingdu_miao)
                print('')
                print('经度:')
                print('%.6f'%jingdu_xy)
                print(jingdu)
                print('')
  
            else :
                print('数据有误,等待刷新')

  

 

GPS解析库

根据协议内容,我们可以自己编写Python脚本对GPS数据进行解析。但是,实际上Python已经有现成的库可以调用——pymea2。

推荐下载方式:

pip install pynmea2

下载完成后即可导入包,并通过pynmea2.parse()方法对GPS数据进行解析,示例如下:

import pynmea2

text = "$GNRMC,074733.00,A,2241.28818,N,11358.44210,E,3.866,,070720,,,A*60"
msg = pynmea2.parse(text)

原始GPS信号的经纬度采用的是60进制的格式,通过msg.lat和msg.lon就能分别显示维度和经度信息:

 
 

 

而地图常用的格式应该是10进制的,通过msg.latitude和msg.longitude就能分别显示10进制的维度和经度信息:

 
 

GPS数据可视化

1 谷歌地球

直接搜索  31.777275,117.367401

 

 

 

3使用folium绘制经纬度轨迹图

 

folium

读取txt解析地址,可视化显示

#!/usr/bin/python
# -*- coding: UTF-8 -*-
#使用教程
# 1安装库
# 2修改txt名字

 ##pip3 install folium
import folium  #可视化工具
import os

def draw_gps(locations, output_path, file_name):
    """
    绘制gps轨迹图
    :param locations: list, 需要绘制轨迹的经纬度信息,格式为[[lat1, lon1], [lat2, lon2], ...]
    :param output_path: str, 轨迹图保存路径
    :param file_name: str, 轨迹图保存文件名
    :return: None
    """
    m = folium.Map(locations[0], zoom_start=15, attr='default')  #中心区域的确定

    folium.PolyLine(    # polyline方法为将坐标用线段形式连接起来
        locations,    # 将坐标点连接起来
        weight=3,  # 线的大小为3
        color='orange',  # 线的颜色为橙色
        opacity=0.8    # 线的透明度
    ).add_to(m)    # 将这条线添加到刚才的区域m内
    
    # 起始点,结束点
    folium.Marker(locations[0], popup='<b>Starting Point</b>').add_to(m)
    folium.Marker(locations[-1], popup='<b>End Point</b>').add_to(m)

   # len(locations)
     
    '''
    for i in locations:
        #folium.Marker(
        #i, popup="<i>Click show a test</i>", tooltip="Click me!",icon=folium.Icon(color="red", icon="info-sign")
        ).add_to(m)
   '''
    
    m.save(os.path.join(output_path, file_name))  # 将结果以HTML形式保存到指定路径
    


'''
从txt读取gps数据解析出经纬高
输入 gps_txt 文件路径和名字
输出 locations  gps数组  格式为[[lat1, lon1], [lat2, lon2], ...]

'''

def read_txtgps(gps_txt):
    locations=[]
    #gps_txt="save/video/VideoLEFT_Tue_Aug_24_19_01_46_2021.txt"
    with open(gps_txt, "r") as f:
        for line in f.readlines():
            line = line.strip('\n')  #去掉列表中每一个元素的换行符
            #print(line)
            strlist = line.split(',')
            #print(strlist[2],strlist[3])
            if strlist[1]=="-1" or strlist[1]=="0":
                pass
            else:
                locations.append([float(strlist[2]),float(strlist[3])])
    return locations


#开始调用

print("读取txt数据")
name="VideoLEFT_Wed_Aug_25_17_32_19_2021"
gps_txt=name+".txt"
map_html=name+".html"
locations=read_txtgps(gps_txt)

print("地图生成中请等待")
draw_gps(locations,"",map_html)
print(map_html,"地图网页生生结束,请用网页打开查看")

  

 

 

通过上面的解析方法,我们已经获取了传感器的维度和经度信息,接下来就能够在地图上进行可视化展示,这里我采用的是Python的folium库。

假设我们最终获取到的一批经纬度数据如下:

locations = [[22.674574, 113.993353], [22.674544, 113.993362], [22.674521, 113.993376], [22.67447, 113.99342], [22.674471, 113.993428], [22.674485, 113.993434], [22.674487, 113.993437], [22.674471, 113.993416], [22.674452, 113.993416], [22.674449, 113.993412], [22.674443, 113.993389], [22.674444, 113.993382], [22.67445, 113.993363], [22.67444, 113.993358], [22.67444, 113.993351], [22.67444, 113.993338], [22.674441, 113.993331], [22.674485, 113.993265], [22.674452, 113.993305], [22.674511, 113.99323], [22.674504, 113.993236], [22.674484, 113.99326], [22.674419, 113.993359], [22.67441, 113.993369], [22.674403, 113.993381], [22.674406, 113.993385], [22.674406, 113.993395], [22.674404, 113.993397], [22.674403, 113.9934], [22.674402, 113.993411], [22.6744, 113.993414], [22.674398, 113.993417], [22.674308, 113.993457], [22.674269, 113.99347], [22.67423, 113.99349], [22.674191, 113.993506], [22.674151, 113.993532], [22.674045, 113.993583], [22.673965, 113.993597], [22.673879, 113.993607], [22.673724, 113.993639], [22.673321, 113.993752], [22.673212, 113.993784], [22.673101, 113.993825], [22.672887, 113.993894], [22.672785, 113.993937], [22.672684, 113.993977], [22.672476, 113.994081], [22.672063, 113.994352], [22.671971, 113.994427], [22.671873, 113.994503], [22.67178, 113.994583], [22.671449, 113.994935], [22.671373, 113.995017], [22.671315, 113.995096], [22.671252, 113.995173], [22.671199, 113.995219], [22.671165, 113.99525], [22.671108, 113.995304], [22.671128, 113.995301], [22.671125, 113.995312], [22.671131, 113.995302], [22.671133, 113.995301], [22.671136, 113.99531], [22.671135, 113.995313], [22.671131, 113.995316], [22.671077, 113.995376], [22.671059, 113.995395], [22.671039, 113.995415], [22.670993, 113.995452], [22.670868, 113.995574], [22.670666, 113.995825], [22.67061, 113.995877], [22.670563, 113.995943], [22.670503, 113.996008], [22.670448, 113.996076], [22.670393, 113.996143], [22.670233, 113.996335], [22.670022, 113.996558], [22.669967, 113.996622], [22.669913, 113.996683], [22.669862, 113.996741], [22.669812, 113.996795], [22.669768, 113.996847], [22.669734, 113.996899], [22.669687, 113.996965], [22.669639, 113.997026], [22.669441, 113.997291], [22.669385, 113.997353], [22.669331, 113.997423], [22.669274, 113.997491], [22.669216, 113.997564], [22.66915, 113.997639], [22.668873, 113.997982], [22.668809, 113.998056], [22.668754, 113.998126], [22.668686, 113.998199], [22.668632, 113.998269], [22.668578, 113.998336], [22.66852, 113.998408], [22.668462, 113.998486], [22.668212, 113.998776], [22.668152, 113.998849], [22.668082, 113.998925], [22.667963, 113.999024], [22.667923000000002, 113.999077], [22.667784, 113.999228], [22.667669, 113.999349], [22.667521, 113.999529], [22.667482, 113.999574], [22.667442, 113.999625], [22.667401, 113.999676], [22.667358, 113.999724], [22.667321, 113.999774], [22.667283, 113.99982], [22.667246, 113.999863], [22.667209, 113.999906], [22.667169, 113.999947], [22.667128, 113.999992], [22.667085, 114.000046], [22.667043, 114.000096], [22.667, 114.000147], [22.666961, 114.000199], [22.66692, 114.000247], [22.66688, 114.000286], [22.666841, 114.000334], [22.666797, 114.000384], [22.66673, 114.000437], [22.666673, 114.000496], [22.666607, 114.000549], [22.666545, 114.000612], [22.666287, 114.000833], [22.66621, 114.000882], [22.666138, 114.000926], [22.66606, 114.00099], [22.665972, 114.001058], [22.665891, 114.001114], [22.665809, 114.001158], [22.665725, 114.001216], [22.665635, 114.001275], [22.665255, 114.001479], [22.665149, 114.001524], [22.66504, 114.001577], [22.664923, 114.001628], [22.664575, 114.001775], [22.664114, 114.001933], [22.664001, 114.001966], [22.663888, 114.00199], [22.663774, 114.002035], [22.663655, 114.002067], [22.66353, 114.002101], [22.663402, 114.002132], [22.663275, 114.002169], [22.663148, 114.002203], [22.66266, 114.002342], [22.662544, 114.002373], [22.662429, 114.0024], [22.662106, 114.002517], [22.662032, 114.00255], [22.661957, 114.002583], [22.661886, 114.002604], [22.661814, 114.002636], [22.661663, 114.0027], [22.661583, 114.00274], [22.661315, 114.002878], [22.661247, 114.002907], [22.661185, 114.002932], [22.66113, 114.00296], [22.660899, 114.003051], [22.660847, 114.003065], [22.660659, 114.003121], [22.660608, 114.003139], [22.66058, 114.003162], [22.660565, 114.003191], [22.660538, 114.003213], [22.660508, 114.003231], [22.660495, 114.003259], [22.660458, 114.003296], [22.660429, 114.003397], [22.660408, 114.003464], [22.660378, 114.00354], [22.660363, 114.003564], [22.660314, 114.003608], [22.6602, 114.003818], [22.660175, 114.003876], [22.660049, 114.004195], [22.660021, 114.004256], [22.66, 114.004318], [22.659912, 114.004546], [22.659893, 114.004602], [22.659884, 114.004656], [22.659863, 114.004709], [22.65984, 114.004772], [22.659823, 114.004833], [22.659774, 114.004916], [22.659742, 114.004953], [22.659702, 114.004991], [22.659526, 114.00511], [22.659313, 114.005117], [22.659275, 114.005128], [22.659236, 114.005143], [22.659204, 114.005154], [22.659177, 114.005174], [22.659, 114.005249], [22.658954, 114.005246], [22.65891, 114.005242], [22.658881, 114.005232], [22.658862, 114.005226], [22.658822, 114.005206], [22.658791, 114.005192], [22.658759, 114.005171], [22.658612, 114.005036], [22.658563, 114.005019], [22.658514, 114.005001], [22.65846, 114.004978], [22.65841, 114.004958], [22.658359, 114.004939], [22.658102, 114.0049], [22.658043, 114.004901], [22.6577, 114.00493], [22.657606, 114.004941], [22.657507, 114.004945], [22.657422, 114.004959], [22.657338, 114.00497], [22.657009, 114.005009], [22.656778, 114.005121], [22.656726, 114.005149], [22.656679, 114.005174], [22.656635, 114.005197], [22.656598, 114.005217], [22.656512, 114.00526], [22.656477, 114.005279], [22.656426, 114.005314], [22.656315, 114.005396], [22.656256, 114.00544], [22.656188, 114.00549], [22.65605, 114.005583], [22.655815, 114.005766], [22.655529, 114.005985], [22.655465, 114.006031], [22.655409, 114.006071], [22.655205, 114.00624], [22.65511, 114.006312], [22.655066, 114.006345], [22.654989, 114.006407], [22.65491, 114.006467], [22.654868, 114.006496], [22.654832, 114.006524], [22.654792, 114.006552], [22.654674, 114.006626], [22.654656, 114.006641], [22.654631, 114.006665], [22.654624, 114.006669], [22.654613, 114.006677], [22.654597, 114.006687], [22.65459, 114.006694], [22.654584, 114.006698], [22.654579, 114.006702], [22.654573, 114.006706], [22.654555, 114.006716], [22.654554, 114.006715], [22.654555, 114.006715], [22.654555, 114.006715], [22.654555, 114.006717], [22.654555, 114.006719], [22.654539, 114.00674], [22.654529, 114.006756], [22.654509, 114.00678], [22.654481, 114.006809], [22.654417, 114.006871], [22.654407, 114.006882], [22.654394, 114.006892], [22.654363, 114.006916], [22.65432, 114.006949], [22.654302, 114.006962], [22.654289, 114.006973], [22.654275, 114.006982], [22.654257, 114.006994], [22.65424, 114.007007], [22.654223, 114.007018], [22.654195, 114.007035], [22.654146, 114.007078], [22.65413, 114.007096], [22.654124, 114.007102], [22.654116, 114.00711], [22.654035, 114.00718], [22.653994, 114.007212], [22.653942, 114.007248], [22.653891, 114.007284], [22.653837, 114.007319], [22.653782, 114.00736], [22.653725, 114.007406], [22.653665, 114.007455], [22.653604, 114.007507], [22.653537, 114.007559], [22.653237, 114.007795], [22.653162000000002, 114.007853], [22.652859, 114.008086], [22.65279, 114.008141], [22.652722, 114.008193], [22.652486, 114.008392], [22.652425, 114.008436], [22.652364, 114.008478], [22.652141, 114.008652], [22.651907, 114.008831], [22.651843, 114.008877], [22.651779, 114.008923], [22.651713, 114.008971], [22.651653, 114.009008], [22.651391, 114.009213], [22.651153, 114.009397], [22.651097, 114.00944], [22.651041, 114.009481], [22.650994, 114.009514], [22.650954, 114.009544], [22.650919000000002, 114.009572], [22.650851, 114.009628], [22.650815, 114.009661], [22.65078, 114.00969], [22.650748, 114.009719], [22.650626, 114.009822], [22.65059, 114.009849], [22.65056, 114.009878], [22.65052, 114.009909], [22.6504, 114.010005], [22.650277, 114.010077], [22.650266, 114.01009], [22.65026, 114.010104], [22.65026, 114.010105], [22.650258, 114.010107], [22.650254, 114.01011], [22.650244, 114.010115], [22.65025, 114.010123], [22.65025, 114.010126], [22.650253, 114.010131], [22.650257, 114.010133], [22.650256, 114.010134], [22.650252000000002, 114.010136], [22.65025, 114.010136], [22.650243, 114.010136], [22.650249, 114.010139], [22.650238, 114.010139], [22.650215, 114.010136], [22.650215, 114.010139], [22.650212, 114.010143], [22.650206, 114.010148], [22.650205, 114.010155], [22.6502, 114.010159], [22.650197, 114.010161], [22.650194, 114.010163], [22.650187, 114.010171], [22.650187, 114.010172], [22.650187, 114.010174], [22.650187, 114.010176], [22.650187, 114.010178], [22.650186, 114.010178], [22.650176, 114.010181], [22.65017, 114.010186], [22.650168999999998, 114.010187], [22.65017, 114.010188], [22.65017, 114.010189], [22.650174, 114.01019], [22.650174, 114.01019], [22.650175, 114.010185], [22.650177, 114.010184], [22.65018, 114.010183], [22.650181, 114.010184], [22.650179, 114.010183], [22.650175, 114.010181], [22.650164, 114.010177], [22.650164, 114.010168], [22.65016, 114.010171], [22.650156, 114.010171], [22.650077, 114.010223], [22.65005, 114.010245], [22.650019, 114.010266], [22.64999, 114.01029], [22.64996, 114.010309], [22.649917, 114.010341], [22.649892, 114.010353], [22.649874, 114.010367], [22.649844, 114.01039], [22.649637, 114.010561], [22.649569, 114.010614], [22.649493, 114.010679], [22.649349, 114.010807], [22.64928, 114.010869], [22.649211, 114.010927], [22.649142, 114.010986], [22.649075, 114.011046], [22.64888, 114.01122], [22.648835, 114.011255], [22.648791, 114.01129], [22.648697, 114.011371], [22.648469, 114.011552], [22.64841, 114.011602], [22.648349, 114.011651], [22.648288, 114.011697], [22.648226, 114.011744], [22.648162, 114.01179], [22.647882, 114.012002], [22.647812000000002, 114.012056], [22.647737, 114.012115], [22.647455, 114.01231], [22.647386, 114.01235], [22.647316, 114.01239], [22.647259, 114.01242], [22.647165, 114.012422], [22.647145, 114.012414], [22.647127, 114.012402], [22.647107, 114.012387], [22.647089, 114.012372], [22.647061, 114.012348], [22.647032, 114.012301], [22.646994, 114.012256], [22.646963, 114.012211], [22.646934, 114.012167], [22.6469, 114.012126], [22.646858, 114.012074], [22.646829, 114.012025], [22.646798, 114.011976], [22.646676, 114.011792], [22.646641, 114.011738], [22.646593, 114.011682], [22.646548, 114.011619], [22.646392, 114.011391], [22.646359, 114.011348], [22.646242, 114.011275], [22.64621, 114.011284], [22.646176, 114.011308], [22.646057, 114.011403], [22.646036, 114.011422], [22.646023, 114.011419], [22.645966, 114.011418], [22.645968, 114.01141], [22.645971, 114.011398], [22.645968, 114.011385], [22.645959, 114.011384], [22.645965, 114.011382], [22.645963, 114.011381], [22.645963, 114.011377], [22.645955, 114.011391], [22.64595, 114.011385], [22.645947, 114.011383], [22.64595, 114.011378], [22.645932, 114.011349], [22.645955999999998, 114.011367], [22.645954, 114.011364], [22.64595, 114.011361], [22.645944, 114.011363], [22.645945, 114.011366], [22.645925, 114.011378], [22.645917, 114.011377], [22.645914, 114.01137], [22.645915, 114.011394], [22.645914, 114.011395], [22.645919, 114.011399], [22.645902, 114.011416], [22.645927, 114.01145], [22.645934, 114.01145], [22.645931, 114.011415], [22.645931, 114.011423], [22.64594, 114.011465], [22.645958, 114.011438], [22.64597, 114.011438], [22.645948, 114.011414], [22.645972, 114.011407], [22.645969, 114.011389], [22.645957, 114.011383], [22.645966, 114.011391], [22.646028, 114.011349], [22.646038, 114.011348], [22.646038, 114.011346], [22.646144, 114.011338], [22.646165, 114.011331], [22.646185, 114.011323], [22.646296, 114.011279], [22.646366, 114.011254], [22.646385, 114.011245], [22.646409, 114.011188], [22.64643, 114.011175], [22.645819, 114.011172], [22.645744, 114.011106], [22.645695, 114.011069], [22.64569, 114.011058], [22.64581, 114.011152], [22.645709, 114.011067], [22.645675, 114.011042], [22.645633, 114.011031], [22.645633, 114.011066], [22.645639, 114.011083], [22.645645000000002, 114.01109], [22.64563, 114.011079], [22.645635, 114.011107], [22.645651, 114.011131], [22.645679, 114.011169], [22.645688, 114.011188], [22.645694, 114.011194], [22.645697, 114.011206], [22.6457, 114.011215], [22.645707, 114.011226], [22.645692, 114.011203], [22.645708, 114.011211], [22.645718, 114.011244], [22.645722, 114.011281]]

  

注意:顺序为[纬度,经度]。

编写Python函数绘制GPS轨迹图:

 

def draw_gps(locations, output_path, file_name):
    """
    绘制gps轨迹图
    :param locations: list, 需要绘制轨迹的经纬度信息,格式为[[lat1, lon1], [lat2, lon2], ...]
    :param output_path: str, 轨迹图保存路径
    :param file_name: str, 轨迹图保存文件名
    :return: None
    """
    m = folium.Map(locations[0], zoom_start=15, attr='default')  #中心区域的确定

    folium.PolyLine(    # polyline方法为将坐标用线段形式连接起来
        locations,    # 将坐标点连接起来
        weight=3,  # 线的大小为3
        color='orange',  # 线的颜色为橙色
        opacity=0.8    # 线的透明度
    ).add_to(m)    # 将这条线添加到刚才的区域m内
    
    # 起始点,结束点
    folium.Marker(locations[0], popup='<b>Starting Point</b>').add_to(m)
    folium.Marker(locations[-1], popup='<b>End Point</b>').add_to(m)
    
    m.save(os.path.join(output_path, file_name))  # 将结果以HTML形式保存到指定路径
   

  

GPS轨迹图结果:

 

 

 

解决folium国内访问太慢的问题

如果我们直接用浏览器打开生成的HTML文件,有可能会发现网络访问非常缓慢,需要加载大概1分钟才能看到地图显现。
我们打开用folium生成的HTML文件就可以看到:

 
 

 

由于生成的HTML文件调用的很多资源都是访问的国外资源,所以在国内打开可能会比较慢。这时候我们可以考虑把这些静态资源下载到本地,然后采用Python读取HTML,修改静态资源路径的方式,把HTML中的css和js路径修改成本地路径,这样就能够极大程度的提高速度。
示例如下:

 
 

可以看到示例中有一行我没有进行修改,这是因为我在前面绘制地图的时候增加了起始点的绘制,如果把这个css路径改了就会导致无法正常显示起始点(没有下载起始点图标),再加上这个css网络访问起来并不慢,所以我没有进行替换。

 

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.6.0/dist/leaflet.css"/>

修改了静态资源访问路径的HTML,再次打开的速度应该是非常快的,如果地图加载依然比较慢,那就是地图瓦片的网络问题了,而非静态资源的问题。




3 censium

https://www.cnblogs.com/gooutlook/p/13891300.html

 

4 高德可视化

GPS在国内的数据都加了密,直接显示并不是原始的地方,需要地图纠偏.

https://lbs.amap.com/demo/javascript-api/example/other-gaode/othertoamap-more

 

posted on 2021-08-23 18:51  MKT-porter  阅读(2541)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3