gps经纬度换算,WGS-84->GCJ02->BD-09

在经纬度换算前,我们先了解一下常用的坐标种类有哪些:

1、大地坐标系统 WGS-84

用来表述地球上点的位置的一种地区坐标系统。它采用一个十分近似于地球自然形状的参考椭球作为描述和推算地面点位置和相互关系的基准面。一个大地坐标系统必须明确定义其三个坐标轴的方向和其中心的位置。通常人们用旋转椭球的短轴与某一规定的起始子午面分别平行干地球某时刻的平均自转轴和相应的真起始子午面来确定坐标轴的方向。若使参考椭球中心与地球平均质心重合,则定义和建立了地心大地坐标系。它是航天与远程武器和空间科学中各种定位测控测轨的依据。若椭球表面与一个或几个国家的局部大地水准面吻合最好,则建立了一个国家或区域的局部大地坐标系。大地坐标系中点的位置是以其大地坐标表示的,大地坐标均以椭球面的法线来定义。其中,过某点的椭球面法线与椭球赤道面的交角为大地纬度;包含该法线和大地子午面与起始大地子午面的二面角为该点的大地经度;沿法线至椭球面的距离为该点的大地高。大地纬度、大地经度和大地高分别用大写英文字母B、L、H表示。

国内的互联网公司,都不会使用GPS坐标,因为这不符合国家政策。所以大家都会使用GCJ-02坐标系。

2、火星坐标系统 GCJ-02

国家保密插件,也叫做加密插件或者加偏或者SM模组,其实就是对真实坐标系统进行人为的加偏处理,按照几行代码的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。而加密后的坐标也常被人称为火星坐标系统。

目前使用火星坐标系的地图商:

  • 腾讯搜搜地图
  • 搜狐搜狗地图
  • 阿里云地图
  • 高德MapABC地图
  • 灵图51ditu地图

所有的电子地图所有的导航设备,都需要加入国家保密插件。第一步,地图公司测绘地图,测绘完成后,送 到国家测绘局,将真实坐标的电子地图,加密成“火星坐标”,这样的地图才是可以出版和发布的,然后才可以让GPS公司处理。第二步,所有的GPS公司,只要需要汽车导航的,需要用到导航电子地图的,统统需要在软件中加入国家保密算法,将COM口读出来的真实的坐标信号,加密转换成国家要求的保密的坐标,这样,GPS导航仪和导航电子地图就可以完全匹配,GPS也就可以正常工作。

国内互联网公司,都必须使用GCJ-02坐标系。

3、百度坐标系统 BD-09

百度坐标对火星坐标系进行了一次加密,形成了百度坐标系.

目前使用百度坐标系的地图商:

  • 百度Baidu地图

少部分公司会在GCJ-02的基础上再进行一次加密,但这样的坐标不通用,只适于特定公司的地图

坐标的获取:

我们通过GPS模块来测量出当前位置的经纬度信息,使用的模块如图:

通过电脑的串口调试助手可查看GPS模块收到的信息,该模块收到的信息符合NMEA协议,由于本文章只需要经纬度信息,所以就简单对其中一条数据进行讲解,如:

GGA(Global Positioning System Fix Data)GPS定位信息

$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*hh<CR><LF>

<1> UTC时间,hhmmss(时分秒)格式,和北京时间差8个小时。

<2> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)

<3> 纬度半球N(北半球)或S(南半球)

<4> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)

<5> 经度半球E(东经)或W(西经)

<6> GPS状态:0=未定位,1=单点定位,2=SBAS差分定位,4=RTK固定解,5=RTK浮点解,6=惯导定位

<7> 正在使用解算位置的卫星数量(00~12)(前面的0也将被传输)

<8> HDOP水平精度因子(0.5~99.9)

<9> 海拔高度(-9999.9~99999.9)

<10> 地球椭球面相对大地水准面的高度

<11> 差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空)

<12> 差分站ID号0000~1023(前面的0也将被传输,如果不是差分定位将为空)

其中的经度就是10403.514810E

其中的纬度就是3043.506913N

这里提供一个使用python来读取串口中GPS模块收到数据的代码

# -*- coding: UTF-8 -*-
# 请看下面代码
import serial

# port就是电脑连接GPS模块的串口名,可通过电脑设备管理器查看
# baudrate参数代表模块的波特率,文章展示的这一款模块的波特率默认为38400
ser = serial.Serial(port='COM3', baudrate=38400, stopbits=1, bytesize=8, timeout=1)
s = ser.readline()
s = str(s)
print(s)

经纬度换算

