GPS定位解决偏差
目录
GPS定位解决偏差
开篇
大家都知道啊,小黑是靠Unity吃饭的,所以觉得Unity就是万能的,小黑需要什么他就会提供什么,事实证明,Unity确实是很强大,但是他还没有强大到可以知道小黑心里想什么。所以就遇到问了呗。
事情是这样的,小黑从前段时间开始,加入了一个项目组,开始是帮着解决一些原生交互啊,或者是另外一些简单的东西吧。但随着时间的推进,小黑稀里糊涂的就成了该项目组成员,彻底进入开发了状态了!!!!开发就开发吧,有一个GPS定位功能之前是另一个项目组同事负责,他告诉我们说是Unity的GPS有问题,和实际位置有6公里的偏差,这这这小黑能忍?好歹一年前也是做过GPS相关功能的,于是小黑拿着1年前的知识和他开始了Battle!!!并且叫嚣着:(下方),现在想来,真的想打死我自己。太丢人了
出自小黑的嘴:我之前做过Demo,GPS是绝对不可能有这么大偏差的,最多800米的偏差,并且还是看什么地图的坐标拾取器!!高德、腾讯、谷歌很厉害,偏差在400米左右,百度最垃圾,偏差在800米左右!!
实践
1、解决思路以及步骤
那废话也说了好多了, 就开始学习如何解决吧。
- 首先:我们要知道什么是GPS。
GPS从入门到放弃(一) --- GPS基础原理
GPS从入门到放弃(二) --- GPS时间
GPS从入门到放弃(三) --- GPS坐标系 主要看这个★★★★★- 第二:知道坐标系后,我们要弄明白为什么会有偏差。
关于GPS坐标系和地图定位偏差
借用文章中的话:
1):获取GPS位置后,为什么在地图上定位不准?
答 :中国地图采用的坐标系和GPS坐标不是同一个坐标系,所以采用GPS坐标在地图上定位不准。
2):国外GPS位置和国内GPS位置有差别吗?
答 :GPS是美国的导航系统,全球通用,手机内置的芯片都是GPS芯片,没有差别。不同的地方是地图有着不同的GPS坐标系。- 最后:我们明白偏差原因后,就需要解决,那代码在哪呢,正下方咯。
地图坐标系相互转换(WGS-84、GCJ-02、BD-09)
2、实践出真理!
正如第三步骤的文章中所说:我们开发人员一般会用到三种坐标系。
- WGS-84原始坐标系
一般用国际GPS纪录仪记录下来的经纬度,通过GPS定位拿到的原始经纬度,Google和高德地图定位的的经纬度(国外)都是基于WGS-84坐标系的。但是在国内是不允许直接用WGS84坐标系标注的,必须经过加密后才能使用。GCJ-02坐标系,又名"火星坐标系"
是我国(中国)国测局独创的坐标体系,由WGS-84加密而成,在国内,必须至少使用GCJ-02坐标系,或者使用在GCJ-02加密后再进行加密的坐标系,如百度坐标系。高德和Google在国内都是使用GCJ-02坐标系,可以说,GCJ-02是国内最广泛使用的坐标系。BD-09,又名"百度坐标系"
百度坐标系是在GCJ-02坐标系的基础上再次加密偏移后形成的坐标系,只适用于百度地图。(目前百度API提供了从其它坐标系转换为百度坐标系的API,但却没有从百度坐标系转为其他坐标系的API)。
小黑在不同地图的坐标拾取器上边反复测试后,得到以下结果:
1、Unity通过API (Input.location) 获取到的正是WGS-84原始坐标系。
2、高德、腾讯、谷歌(中国) 用的都是GCJ - 02坐标系。
3、百度自然用的是自家坐标系咯(百度坐标系)。
3、上坐标系之间的代码。
using System;
public class GPSUtil
{
/// <summary>
/// Π
/// 圆周率
/// </summary>
private const double PI = 3.14159265358979324;
private const double X_PI = 3.14159265358979324 * 3000.0 / 180.0;
private const double A = 6378245.0;
private const double EE = 0.00669342162296594323;
private const double LON_BOUNDARY_MIN = 72.004;
private const double LAT_BOUNDARY_MIN = 0.8293;
private const double LON_BOUNDARY_MAX = 137.8347;
private const double LAT_BOUNDARY_MAX = 55.8271;
/// <summary>
/// 是否中国境内坐标
/// </summary>
/// <param name="gpsLat"></param>
/// <param name="gpsLng"></param>
/// <returns></returns>
private static bool OutOfChina(double gpsLat, double gpsLng)
{
if (gpsLng < LON_BOUNDARY_MIN || gpsLng > LON_BOUNDARY_MAX)
{
return true;
}
if (gpsLat < LAT_BOUNDARY_MIN || gpsLat > LAT_BOUNDARY_MAX)
{
return true;
}
return false;
}
#region WGS坐标系与GCJ02坐标系互转
/// <summary>
/// WGS84坐标系转GCJ02坐标系
/// </summary>
/// <param name="wgsLat">WGS坐标,纬度</param>
/// <param name="wgsLng">WGS坐标,经度</param>
/// <param name="gcjLat">GCJ02坐标,纬度</param>
/// <param name="gcjLng">GCJ02坐标,经度</param>
public static void WGS84_to_GCJ02(double wgsLat, double wgsLng, out double gcjLat, out double gcjLng)
{
if (OutOfChina(wgsLat, wgsLng))
{
gcjLat = wgsLat;
gcjLng = wgsLng;
}
else
{
double dLat = TransformLat(wgsLng - 105.0, wgsLat - 35.0);
double dLon = TransformLon(wgsLng - 105.0, wgsLat - 35.0);
double radLat = wgsLat / 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);
gcjLat = wgsLat + dLat;
gcjLng = wgsLng + dLon;
}
}
public static void GCJ02_to_WGS84(double gcjLat, double gcjLng, out double wgsLat, out double wgsLng)
{
WGS84_to_GCJ02(gcjLat, gcjLng, out wgsLat, out wgsLng);
wgsLng = gcjLng * 2 - wgsLng;
wgsLat = gcjLat * 2 - wgsLat;
}
private 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;
}
private 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;
}
#endregion
#region 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的互转
public static void GCJ02_to_Bd09(double gcjLat, double gcjLng, out double bdLat, out double bdLng)
{
double z = Math.Sqrt(gcjLng * gcjLng + gcjLat * gcjLat) + 0.00002 * Math.Sin(gcjLat * PI);
double theta = Math.Atan2(gcjLat, gcjLng) + 0.000003 * Math.Cos(gcjLng * PI);
bdLng = z * Math.Cos(theta) + 0.0065;
bdLat = z * Math.Sin(theta) + 0.006;
}
public static void BD09_to_GCJ02(double bdLat, double bdLng, out double gcjLat, out double gcjLng)
{
double x = bdLng - 0.0065, y = bdLat - 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);
gcjLng = z * Math.Cos(theta);
gcjLat = z * Math.Sin(theta);
}
#endregion
}
至此,圆满结束。
好了,知识讲了,参考链接也上了,代码更是放出来了,这次相信大家和小黑一样,会GPS的使用了吧!
希望大家:点赞,留言,关注咯~
唠家常
- 小黑的今日分享结束啦,小伙伴们你们get到了么,你们有没有更好的办法呢,可以评论区留言分享,也可以加小黑的QQ:841298494,大家一起进步。
今日推荐都在文章中了
- 客官,看完get之后记得点赞哟!
- 小伙伴你还想要别的知识?好的呀,分享给你们
- 小黑的杂货铺,想要什么都有,客官不进来喝杯茶么?
GPS定位解决偏差的更多相关文章
- [置顶]
xamarin android使用gps定位获取经纬度
看了文章你会得出以下几个结论 1.android定位主要有四种方式GPS,Network(wifi定位.基站定位),AGPS定位 2.绝大部分android国产手机使用network进行定位是没有作用 ...
- 【转】GPS定位原理
一.距离测定原理 1.伪距测量 伪距测量是利用全球卫星定位系统进行导航定位的最基本的方法,其基本原理是:在某一瞬间利用GPS接收机同时测定至少四颗卫星的伪距,根据已知的卫星位置 和伪距观测值,采用距离 ...
- Uber是如何重新思考GPS定位的(尤其是在城市峡谷中)
郑昀(公众号:老兵笔记) 20180424 2018年4月19日,Uber 公布了 GPS 优化算法,https://eng.uber.com/rethinking-gps/,针对GPS定位在城市环境 ...
- Flex AIR应用GPS定位功能(Android和IOS)
说明: 使用AIR进行GPS定位功能实现时,会经常判断GPS是否打开.一般的官方或者书上的介绍的方法,测试后,只能对Android系统进行判断,而对ios系统则无法进行判断. 经过研究测试,终于解决实 ...
- GPS定位 测试
public class MainActivity extends Activity { private final String TAG = "BX"; private Loca ...
- Android中GPS定位的简单应用
在Android中通过GPS获得当前位置,首先要获得一个LocationManager实例,通过该实例的getLastKnownLocation()方法获得第一个的位置,该方法的说明如下: void ...
- GPS定位为什么要转换处理?高德地图和百度地图坐标处理有什么不一样?
GPS定位为什么要转换处理?高德地图和百度地图坐标处理有什么不一样? 先了解一下 高德地图 采用: GCJ-02 (不可逆) 百度百科: http://baike.baidu.com/link?url ...
- GPS定位原理
多分钟吧(有人认为美国对其本土覆盖的GPS信号实行不同码率因此纯GPS定位也会很快,谁有美国朋友不妨让他拔卡试试)!因为美版机型其GPS模块的数据处理软件部分与欧版机型是不同的,欧版机型的数据处理软件 ...
- GPS(2)关于位置的3个示例,实时获取GPS定位数据,求两个经纬点距离,邻近某个区域圆时警告
实时获取GPS定位数据 import android.app.Activity; import android.content.Context; import android.location.Loc ...
随机推荐
- Golang 和 Python 随机生成N位字符串
Golang: func RandomString(n int) string { var letters = []byte("ABCDEFGHIGKLMNOPQRSTUVWXYZabcde ...
- Python基础部分:10、数据类型的内置方法和字符编码
目录 一.数据类型内置方法 1.字典dict内置方法 1.1.类型转换 2.字典必须要掌握的方法 2.1.取值方式 2.2.修改内部数据值 2.3.删除数据 2.4.统计字典中键值对个数 2.5.字典 ...
- day09-Tomcat01
Tomcat01 1.WEB开发介绍 WEB,在英文中WEB表示网/网络资源,它用于表示WEB服务器(主机)供浏览器访问的资源 WEB服务器(主机)上供外界访问的Web资源为: 静态web资源(如ht ...
- Day14 note1
package com.oop.demo06;public class Person { public void run(){ System.out.println("run"); ...
- yaml使用
yml使用 安装yaml pip install PyYaml yaml基本规则 # 1.大小写敏感 # 2.使用缩进表示层级关系, # 2.1 不能使用tab进行缩进,只能使用空格 # 2.2 缩进 ...
- Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo
前两篇文章分享了基于 vite3 vue3 的组件库基础工程 vue3-component-library-archetype 和用于快速创建该工程的工具 yyg-cli,但在中大型的企业级项目中,通 ...
- Git创建、diff代码、回退版本、撤回代码,学废了吗
.eye-care { background-color: rgba(199, 237, 204, 1); padding: 10px } .head-box { display: flex } .t ...
- uniapp之uni-starter小程序多端研发框架搭建与项目实践
随着移动互联网的飞速发展,无数移动APP琳琅满目:在移动App的发展的基础上,衍生了小程序.轻应用技术,它随时可用,但又无需安装卸载.小程序是一种不需要下载安装即可使用的应用,它实现了应用" ...
- 【题解】P7860 [COCI2015-2016#2] ARTUR
题面传送门 好题. 主要思路和另一位巨佬差不多,详细讲一下判断的部分. 解决思路: 首先考虑本题与拓扑排序有和关系.可以想到,某些棍子的先后移动顺序是有限制的.比如: 这里红色的必须比蓝色的先移动,因 ...
- C#字典出错“集合已经修改,可能无法执行枚举操作”
出现这个现象的原因是由于线程安全考虑,如果你边对字典循环,又同时移除字典中的某个键值对, 那么将会出现这种错误,解决这种问题的方法是你没次remove某个键值对后需要break结束对字典的循环.