摘要:SIM7600X 4G HAT因其完善的功能以及稳定的性能深受世人的钟爱,但SIM7600X 4G HAT上网是很犀利,可为什么SIM7600定位和我的位置差异这么大(将SIM7600X获取到的坐标系放到百度或者高德地图坐标反查),有几条街的差距呢。下面让我们走进GNSS的大街里走一走,看看是谁用了时空转移:
硬件准备
硬件连接图
软件准备
原理分析
SIM7600X用到的坐标系是WGS-84坐标系;而我们常用的百度或者高德地图用到的坐标系是经过加密的百度坐标(bd09)和火星坐标系(gcj_02)。因此,如果直接将WGS-84坐标系放到百度或者高德等地图是有很大误差的(放到谷歌地图可以)此外,SIM7600获取到的经纬度是分为单位,需要先转换常用的单位度:
SIMXXX获取经纬度等位置信息
温馨提示:
- 由于 GPS 室内搜星不稳定,请将模块或者天线放到阳台或窗户旁,或者直接在户外进行实验。
- 插上GPS天线,并将接收器标签面朝下置于空旷的室外,在正常情况下(户外,天气良好,没有大型建筑遮挡)上电需要等待约1分钟才能接收到定位信号;如果天气条件不好,可能需要更长的定位时间,甚至无法定位。
- 发送以下指令打开GPS:
AT+CGPS=1
- 用以指令获取经纬度等位置信息:
AT+CGPSINFO
- 打开NEMA获取详细信息
sudo minicom -D /dev/ttyUSB1
- 单位转换
ddmm.mm--> dd.mm.ss: 度数不变,分数*100/60 :
如2232.448620--> 22.(32448620*100/60)= 22.54081033
- 坐标系转换关键代码
def wgs84_to_gcj02(lng, lat):
"""
WGS84转GCJ02(火星坐标系)
:param lng:WGS84坐标系的经度
:param lat:WGS84坐标系的纬度
:return:
"""
dlat = _transformlat(lng - 105.0, lat - 35.0)
dlng = _transformlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
mglat = lat + dlat
mglng = lng + dlng
return [mglng, mglat]
def wgs84_to_bd09(lon, lat):
lon, lat = wgs84_to_gcj02(lon, lat)
return gcj02_to_bd09(lon, lat)
def _transformlng(lng, lat):
ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
math.sin(2.0 * lng * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(lng * pi) + 40.0 *
math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
return ret
def _transformlat(lng, lat):
ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
math.sin(2.0 * lng * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(lat * pi) + 40.0 *
math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
math.sin(lat * pi / 30.0)) * 2.0 / 3.0
return ret
- 编辑并保存示例程序
sudo nano SIMXXX.py
from socket import socket
import sys
import re
import pynmea2
import serial
import chardet
import time
import math
import json
global Latitude
global Longitude
global line
global line1
global ser2
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626 # π
a = 6378245.0 # Semi-major axis
ee = 0.00669342162296594323 # Eccentricity squared
def _transformlng(longitude, latitude):
ret = 300.0 + longitude + 2.0 * latitude + 0.1 * longitude * longitude + \
0.1 * longitude * latitude + 0.1 * math.sqrt(math.fabs(longitude))
ret += (20.0 * math.sin(6.0 * longitude * pi) + 20.0 *
math.sin(2.0 * longitude * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(longitude * pi) + 40.0 *
math.sin(longitude / 3.0 * pi)) * 2.0 / 3.0
ret += (150.0 * math.sin(longitude / 12.0 * pi) + 300.0 *
math.sin(longitude / 30.0 * pi)) * 2.0 / 3.0
return ret
def _transformlat(longitude, latitude):
ret = -100.0 + 2.0 * longitude + 3.0 * latitude + 0.2 * latitude * latitude + \
0.1 * longitude * latitude + 0.2 * math.sqrt(math.fabs(longitude))
ret += (20.0 * math.sin(6.0 * longitude * pi) + 20.0 *
math.sin(2.0 * longitude * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(latitude * pi) + 40.0 *
math.sin(latitude / 3.0 * pi)) * 2.0 / 3.0
ret += (160.0 * math.sin(latitude / 12.0 * pi) + 320 *
math.sin(latitude * pi / 30.0)) * 2.0 / 3.0
return ret
def setup():
# global response
ser2 = serial.Serial("/dev/ttyUSB2",115200)
print("ttyUSB2 Open!!!")
ser2.write('AT+CGPS=1\r'.encode())
print("AT+CGPS=1")
ser2.close()
print("ttyUSB2 Close!!!")
def loop():
global ser1
ser1 = serial.Serial("/dev/ttyUSB1",115200)
print("ttyUSB1 Open!!!")
while True:
line = str(ser1.readline(),encoding='utf-8')
if line.startswith("$GPRMC"):
global Longitude
global Latitude
rmc = pynmea2.parse(line)
if re.match("^\d+?\.\d+?$", rmc.lat)is not None:
print(rmc)
latitude = rmc.latitude
longitude= rmc.longitude
# ''' SIM820X uses the gcj_02 coordinate system, no coordinate conversion is required
dlat = _transformlat(longitude - 105.0, latitude - 35.0)
dlng = _transformlng(longitude - 105.0, latitude - 35.0)
radlat = latitude / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
mglat = latitude + dlat
mglng = longitude + dlng
# '''Please comment out the conversion part
print ("longitude,latitude")#longitude,latitude
print (""+str(mglng)+","+str(mglat)+"")#经度,纬度
time.sleep(2)
def destroy():
ser1.close()
print("ttyUSB1 Close!!!")
ser2 = serial.Serial("/dev/ttyUSB2",115200)
print("ttyUSB2 Open!!!")
ser1.close()
print("ttyUSB1 Close!!!")
ser2.close()
print("ttyUSB2 Close!!!")
try:
setup()
loop()
except KeyboardInterrupt:
destroy()
- 运行示例程序后生成的坐标复制到高德地图API
sudo pip3 install pynmea2
sudo pip3 install pynmeagps
sudo python3 SIM7600X-GNSS.py
114.0832857092161,22.53842762954979
- 我的位置
小编在世界贸易贸易广场的南侧窗边(不小心暴露了小编的位置,找到我请您喝茶,哈哈!),定位和我有1-2米的误差,有转换和硬件本身决定的,不同的测试环境和转换算法,可能误差有所差异。