█ 【无人机学习之DroidPlanner】RTK数据解析


█ 系列文章目录

提示:这里是收集了无人机的相关文章


█ 文章目录


█ 读前说明

  • 本文通过学习别人写demo,学习一些课件,参考一些博客,学习相关知识,如有涉及侵权请告知
  • 本文可能只简单罗列了一些相关的代码实现过程,复制了一些大神的高论,如内容有误请自行辨别
  • 涉及到的逻辑以及说明可能只做了简单的介绍,主要当做笔记,了解过程而已,如有不同看法,欢迎下方评论
  • 本文源码:https://github.com/DroidPlanner/Tower


█ 关于几个知识点

  • 1.RTK设备 :
    一种蓝牙设备,高精度测试GPS位置,里面一个核心部件就需要500多元,使用NMEA数据格式

  • 2.NMEA数据格式:(蓝牙发送的数据)

室内$GNGGA,0,00,127.00,*62
室外$GNGGA,024836.000,2455.832365,N,11838.669887,E,1,12,1.64,55.428,M,0,M,*6B \r\n
  • 3.GNGGA数据帧结构 :(参考百度百科)
$GP GGA<1><2><3><4><5><6><7><8><9>M<10>M<11><12>*CRC< CR>< LF>
起始符UTC时间纬度纬度半球经度经度半球GPS状态卫星数量HD OP海拔单位米水准面单位米差分时间差分标号结束符校验和回车符换行符
帧结构名称值备注
$帧命令起始位$开始标记
aaccc地址域GNGGA全球定位信息
<1>UTC时间024836.000格式为hhmmss.sss
<2>纬度2455.832365格式为ddmm.mmmm(第一位是零也将传送)
<3>纬度半球NN或S(北纬或南纬)
<4>经度11838.669887格式为dddmm.mmmm(第一位零也将传送)
<5>经度半球EE或W(东经或西经)
<6>GPS状态10初始化, 1单点定位, 2码差分, 3无效PPS, 4固定解, 5浮点解, 6正在估算 7,人工输入固定值, 8模拟模式, 9WAAS差分
<7>卫星数量12从00到12(第一个零也将传送)
<8>HDOP-水平精度因子1.640.5到99.9,一般认为HDOP越小,质量越好
<9>海拔高度55.428-9999.9到9999.9米
M单位米M单位米
<10>大地水准面高度异常差值0-9999.9到9999.9米
M单位米M单位米
<11>差分时间从最近一次接收到差分信号开始的秒数,如不是差分定位则为空
<12>差分参考基站标号0000 到 1023,首位 0 也将传送,非差分定位,此项为空
*校验和前缀*校验和前缀,语句结束标志符
hh校验和6B$与*之间所有字符 ASCII 码的校验和(各字节做异或运算,得到校验和后,再转换 16 进制格式的 ASCII 字符)
< CR>回车符\r结束标记
< LF>换行符\n结束标记
  • 4.经度纬度
坐标格式说明
纬度ddmm.mmmm第一位是零也将传送,正数表示北纬N,负数表示南纬S
经度dddmm.mmmm第一位是零也将传送,正数表示东经E,负数表示西经W

