一、GPS模块数据格式
笔者在项目中使用过移远L76K以及梦芯MXT905HM两款GPS定位芯片,两款芯片均是采用串口输出数据,而且数据包采用的是NEMA协议消息结构,消息结构如下:
数据包格式如下:
$GNTXT,01,01,02,ANTSTATUS=OPEN*35
$GNRMC,032323.000,A,3028.123102,N,11423.526968,E,0.682,113.01,210622,,E,A,V*7E
$GNVTG,113.01,T,,M,0.682,N,1.263,K,A*2B
$GNGGA,032323.000,3028.123102,N,11423.526968,E,1,10,1.05,68.932,M,-13.78,M,,*5B
$GNGSA,A,3,01,03,14,19,30,194,195,,,,,,1.77,1.05,1.42,1*0E
$GNGSA,A,3,01,04,28,,,,,,,,,,1.77,1.05,1.42,4*09
$GPGSV,2,1,08,01,18,044,27,03,42,066,45,06,,,22,14,72,167,18,1*59
$GPGSV,2,2,08,19,43,318,27,30,11,196,23,194,45,154,38,195,66,053,40,1*69
$GBGSV,1,1,04,01,42,130,37,04,30,115,34,28,56,016,40,33,,,12,1*4F
$GNGLL,3028.123102,N,11423.526968,E,032323.000,A,A*4D
二、应用说明
实际应用中需要根据GPS坐标信息得到设备分布位置,以及根据相邻位置坐标获取设备移动距离,这里使用python对GPS模块输出的位置坐标信息进行提取,并使用python库对坐标位置进行描点,生成设备位置分布图,根据前后两点的坐标计算出设备移动的距离
1、python解析数据
使用串口助手将GPS模组数据提取出来,并保存为gps.txt文档,放到python脚本目录下。编写程序提取坐标信息
def create_float_value(tmpfloat):
intPart = 0.0
fractPart = 0.0
fractPart, intPart = math.modf(tmpfloat)
#print(fractPart, intPart)
tempVal1 = int(intPart / 100)
tempVal2 = int(intPart % 100)
tempVal3 = tempVal2 + fractPart
tempVal4 = tempVal3 / 60.0
tempVal5 = tempVal1 + tempVal4
return tempVal5
fp = open("gps.txt", 'r')
lines = fp.readlines()
line_num = 0
longitude_list = []
latitude_list = []
for line in lines:
if line[:6] == '$GNGLL':
longitude_list.append(create_float_value(float(line.split(',')[3])))
latitude_list.append(create_float_value(float(line.split(',')[1])))
else:
continue
函数create_float_value():浮点数转换函数,模块回复数据中的坐标采用ddmm.mmmmm格式,需要转换成度.分的浮点数据
将数据提取到列表中,分别对应经度和纬度
2、使用folium库将数据展示出来
folium库可将WGS-84坐标直接带入使用,模块回复数据也是WGS-84坐标,所以直接带入调试。这里笔者使用的是pycharm,安装folium库非常方便。
import folium
map_info = folium.Map(location=[30.2813, 114.2352], zoom_start=12, control_scale=True)
for longitude, latitude in zip(longitude_list, latitude_list):
folium.Circle((latitude, longitude), radius=7, color='yellow', fill=True,
fill_color='red', fill_opacity=0.7).add_to(map_info)
lenth = len(longitude_list)
for i in range(lenth):
folium.Marker(location=[latitude_list[i], longitude_list[i]], popup='点',
icon=folium.Icon(icon='cloud')).add_to(map_info)
map_info.add_child(folium.LatLngPopup())
map_info.save('gps.html')
这里笔者将所有点用同一个图标在地图上显示出来,所以实际效果中图标大部分重合在一起,有兴趣的朋友可以自行去修改,显示不同的点,最后生成一个html格式的网页文件,用浏览器打开即可看到分布
3、坐标系转换
在验证坐标准确性的时候,笔者使用的是百度坐标拾取系统, 但是模块输出的并非百度坐标系,所以需要用算法去转换,这里笔者参考网上资料(C语言)常用的几种在线地图(天地图、百度地图、高德地图)坐标系之间的转换算法_四域公子的博客-CSDN博客_天地图坐标系自行编写了python函数来实现坐标转换,先调用transform_both_all(),之后再调用mars_to_baidu(),即可获得百度坐标,笔者实测,转换后的坐标在百度拾取系统中基本一致(存在浮点数计算的误差),有兴趣的朋友可以自行去计算误差,然后补偿
import math
import os
PI = 3.14159265358979324
ax = 6378245.0
ee = 0.00669342162296594323
x_pi = 52.3598775598298873
def outofChina(lat, lon):
if (lon < 72.004 or lon > 137.8347) and (lat < 0.8293 or lat > 55.8271):
return True
else:
return False
def mars_to_baidu(longtide, latitude):
baidu_long = 0.0
baidu_lati = 0.0
z = math.sqrt(longtide*longtide + latitude*latitude) + 0.00002 * math.sin(latitude * x_pi)
theta = math.atan2(latitude, longtide) + 0.000003 * math.cos(longtide * x_pi)
baidu_long = z * math.cos(theta) + 0.0065
baidu_lati = z * math.sin(theta) + 0.006
return baidu_long, baidu_lati
def transformLat(x , y):
ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(math.fabs(x))
ret += (20.0 * math.sin(6.0 * x * PI) + 20.0 * math.sin(2.0 * x * PI)) * 2.0 / 3.0
ret += (20.0 * math.sin(y * PI) + 40.0 * math.sin(y / 3.0 * PI)) * 2.0 / 3.0
ret += (160.0 * math.sin(y / 12.0 * PI) + 320.0 * math.sin(y * PI / 30.0)) * 2.0 / 3.0
return ret
def transformLon(x, y):
ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(math.fabs(x))
ret += (20.0 * math.sin(6.0 * x * PI) + 20.0 * math.sin(2.0 * x * PI)) * 2.0 / 3.0
ret += (20.0 * math.sin(x * PI) + 40.0 * math.sin(x / 3.0 * PI)) * 2.0 / 3.0
ret += (150.0 * math.sin(x / 12.0 * PI) + 300.0 * math.sin(x / 30.0 * PI)) * 2.0 / 3.0
return ret
def transform_both_all(wgLat, wgLon):
trans_long = 0.0
trans_lati = 0.0
if outofChina(wgLat, wgLon):
trans_long = wgLon
trans_lati = wgLat
return 0, 0
dLat = transformLat(wgLon - 105.0, wgLat - 35.0)
dLon = transformLon(wgLon - 105.0, wgLat - 35.0)
radLat = wgLat / 180.0 * PI
magic = math.sin(radLat)
magic_2 = 1 - ee * magic * magic
sqrtMagic = math.sqrt(magic_2)
dLat_2 = (dLat * 180.0) / ((ax * (1 - ee)) / (magic_2 * sqrtMagic) * PI)
dLon_2 = (dLon * 180.0) / (ax / sqrtMagic * math.cos(radLat) * PI)
trans_lati = wgLat + dLat_2
trans_long = wgLon + dLon_2
return trans_long, trans_lati
4、相邻坐标换算距离
已知两个点的经纬度坐标信息,计算两个点之间的距离,笔者用同一位置模块输出位置信息测试,传入相邻点的位置信息,计算出来的距离(KM),参考代码:根据坐标经纬度计算两点之间的距离_weixin_33696106的博客-CSDN博客
def ConvertDegreesToRadians(degrees):
return degrees * PI / 180.0
def ConvertRadiansToDegrees(radian):
return radian * 180.0 / PI
def HaveSin(theta):
val = math.sin(theta / 2)
return val * val
def Long_Lati_Distance(lat1, long1, lat2, long2):
earth_radius = 6371.0
temp_lat_1 = ConvertDegreesToRadians(lat1)
temp_lon_1 = ConvertDegreesToRadians(long1)
temp_lat_2 = ConvertDegreesToRadians(lat2)
temp_lon_2 = ConvertDegreesToRadians(long2)
vLon = math.fabs(temp_lon_1 - temp_lon_2)
vLat = math.fabs(temp_lat_1-temp_lat_2)
high = HaveSin(vLat) + math.cos(temp_lat_1) * math.cos(temp_lat_2) * HaveSin(vLon)
distance = 2 * earth_radius * math.asin(math.sqrt(high))
return distance
完整代码:python提取gps数据,利用folium库生成位置分布图,包含百度坐标转换以及两点距离换算函数-智慧城市文档类资源-CSDN下载