SIM820X-M2 5G HAT 在高德地图API精准定位

来自Waveshare Wiki
跳转至: 导航搜索

摘要:为什么SIM7600定位和我的位置差异这么大(将SIM7600X获取到的坐标系放到百度或者高德地图坐标反查),甚至有几条街的差距呢,其实是坐标系和单位的差异。下面就让我们来验证一下:

硬件准备

硬件连接图

SIM7600G-H-4G-for-Jetson-Nano-6.jpg

软件准备

原理分析

SIM7600X用到的坐标系是WGS-84坐标系;而我们常用的百度或者高德地图用到的坐标系是经过加密的百度坐标(bd09)和火星坐标系(gcj_02)。因此,如果直接将WGS-84坐标系放到百度或者高德等地图是有很大误差的(放到谷歌地图可以)此外,SIM7600获取到的经纬度是分为单位,需要先转换常用的单位度: SIMXXX GNSS API.png

SIMXXX获取经纬度等位置信息

由于 GPS 室内搜索不稳定,请将模块或者天线放到阳台或窗户旁,或者直接在户外进行实验。 插上GPS天线,并将接收器标签面朝下置于空旷的室外,在正常情况下(户外,天气良好,没有大型建筑遮挡)上电需要等待约1分钟才能接收到定位信号;如果天气条件不好,可能需要更长的定位时间,甚至无法定位。

  • 打开minicom,发送以下指令打开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
               
  1. 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
  1. 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
wget https://www.waveshare.net/w/upload/1/17/SIMXXX-GNSS.zip
sudo python3 SIM7600X-GNSS.py
  • 结果显示:
114.0832857092161,22.53842762954979

我的位置

API GAODE SIM7600X.png