█ 收到的数据

  • 1.GPS锁星数太少(如室内):
    。。。。。。
    $GNGGA,,,,,,0,00,127.00,,,,,,*62
    $GNGSA,A,1,,,,,,,,,,,,,127.00,127.00,127.00,1*07
    $GNGSA,A,1,,,,,,,,,,,,,127.00,127.00,127.00,2*04
    $GNGSA,A,1,,,,,,,,,,,,,127.00,127.00,127.00,4*02
    $GNGLL,,,,,,V,N*7A
    $GNRMC,,V,,,,,,,,,E,N,V*72
    $GNVTG,,,,,,,,N*02
    。。。。。。    
    $GNGGA,,,,,,0,00,127.00,,,,,,*62
    $GNGSA,A,1,,,,,,,,,,,,,127.00,127.00,127.00,1*07
    $GNGSA,A,1,,,,,,,,,,,,,127.00,127.00,127.00,2*04
    $GNGSA,A,1,,,,,,,,,,,,,127.00,127.00,127.00,4*02
    $GNGLL,,,,,,V,N*7A
    $GNRMC,,V,,,,,,,,,E,N,V*72
    $GNVTG,,,,,,,,N*02
    
    。。。。。。
  • 2.正常情况(如室外,蓝天白云):
    。。。。。。
    $GNGGA,014354.000,2455.831086,N,11838.665527,E,1,06,2.29,22.412,M,0,M,,*67 
    $GNGSA,A,3,07,08,27,31,,,,,,,,,2.84,2.29,1.68,1*01
    $GNGSA,A,3,,,,,,,,,,,,,2.84,2.29,1.68,2*0A
    $GNGSA,A,3,01,07,,,,,,,,,,,2.84,2.29,1.68,4*0A
    $GPGSV,1,1,04,07,23,320,30,08,73,260,42,27,62,023,38,31,11,129,31,1*6B
    $GPGSV,1,1,04,07,23,320,,08,73,260,36,27,62,023,,31,11,129,,6*65
    $GLGSV,1,1,01,73,,,36,1*78
    $GBGSV,1,1,02,01,49,130,38,07,60,350,36,1*73
    $GBGSV,1,1,02,01,49,130,,07,60,350,34,3*78
    $GNGLL,2455.831086,N,11838.665527,E,014354.000,A,A*44
    $GNRMC,014355.000,A,2455.830913,N,11838.665636,E,0.518,260.47,100521,,E,A,V*76
    $GNVTG,260.47,T,,M,0.518,N,0.960,K,A*27
    。。。。。。
    $GNGGA,014357.000,2455.830590,N,11838.665853,E,1,06,2.17,22.237,M,0,M,,*65
    $GNGSA,A,3,07,08,27,31,,,,,,,,,2.74,2.17,1.67,1*0C
    $GNGSA,A,3,,,,,,,,,,,,,2.74,2.17,1.67,2*07
    $GNGSA,A,3,01,07,,,,,,,,,,,2.74,2.17,1.67,4*07
    $GPGSV,1,1,04,07,23,320,30,08,73,260,41,27,62,023,38,31,11,129,32,1*6B
    $GPGSV,1,1,04,07,23,320,,08,73,260,36,27,62,023,,31,11,129,,6*65
    $GLGSV,1,1,01,73,,,36,1*78
    $GBGSV,1,1,02,01,49,130,37,07,60,350,35,1*7F
    $GBGSV,1,1,02,01,49,130,,07,60,350,34,3*78
    $GNGLL,2455.830590,N,11838.665853,E,014357.000,A,A*4A
    $GNRMC,014358.000,A,2455.829940,N,11838.667064,E,0.095,,100521,,E,A,V*6F
    $GNVTG,,T,,M,0.095,N,0.176,K,A*31
    。。。。。。

█ 数据解析

  • 1.DroidPlanner中LatLong的数据格式为度.度 格式:ddd.dddd,
  • 2.RTK数据的数据格式为度分.分格式:dddmm.mmmm
  • 3.度.度 转 度分.分:(看下GPS2NMEAUtils.java)
    提示:假设小数点为4位,写的不是很标准,可以看懂意思就可以
经度:ddd.dddd(度度)dddmm.mmmm = ddd x 100 +dddd x 60 x 100
纬度:dd.dddd(度度)ddmm.mmmm = dd x 100 +dddd x 60 x 100
 public static String gps2GPGGA(msg_gps_raw_int gpsState){
        StringBuilder sb = new StringBuilder();
        double lat = gpsState.lat / 1E7;
        double lon = gpsState.lon / 1E7;
        sb.append("GNGGA").append(",").append(gpsState.time_usec)
                .append(",").append(onenetToLatitude(lat) ).append(",");
        if(gpsState.lat > 0){
            sb.append("N");
        }else {
            sb.append("S");
        }
        sb.append(",").append(onenetToLongitude(lon)).append(",");
        。。。。。。
        return sb.toString();
    }
    public  static String onenetToLongitude(double lon) {
        int dd_int =  (int)lon;
        long mm_int = (long) ((lon - dd_int ) * 100000 * 60);

        String lon_Onenet = dd_int + "." +  mm_int;
        BigDecimal bigDecimal=new BigDecimal(Double.parseDouble(lon_Onenet) * 100);
        if(bigDecimal.doubleValue() == 0){
            return "0";
        }
        DecimalFormat df=new DecimalFormat("###.0000");
        df.setRoundingMode(RoundingMode.DOWN);
        return  df.format(bigDecimal);
    }

