STM32开发 -- 坐标转换

发布者:浊酒最新更新时间:2019-09-02 来源: eefocus关键字:STM32  坐标转换  坐标系 手机看文章 扫描二维码
随时随地手机看文章

WGS84坐标系 地球坐标系,国际通用坐标系

GCJ02坐标系 火星坐标系,WGS84坐标系加密后的坐标系;Google国内地图、高德、QQ地图

BD09坐标系 百度坐标系,GCJ02坐标系加密后的坐标系


BUT,这三者之间是之间该如何转换呢?

比如我获得GPS原始数据 2312.49700,11314.65422,三者之间该怎么转换呢?

再有打开:GPS经纬度坐标拾取

在这里插入图片描述

我输入的是什么经纬度?

硬件/谷歌地球卫星 谷歌地图 百度地图

腾讯地图/高德地图 图吧地图


这里是有以选择哪种坐标系输入经纬度的。


接下来就简单的来看一下咯。


一、各坐标系简介与转换

参看:各坐标系简介与转换,包括WGS84(地球坐标系)、GCJ02(火星坐标系)和BD09(百度坐标系)


从GPS和北斗卫星定位得到的定位数据采用的都是WGS84坐标系,即地球坐标系,但是国内不管是高德地图、百度地图采用的并不是WGS84坐标系,所以需要经过转换后才能使用,前端用百度API提供的方法转换速度较慢。


好像还真是。。。这样。

我之前讲的GPS经纬度的表示方法及换算:

在这里插入图片描述

2312.49700,11314.65422

ddmm.mmmmm,dddmm.mmmmm


23°12′

0.49700′ * 60 = 29.82″


113°14′

0.65422′ * 60 = 39.25″

即:北纬N23°12′29.82″ 东经E113°14′39.25″


也可以这么算:

2312.49700,11314.65422

ddmm.mmmmm,dddmm.mmmmm


23°

12.49700′ / 60 = 0.2082833333°


113°

14.65422′ / 60 = 0.2442370000°

即:23.2082833333,113.2442370000


因此转换为应该为:

23.2082833333,113.2442370000


最后转换出来的是WGS84坐标系的。所以我用 GPS经纬度坐标拾取 选择的是硬件/谷歌地球卫星的经纬度。


BUT,实际开发用的高德地图是GCJ02坐标系。

换算方法都不一样了呢。。。


二、各坐标系简介

●WGS84坐标系 即地球坐标系,国际上通用的坐标系。 设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系。谷歌地图采用的是WGS84地理坐标系(中国范围除外,谷歌中国地图采用的是GCJ02地理坐标系。)


●GCJ02坐标系 即火星坐标系,WGS84坐标系经加密后的坐标系。 出于国家安全考虑,国内所有导航电子地图必须使用国家测绘局制定的加密坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标。


●BD09坐标系 即百度坐标系,GCJ02坐标系经加密后的坐标系。搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。


●各主流地图API采用的坐标系 高德MapABC地图API 火星坐标 腾讯搜搜地图API 火星坐标 阿里云地图API 火星坐标 灵图51ditu地图API 火星坐标


百度地图API 百度坐标 搜狐搜狗地图API 搜狗坐标 图吧MapBar地图API 图吧坐标

在这里插入图片描述

一张图就搞清楚了!!!


●这里介绍几个常用的在线坐标工具 高德开放平台 百度拾取坐标系统 在线坐标转换工具


这里各个坐标系介绍,没啥可说的。

这个高德开放平台还是才发现的,这个不错,界面整洁地图高清。哈哈哈哈哈嗝。


三、各坐标系转换

各坐标系转换,网上相关代码有很多。

参看:WGS84、GCJ02、BD09地图坐标系间的坐标转换及坐标距离计算 

参看:火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法


/**

 * 各地图API坐标系统比较与转换;

 * WGS84坐标系:即地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系,

 * 谷歌地图采用的是WGS84地理坐标系(中国范围除外);

 * GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。

 * 谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系; BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系;

 * 搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。 chenhua

 */

public class PositionUtil {

public static final String BAIDU_LBS_TYPE = "bd09ll";

public static double pi = 3.1415926535897932384626;

public static double a = 6378245.0;

public static double ee = 0.00669342162296594323;


public static void main(String[] args) {

//System.out.println(gps84_To_Gcj02(39.9000000d,116.4000000d).toString());

// 北斗芯片获取的经纬度为WGS84地理坐标 31.426896,119.496145  

        Gps gps = new Gps(31.426896, 119.496145);  

        System.out.println("gps :" + gps);  

        Gps gcj = gps84_To_Gcj02(gps.getWgLat(), gps.getWgLon());  

        System.out.println("gcj :" + gcj);  

        Gps star = gcj02_To_Gps84(gcj.getWgLat(), gcj.getWgLon());  

        System.out.println("star:" + star);  

        Gps bd = gcj02_To_Bd09(gcj.getWgLat(), gcj.getWgLon());  

        System.out.println("bd  :" + bd);  

        Gps gcj2 = bd09_To_Gcj02(bd.getWgLat(), bd.getWgLon());  

        System.out.println("gcj :" + gcj2);  

}

/**

* 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System

* @param lat

* @param lon

* @return

*/

public static Gps gps84_To_Gcj02(double lat, double lon) {

if (outOfChina(lat, lon)) {

return null;

}

double dLat = transformLat(lon - 105.0, lat - 35.0);

double dLon = transformLon(lon - 105.0, lat - 35.0);

double radLat = lat / 180.0 * pi;

double magic = Math.sin(radLat);

magic = 1 - ee * magic * magic;

double sqrtMagic = Math.sqrt(magic);

dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);

dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);

