SIMXXX 在高德地图定位到我的位置
来自Waveshare Wiki
摘要
SIM7600X 4G HAT因其完善的功能以及稳定的性能深受世人的钟爱,但是有不少小鲜肉就吐槽说,SIM7600X 4G HAT上网是很犀利,可为什么SIM7600定位和我的位置差异这么大(将SIM7600X获取到的坐标系发到百度或者高德地图坐标反查),有几条街的差距呢。下面让我们走进GNSS的大街里走一走,看看是谁用了时空转移:
硬件准备
硬件连接图
软件准备
原理分析
SIM7600X用到的坐标系是WGS-84坐标系,SIM820X用到的是火星坐标系(gcj_02);而我们常用的百度或者高德地图用到的坐标系是经过加密的百度坐标(bd09)和火星坐标系(gcj_02)。因此,如果直接将WGS-84坐标系放到百度或者高德等地图是有很大误差的(放到谷歌地图可以);此外,SIMXXX获取到的经纬度是分为单位,需要先转换常用的度单位:
![]()
SIMXXX获取经纬度等位置信息
由于 GPS 室内搜星不稳定,请将模块或者天线放到阳台或窗户旁,或者直接在户外进行实验。
插上GPS天线,并将接收器标签面朝下置于空旷的室外,在正常情况下(户外,天气良好,没有大型建筑遮挡)上电需要等待约1分钟才能接收到定位信号;如果天气条件不好,可能需要更长的定位时间,甚至无法定位
- 发送以下指令打开GPS:
AT+CGPSAUTO=1 AT+CVAUXS=1
- 用以指令获取经纬度等位置信息:
AT+CGPSINFO
- 打开NEMA获取详细信息
sudo minicom -D /dev/ttyUSB1
- 单位转换
ddmm.mm--> dd.mm.ss: 度数不变,分数*100/60 ;如2232.448620--> 22.(32448620*100/60)= 22.54081033
- 代码展示
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 rm /usr/lib/python3.11/EXTERNALLY-MANAGED sudo pip3 install --upgrade pip sudo pip3 install pynmea2 sudo pip3 install pynmeagps wget https://www.waveshare.net/w/upload/1/17/SIMXXX-GNSS.zip sudo unzip SIMXXX-GNSS.zip sudo python3 SIMXXX-GNSS.py
114.0832857092161,22.53842762954979
我的位置
在世界贸易贸易广场的南侧窗边定位,定位和小编所在位置有不超过10米的误差;不同的测试环境和转换算法,可能误差有所差异。
更多相关教程
FAQ
如果遇到库安装和没有经纬度等问题,可以用这个程序看初始GNSS报文
import serial
import time
ser = serial.Serial('/dev/ttyUSB2', baudrate=115200, timeout=1)
ser.write(b'AT+CGPS=1\r\n')
time.sleep(1)
ser.write(b'AT+CGPSINFOCFG=1,31\r\n')
time.sleep(1)
def read_all_data():
try:
while True:
if ser.in_waiting:
raw_data = ser.read(ser.in_waiting)
try:
decoded_data = raw_data.decode('ascii').strip()
for line in decoded_data.split('\n'):
line = line.strip()
if line.startswith('$') or line.startswith('+CGPSINFO'):
print(line)
except UnicodeDecodeError:
continue
time.sleep(0.1)
except KeyboardInterrupt:
print("\nStop")
ser.close()
read_all_data()