在这里插入图片描述

  • 4.msg_gps_raw_int
    因为,lat lon的单位是 degE7,因此转成WGS84需要 ÷ 1E7
    在这里插入图片描述
    提示:
    1、WGS84:World Geodetic System 1984,是为GPS全球定位系统使用而建立的坐标系统。GPS数据一般是WGS84坐标,此外还有WGS60、WGS66、WGS72、WGS84等世界大地坐标系。
    2、EGM96模型是美国bai推出的一种适用于全球范围,并综合利用现有全球大量重力数据所计算出来的高精度大地水准面模型。利用大地水准面模型求取待定点的高程异常并最终获得正常高,此外还有EGM2008大地水准面模型

  • 5.度分.分 转 度.度:
    提示:假设小数点为4位,写的不是很标准,可以看懂意思就可以

经度:dddmm.mmmm(度分)ddd.ddddd = ddd ÷ 100 + mm.mmmm ÷ 60
纬度:ddmm.mmmm(度分)dd.dddd = dd ÷ 100 + mm.mmmm ÷ 60
    public  static Double onenetToLatitude(double lon) {
        int dd = (int) (lon / 100);
        double mm = (lon - dd * 100);
        return (dd + mm / 60) ;
    }

█ 测试

  • 1.正常
dddmm.mmmm:latitude = 2455.832365,longitude = 11838.669887
ddd.dddd:latitude = 24.93053941666667,longitude = 118.64449811666667
还原dddmm.mmmm:lat = 2455.8323,lon = 11838.6698

在这里插入图片描述

在这里插入图片描述

  • 2.正常
> Task :testJavalib:MyClass.main()
dddmm.mmmm:latitude = 55.832365,longitude = 38.669887
ddd.dddd:latitude = 0.9305394166666667,longitude = 0.6444981166666667
还原dddmm.mmmm:lat = 55.8323,lon = 38.6698

在这里插入图片描述

在这里插入图片描述

  • 3.异常

GPS2NMEAUtils.java → onenetToLatitude() 的计算方法是存在问题的

> Task :testJavalib:MyClass.main()
dddmm.mmmm:latitude = 5.832365,longitude = 8.669887
ddd.dddd:latitude = 0.09720608333333333,longitude = 0.14449811666666665
还原dddmm.mmmm:lat = 58.3235,lon = 86.6987

在这里插入图片描述
在这里插入图片描述

█ 测试2

  • 1.接收的数据 可能存在 不完整,如:
完整包$GNGGA,023302.000,2455.828215,N,11839.669595,E,2,18,0.87,29.787,M,0,M,2,0000*59
室内$GNGGA,0,00,127.00,*62
头尾不完整包$GNGGA,025629.000,2455.830431,N,11839.667971,E,2
中间不完整包
中间少了‘,’
$GNGGA,023303.000,2455.828070,N,11839.669644,E,2,180.87,30.384,M,0

没有注意这些,可能在数据转换时就会遇到异常:

蓝牙断开java.io.IOException: bt socket closed, read return: -1
中间不完整包
数据转换异常
java.lang.NumberFormatException: For input string: “180.87”

█ 相关资料

提示:这里是参考的相关文章

  1. GPGGA_百度百科
  2. 2019-06-04 NMEA-0183 协议简介_Zzt的博客-CSDN博客_nmea0183协议
  3. 2017-05-25 Android 关于定位中的那点事(GPS,GPGGA,NMEA-0183,RTCM)_这片海的博客-CSDN博客
  4. 2018-07-11 这应该是关于GPS定位写得最详实清晰的文章之一
  5. 2020-06-26 北斗为什么室内搜索卫星比GPS少? - 知乎

█ 免责声明

博主分享的所有文章内容,部分参考网上教程,引用大神高论,部分亲身实践,记下笔录,内容可能存在诸多不实之处,还望海涵,本内容仅供学习研究使用,切勿用于商业用途,若您是部分内容的作者,不喜欢此内容被分享出来,可联系博主说明相关情况通知删除,感谢您的理解与支持!

提示:转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/116533679

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