double mgLat = lat + dLat;

double mgLon = lon + dLon;

return new Gps(mgLat, mgLon);

}


/**

* 火星坐标系 (GCJ-02) to 84 

* @param lon 

* @param lat 

* @return

*/

public static Gps gcj02_To_Gps84(double lat, double lon) {

Gps gps = transform(lat, lon);

double lontitude = lon * 2 - gps.getWgLon();

double latitude = lat * 2 - gps.getWgLat();

return new Gps(latitude, lontitude);

}


/**

* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标

* @param gg_lat

* @param gg_lon

*/

public static Gps gcj02_To_Bd09(double gg_lat, double gg_lon) {

double x = gg_lon, y = gg_lat;

double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * pi);

double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * pi);

double bd_lon = z * Math.cos(theta) + 0.0065;

double bd_lat = z * Math.sin(theta) + 0.006;

return new Gps(bd_lat, bd_lon);

}


/**

* * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param

* bd_lat * @param bd_lon * @return

*/

public static Gps bd09_To_Gcj02(double bd_lat, double bd_lon) {

double x = bd_lon - 0.0065, y = bd_lat - 0.006;

double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * pi);

double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * pi);

double gg_lon = z * Math.cos(theta);

double gg_lat = z * Math.sin(theta);

return new Gps(gg_lat, gg_lon);

}


/**

* (BD-09)-->84

* @param bd_lat

* @param bd_lon

* @return

*/

public static Gps bd09_To_Gps84(double bd_lat, double bd_lon) {


Gps gcj02 = PositionUtil.bd09_To_Gcj02(bd_lat, bd_lon);

Gps map84 = PositionUtil.gcj02_To_Gps84(gcj02.getWgLat(),

gcj02.getWgLon());

return map84;


}


public static boolean outOfChina(double lat, double lon) {

if (lon < 72.004 || lon > 137.8347)

return true;

if (lat < 0.8293 || lat > 55.8271)

return true;

return false;

}


public static Gps transform(double lat, double lon) {

if (outOfChina(lat, lon)) {

return new Gps(lat, lon);

}

double dLat = transformLat(lon - 105.0, lat - 35.0);

double dLon = transformLon(lon - 105.0, lat - 35.0);

double radLat = lat / 180.0 * pi;

double magic = Math.sin(radLat);

magic = 1 - ee * magic * magic;

double sqrtMagic = Math.sqrt(magic);

dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);

dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);

double mgLat = lat + dLat;

double mgLon = lon + dLon;

return new Gps(mgLat, mgLon);

}


public static double transformLat(double x, double y) {

double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y

+ 0.2 * Math.sqrt(Math.abs(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 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;

return ret;

}


public static double transformLon(double x, double y) {

double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1

* Math.sqrt(Math.abs(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;

}

private static double rad(double d) {

    return d * Math.PI / 180.0;

}

public static double getDistance(double lat1, double lng1, double lat2, double lng2) {

    double radLat1 = rad(lat1);

    double radLat2 = rad(lat2);

    double a = radLat1 - radLat2;

    double b = rad(lng1) - rad(lng2);

    double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) + 

     Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));

    s = s * 6378.137d;

    s = Math.round(s * 10000) / 10000;

    return s;

}

}

四、总结

各个坐标系转换,总结完了。

但毕竟我获取的GPS原始报文是下面这个样子的:

在这里插入图片描述

关键字:STM32  坐标转换  坐标系 引用地址:STM32开发 -- 坐标转换

上一篇:STM32开发 -- 继电器测试
下一篇:STM32开发 -- 主天线和分集天线

推荐阅读最新更新时间:2024-11-02 05:57