(注:每一个经纬度数据对应不同坐标系地图上的位置是不同的,所以需要对坐标点进行换算,顺序是WGS-84 --> GCJ-02 --> BD-09,需要一步一步实现

1.模块获得的数据换算成WGS-84坐标中的数值

通过以上内容可知,我们获得了经纬度信息10403.514810E,3043.506913N,所以接下来先将此数据进行一地步处理,也就是转换成WGS-84坐标,计算过程如下:

10403.514810E -> 104 + 3.514810/60.0 = 104.05858016(保留八位小数)

3043.506913N -> 30 + 43.506913/60.0 = 30.72511521(保留八位小数)

 

 通过以上方式,我们获得了WGS-84S坐标系下的经纬度信息104.05858016,30.72511521

2.将WGS-84坐标中的数值换算成GCJ-02坐标下的数值

话不多说,直接上代码(python版本)

import math

class GetGpsMessage(object):
    def __init__(self):
        self.x_pi = 3.14159265358979324 * 3000.0 / 180.0
        self.pi = 3.1415926535897932384626  # π
        self.a = 6378245.0  # 长半轴
        self.ee = 0.00669342162296594323  # 偏心率平方

    def _transformlat(self, 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 * self.pi) + 20.0 *
                math.sin(2.0 * lng * self.pi)) * 2.0 / 3.0
        ret += (20.0 * math.sin(lat * self.pi) + 40.0 *
                math.sin(lat / 3.0 * self.pi)) * 2.0 / 3.0
        ret += (160.0 * math.sin(lat / 12.0 * self.pi) + 320 *
                math.sin(lat * self.pi / 30.0)) * 2.0 / 3.0
        return ret

    def _transformlng(self, 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 * self.pi) + 20.0 *
                math.sin(2.0 * lng * self.pi)) * 2.0 / 3.0
        ret += (20.0 * math.sin(lng * self.pi) + 40.0 *
                math.sin(lng / 3.0 * self.pi)) * 2.0 / 3.0
        ret += (150.0 * math.sin(lng / 12.0 * self.pi) + 300.0 *
                math.sin(lng / 30.0 * self.pi)) * 2.0 / 3.0
        return ret

    def wgs84_to_gcj02(self, lng, lat):
        """
        WGS84转GCJ02(火星坐标系)
        :param lng:WGS84坐标系的经度
        :param lat:WGS84坐标系的纬度
        :return:
        """
        dlat = self._transformlat(lng - 105.0, lat - 35.0)
        dlng = self._transformlng(lng - 105.0, lat - 35.0)
        radlat = lat / 180.0 * self.pi
        magic = math.sin(radlat)
        magic = 1 - self.ee * magic * magic
        sqrtmagic = math.sqrt(magic)
        dlat = (dlat * 180.0) / ((self.a * (1 - self.ee)) / (magic * sqrtmagic) * self.pi)
        dlng = (dlng * 180.0) / (self.a / sqrtmagic * math.cos(radlat) * self.pi)
        mglat = lat + dlat
        mglng = lng + dlng
        return [mglng, mglat]

    def getGpsMessage(self):
        try:
            '''
            gps经纬度计算方法
            读出来的数值为:3155.09004,N,10122.24349,E
            N = 31 + 55.09004/60
            E = 101 + 22.24349/60

            '''

            latitudeObj = ['3155.2860N', '3111.1850N']# 纬度信息,用于测试,请替换为自己的信息
            longitudeObj = ['10218.2207E', '10158.8107E']# 经度信息,用于测试,请替换为自己的信息
            latitudeLst = []
            longitudeLst = []
            gpsMessage = []

            for lat in latitudeObj:
                latitude = lat.split('N')[0]
                latitude = latitude.split('.')[0] + latitude.split('.')[1]
                latitude = float(latitude[0:2]) + float(latitude[2:4] + '.' + latitude[4:]) / 60.0
                latitudeLst.append(latitude)

            for long in longitudeObj:
                longitude = long.split('E')[0]
                longitude = longitude.split('.')[0] + longitude.split('.')[1]
                longitude = float(longitude[0:3]) + float(longitude[3:5] + '.' + longitude[5:]) / 60.0
                longitudeLst.append(longitude)
            for i in range(len(latitudeObj)):
                gpsMessage.append(self.wgs84_to_gcj02(longitudeLst[i], latitudeLst[i]))

            return gpsMessage
        except:
            print('error')


# 测试代码
obj = GetGpsMessage()
s = obj.getGpsMessage()
print(s)

运行代码后,可看到换算后的经纬度数值。换算方法自行网上了解,比较复杂,这里不予讲解。

3.将GCJ-02坐标中的数值换算成BD-09坐标下的数值

baidu_lat = 30.567924 #GCJ-02坐标中的纬度数值,测试数据,请填入自己的纬度信息
baidu_long = 103.970845833333333 #GCJ-02坐标中的经度数值,测试数据,请填入自己的经度信息
Pi = 3.14159265358979324 * 3000.0 / 180.0

x = baidu_long
y = baidu_lat
z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * Pi)
theta = math.atan2(y, x) + 0.000003 * math.cos(x * Pi)
long = z * math.cos(theta) + 0.0065
lat = z * math.sin(theta) + 0.006
print(long, lat)

运行代码即可获得BD-09坐标下的数值。

国内的互联网公司,都不会使用WGS-84坐标,因为这不符合国家政策。所以大家都会使用GCJ-02坐标系。

目前使用GCJ-02坐标系的地图商:

  • 腾讯搜搜地图
  • 搜狐搜狗地图
  • 阿里云地图
  • 高德MapABC地图
  • 灵图51ditu地图

目前使用BD-09坐标系的地图商:

  • 百度Baidu地图

下篇文章是关于将换算而来的经纬度信息展示在web前端上展示

百度地图开放平台 | 百度地图API SDK | 地图开发 (baidu.com)icon-default.png?t=N3I4https://lbsyun.baidu.com/

腾讯位置服务 - 立足生态,连接未来 (qq.com)icon-default.png?t=N3I4https://lbs.qq.com/

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值