STM32工程上printf()函数的方法实现
针对STM32的串口编程,可以通过USART1向计算机的串口调试助手打印数据,或者接收计算机串口调试助手的数据。 下面,我们可以实现STM32工程上的printf()函数了,方便用于程序开发中调试信息的打印。 方法1:使用MicroLIB库 1.1 KEIL-MDK中的Use MicroLIB选项 在MDK开发环境中, MicroLib是缺省c库的备选库,它可装入少量内存中,与嵌入式应用程序配合使用,且这些应用程序不在操作系统中运行。MicroLib进行了高度优化以使代码变得很小,功能比缺省c库少,不具备某些ISO C特性,部分库函数的运行速度也比较慢,如内存拷贝函数memcpy()。 MicroLib与缺
[单片机]
<font color='red'>STM32</font>工程上printf()函数的方法实现
stm32关于串口输出的几种常用方式
在使用stm32做项目时,我们常常会使用到串口调试,通过串口来输出我们想要看的相关参数值,这样既方便有快捷。 具体方法有哪些呢,我自己整理了一下,这个也是借鉴别人的用法而已。希望大家可以相互讨论学习。 1、使用printf语句通过串口输出我们想要的参数值 具体的用法:使用之前必须包含相应的头文件#include stdio.h int fputc(int ch, FILE *f)//重定向,让printf输出到串口 { USART_SendData(USART1, (uint8_t) ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) ==
[单片机]
<font color='red'>stm32</font>关于串口输出的几种常用方式
STM32之中断函数介绍篇
NVIC驱动有很多的用途,如使能或者失能IRQ(中断请求),或者是使能或失能单独的IRQ通道,或者是改变其优先级。以下介绍相关函数的功能和基本用法。 1.NVIC_DeInit函数的功能是将外设NVIC寄存器重设为默认值。 2.NVIC)PriorityGroupConfig函数的功能是设置优先级分组:先占优先级和从优先级,且有一个输入参数是优先级分组的长度 例:定义先占优先级1,从优先级3. NVIC_PriorityGroupConfig(NVICPriorityGroup_1); 3.NVIC_Init函数的功能是根据NVIC_InitStruct里面指定的参数初始化外设NVIC寄存器,其中NVIC_In
[单片机]
STM32+OLED巧妙显示汉字英文
目标:实现OLED_Print函数,可以在OLED屏幕上显示中英文和符号混合的任意字符串 汉字编码原理 ASCII码显示的原理这里不再说明,一般的OLED例程都有使用方法。下面说一下中文编码的原理。 在keil的环境使用的是GBK或者GB2312的编码方式,GBK编码汉字使用两个字节: 第一个字节为区码,第二个好像叫段码,区码是大于127的,段码不一定。 具体编码方式可以查阅资料: 下面编写一个简单的程序进行验证: int main(void) { char *s = 哈h ; int i; delay_init(); //延时函数初始化 NVIC_Configurat
[单片机]
STM32+OLED巧妙显示汉字英文
STM32 启动代码分析详解
1、堆栈存储器 堆栈存储区是在片上存储器中的SRAM(或RAM)中由用户自行开辟的一片数据存储区域,并且堆栈区的大小可根据用户的需要任意指定(只要不超过SRAM或RAM的大小),而堆栈区的位置由编译器指定分配。 Cortex-M3/M4处理器的堆栈指针SP是“满递减,空递增”,呈现向下逆生长的特点。 堆栈区数据的存储特点是“先进后出,后进先出”。 这种特点是由堆栈指针的移动方式决定的,先入栈的数据对应的指针值比较大,后入栈的数据对应的指针值比较小,而出栈时堆栈指针的值是递增的,所以指针值大的数据当然后出栈。 堆栈的作用: 局部变量的存储、函数调用时函数或子程序间数据的传递(形参的保存,其实函数调用一旦结束被
[单片机]
<font color='red'>STM32</font> 启动代码分析详解
STM32学习笔记七——LED闪烁的三种控制方法
法一:软件延时(不精准) void delay_nms(u16 time) { u16 i=0; while(time--) { i=12000; while(i--); } } 方法二: main.c #include stm32f10x.h __IO uint32_t TimingDelay; /****************** *函数名称: LED_GPIO_Config() *功 能:实现LED等GPIO的配置 *参 数:无 *返 回 值:无 *作 者:Katter ******************/ void LED_GPIO_Config(void) {
[单片机]
基于STM32的PWM呼吸灯系统设计
一、简述 记--使用定时器4输出PWM来实现呼吸灯效果。 在人眼辨识能力范围内,调节LED亮的时间,达到LED灯的亮度不同。例:给低电平LED就亮,如果一个脉冲中全是低电平那么LED最亮,如果一个脉冲一半是高电平,一半是低电平,那么LED就显得有点暗,这样调整脉冲中的高低电平的比例就可以达到LED的亮度调节。 二、效果 LED1逐渐由暗变亮,接着由亮变暗。 三、工程结构 四、源文件 #include stm32f4xx.h #include led.h #include pwm.h //粗延时 void delay_ms(int ms) { int i,j; for(i=0; i m
[单片机]
基于<font color='red'>STM32</font>的PWM呼吸灯系统设计
STM32串口操作相关事项
放了一段时间,对stm32似乎有点陌生,总结一下! (基于3.0固件库,芯片stm32f103rbt6) 1、配置串口的管脚和时钟 由于串口1、2是在GPIOA上: 所以要是能串口GPIOA、AFIO和1或者2的串口时钟,代码如下: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1 , ENABLE); 2、对串口的具体物理管脚进行相应的配置: /* A9 USART1_Tx */ GPIO_InitStructure.GPIO_Pin = GPIO_Pi
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved