GPS nmealib学习笔记

2023-10-29

0.nmealib简介

    nmealib是一个基于C语言的用于nmea协议的开源库。虽然nmea体积小巧,但是却具备了不少功能。
    分析NMEA语句并把结果保存在合适的C语言结构体中。
    除了解析NMEA语句之外,还可以产生NMEA语句。
    支持多种NMEA语句,包括GPGGA, GPGSA, GPGSV, GPRMC, GPVTG。
    解析算法层次严谨。
    附加地理学相关功能,可支持导航等数据工作。
    更多介绍请参考以下链接

1.目录介绍

    nmealib的目录还是非常清晰的,下面简单介绍一下。
    include\nmealib文件夹中存在nmealib相关的头文件
    src文件夹存放nmealib相关源文件,该文件夹中的内容和include\nmealib文件夹相对应
    samples文件夹存放若干例子,一些简单易懂的例子。

2.示例代码

#include <nmea/nmea.h>
#include <string.h>
#include <stdio.h>

int main()
{
    // 被测试的GPS模块输出数据,仅有GPRMC格式
    char gps_str[] = "$GPRMC,013257.00,A,3129.51829,N,12022.10562,E,0.093,,270813,,,A*7A\r\n";

    nmeaINFO info;                  // nmea协议解析结果结构体
    nmeaPARSER parser;              // nmea协议解析载体

    nmea_zero_INFO(&info);          // 填入默认的解析结果
    nmea_parser_init(&parser);      // 为解析载体分配内存空间

    // 调用函数完成GPS信息解析,最终结果保留于info数组中
    if( (nmea_parse(&parser, gps_str, (int)strlen(gps_str), &info)) > 0 )
    {
        printf("longitude   %.5f\r\n",info.lon);
        printf("latitude    %.5f\r\n",info.lat);
        printf("speed       %.2f\r\n",info.speed);
    }

    nmea_parser_destroy(&parser);   // 释放解析载体的内存空间

    return 0;
}

图1 程序输出结果
利用nmealib解析GPS模块的输出结果大致可以分为三步,第一步定义和初始化GPS信息结构体和解析载体结构体,第二步调用nmea_parse函数完成解析工作,第三步释放解析载体所占用的内存空间。如果仔细查看nmea_parser_init部分的代码,便会发现函数中使用了C标准库的malloc函数,该函数会在RAM中的heap空间开辟一个空间,这就需要使用完该载体之后立刻释放,所以nmea_parser_init和nmea_parser_destroy需要成对出现。
typedef struct _nmeaINFO
{
    int     smask;      /**< Mask specifying types of packages from which data have been obtained */

    nmeaTIME utc;       /**< UTC of position */

    int     sig;        /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
    int     fix;        /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */

    double  PDOP;       /**< Position Dilution Of Precision */
    double  HDOP;       /**< Horizontal Dilution Of Precision */
    double  VDOP;       /**< Vertical Dilution Of Precision */

    double  lat;        /**< Latitude in NDEG - +/-[degree][min].[sec/60] */
    double  lon;        /**< Longitude in NDEG - +/-[degree][min].[sec/60] */
    double  elv;        /**< Antenna altitude above/below mean sea level (geoid) in meters */
    double  speed;      /**< Speed over the ground in kilometers/hour */
    double  direction;  /**< Track angle in degrees True */
    double  declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */

    nmeaSATINFO satinfo; /**< Satellites information */

} nmeaINFO;

nmeaINFO是一个很关键的结构体,该结构体中保存了nmea语句解析的结果。例如lat代表纬度,lon代表精度,speed代表速度。需要注意的是lat和lon的数值格式和百度地图的格式是有区别,而速度的单位为KM/H,相对于“节”这个单位,公里每小时要好理解的多。
    GPS模块可以输出的内容很多,但是最基本的信息可通过GPRMC获得。GPRMC的具体格式如下内容所示:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
<1> UTC时间,hhmmss.sss(时分秒.毫秒)格式
<2> 定位状态,A=有效定位,V=无效定位
<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
<4> 纬度半球N(北半球)或S(南半球)
<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
<6> 经度半球E(东经)或W(西经)
<7> 地面速率(000.0~999.9节,前面的0也将被传输)
<8> 地面航向(000.0~359.9度,以正北为参考基准,前面的0也将被传输)
<9> UTC日期,ddmmyy(日月年)格式
<10> 磁偏角(000.0~180.0度,前面的0也将被传输)
<11> 磁偏角方向,E(东)或W(西)
<12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
在不同的情况下测试GPS模块,可以获得以下三种不同形式的输出内容:
1)    $GPRMC,013257.00,A,3129.51829,N,12022.10562,E,0.093,,270813,,,A*7A\r\n
2)    $GPRMC,022649.00,V,,,,,,,020913,,,N*7F\r\n
3)    $GPRMC,,V,,,,,,,,,,N*53\r\n
【第一种】GPS定位成功,输出正确的GPS位置信息和对地速度信息。
【第二种】GPS定位异常,只有UTC时间信息,其中V代表定位错误。
【第三种】GPS定位异常,甚至没有UTC时间信息,其中V代表定位错误。
通过测试,nmealib处理第一种情况没有任何问题,但是连续处理第二种和第三种情况会产生问题,产生问题的主要原因是动态开辟的空间没有被释放。解决该问题需要修改nmealib的源代码。 如果不想修改nmealib源代码,可以在串口接收GPS输出内容时直接过滤带有V的字符串,这种方法简单有效,同样可以获得准确的GPS坐标信息。

3.若干注意点

3.1 重置解析载体缓冲区

    由于nmealib虽然使用C语言,但是相关测试环境均基于PC环境,所以在嵌入式环境下需要对相关参数(宏定义)进行修改。例如context.h文件中,定义了待处理的nmea缓冲区的大小,相关宏定义如下
#define NMEA_DEF_PARSEBUFF  (1024)
#define NMEA_MIN_PARSEBUFF  (256)
   示例代码的分析中提到,解析载体parser通过动态内存分配的方法开辟空间,该空间位于RAM空间中的heap部分,如果heap部分设置的太小,将会导致MCU进入不可预知的状态或者直接掉入断言中。
在编译器设置中,option->linker,cstack和heap的大小设置如下图所示,此时heap的大小仅有512个字节,而解析载体却需要1024个字节,那么分配内存时势必会产生问题,而工程的编译却不会有任何问题。
图2 不合适的HEAP大小设置
    if(0 == (parser->buffer = malloc(buff_size)))
        nmea_error("Insufficient memory!");        //  此时会发生内存分配错误
    else
    {
        parser->buff_size = buff_size;
        resv = 1;
    }

在这种情况下可以适当减少缓冲区的大小,例如修改如下:
#define NMEA_DEF_PARSEBUFF  (256)
#define NMEA_MIN_PARSEBUFF  (128)
同时可以把HEAP空间大小的调整一下。
图3 合适的HEAP大小设置
当然缓冲区的大小也是视情况而定,若GPS模块仅输出GPRMC语句,那么256字节的缓冲区已经足够了。但是如果GPS模块输出GPGGA, GPGSA, GPGSV, GPRMC, GPVTG等多种数据,那么256字节的缓冲区也有可能不够使用。

3.2 注意nmeaINFO结构体大小

    nmeaINFO结构体左右360字节,若该结构体类型的变量势必会占用较多的CSTACK(全局变量的情况除外),在嵌入式编程中像nmeaINFO类型的变量也可算的上是中型“人物”了。所以在调试的过程中可以打开IDE的stack查看功能(进入debug模式,view->stack),观察当前函数的CSTACK使用情况,尤其要注意CSTACK越界的情况。
图4 查看CSTACK空间占用情况
    从上图可以看出,CSTACK的大小为2048字节(2K),此时被占用752字节,占用率为36%,完全在可以接受的范围内。

4.总结

    nmealib的使用可以缩短GPS的开发周期,这里只是简单的举例了nmealib的基本功能,更多的功能可以查看samples文件夹中的例子,并在实践中不断熟悉提高。
    示例工程链接:【bitbucket
    
    简要说明:IAR ARM 6.5 simulator
    最后感谢我的同事utopiaprince,我从他那里学到很多东西,也帮助我解决了很多“疑难杂症”。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GPS nmealib学习笔记 的相关文章

  • 在 Iphone SDK 中显示 GPS 可用性和准确性

    如何编程以在 iPhone 中显示 GPS 可用性和准确度级别 并且它必须擦除标签中先前的纬度 经度信息 iOS sdk 中有一个类叫做 CLLocationManager 浏览 XCode 中的文档或查找一些示例 http mobileo
  • Android上的“覆盖”尺寸可以与谷歌地图一起缩放吗?

    我已经能够使用 MapActivity 和 ItemizedOverlay 通过 Eclipse 在 Android 上的谷歌地图上绘制叠加层 但是当地图放大和缩小时 叠加层的大小不会改变 我希望叠加层 固定 在地图上 并随地图一起放大和缩
  • GPS 转换 - 像素坐标到 GPS 坐标

    我正在根据视频数据进行一些运动跟踪 使用一些视频处理 即转换为自上而下的视图 我获得了移动路径 我现在需要将路径的像素坐标 x y 转换为世界坐标 纬度 经度 我在图像中有四个参考点及其相关的纬度和经度点 纬度 经度 gt 像素坐标 51
  • 如何在用户行走时跟踪 GPS 坐标,来自 iOS 平台的 xamarin.forms

    我刚刚经历过这个link http developer xamarin com recipes ios multitasking track significant location change 当用户使用 xamarin forms 应
  • 如何在没有“onLocationChange”方法的情况下知道 GPS 位置

    我想通过单击一个按钮来发送短信 并且在短信中我想发送位置信息 我试过 location locationManager getLastKnownLocation LocationManager NETWORK PROVIDER 但第一次显示
  • 如何停止位置管理器?

    不知道为什么 但有时 LocationManager 在关闭应用程序后仍然工作 我在一个 Activity 的 onCreate Methode 中调用 startGPS 只有一个 让我称之为 StartActivity protected
  • GPS/GIS 计算:根据运动/每小时预测未来位置的算法?

    寻找资源或算法来在导航应用程序中计算以下内容 如果我当前的 GPS 位置为 0 0 并且我以 15 英里 小时的速度前进 32 度 我如何计算 10 秒后我的位置 i e GPSCoordinate predictedCoord GPSCo
  • 信号好的情况下GPS更新间隔越快?

    我试图限制我的程序每 10 秒更新一次位置 而不是不断更新 以减少电池消耗 当我在室内调试且信号较弱 即 GPS 图标闪烁 时 此方法工作正常 但如果手机得到正确修复 即 GPS 图标静态 更新间隔会增加到大约一秒 我知道代码mLocati
  • GPS定位无服务

    我是一名新开发人员 有一个简单的问题 我已经四处搜索 但尚未找到明确的答案 简而言之 我正在开发一个需要能够使用 GPS 的应用程序 然而 诀窍是我想使用 GPS 来获取手机的位置 即使它们没有运营商服务 话虽如此 我有两个问题 是否可以通
  • 如何确定当前用户位置是否在我的 MKCooperativeRegion 内?

    我有一个坐标区域 我已确定该区域包含我想要为我的应用程序显示的内容的限制 我已将其设置为具有中心点纬度 经度和跨度的 MKCooperativeRegion 如何确定当前 userLocation 是否在我的坐标区域内 使用地图矩形 这是使
  • GMSPolyline 非常大的内存峰值

    在允许用户在各种不同类型的地图上显示我们称之为轨迹的复杂位置点列表的 GPS 应用程序中 每个轨迹可以包含 2k 到 10k 个位置点 当轨迹在非 Google 地图类型上呈现时 它们会被大量剪切 修剪和路径简化 这是为了降低内存使用量并提
  • 使用 LocationManager 时,为什么打开 Wifi 但未连接有助于网络定位?

    这可能是偏离主题的 如果是这样 我道歉 并很高兴接受关闭标志 但我在弄清楚为什么 WIFI 打开但未连接到任何接入点 在我的 Android 设备上 时遇到问题 它vastly提高网络提供商使用时的准确性LocationManager 如果
  • 从 GPS 坐标获取城市名称

    我想从 GPS 坐标获取城市的名称 我可以使用 Google API 获取 GPS 点的详细信息 http maps googleapis com maps api geocode output parameters 输出是 XML 但我不
  • C# - LINQ - GPS 纬度和经度的最短距离

    我有数据库 其中有带有 GPS 坐标的一流酒店 我想获得距离我选择的坐标最近的地方 我认为它应该看起来像这样 我在这里找到了很多示例代码 就像这样 var coord new GeoCoordinate latitude longitude
  • 在没有互联网的情况下使用 Javascript 获取 GPS 位置 [重复]

    这个问题在这里已经有答案了 您好 如果设备具有 GPS 硬件 我们可以在没有互联网连接的情况下使用 JavaScript 获取 GPS 位置吗 请注意谁将其标记为重复 我需要 JavaScript 在没有互联网连接的情况下工作 并使用 GP
  • 使用纬度/经度计算从 A 点到线段的距离

    我正在开发一个使用 GPS 的 Android 应用程序 我想知道如果 新位置 C 点 距离线段 AB 太远 是否有办法可以丢弃 GPS 位置数据 我正在使用发现的点到线段公式在维基百科上 http en wikipedia org wik
  • 如何知道jar文件是否已经在运行?

    经过谷歌研究后 我找到了很好的答案 例如 1 using jps or jps l让 jars 在 JVM 下运行 这个答案可以 但是如果用户根本没有安装java并且我使用例如 bat文件和带有java JRE的文件夹运行我的jar 另外
  • 如何在 Android 中像 Google 地图一样获得持续的位置更新?

    我正在构建一个朋友跟踪 Android 应用程序 当我的朋友激活应用程序并带着他的 GPS 和蜂窝数据离开时 我需要在我的设备上跟踪他 这就是这个概念 我已经实现了 LocationListener 类 现在我可以从 Gps 或网络获取最后
  • 关闭应用程序后如何调试

    我正在尝试重现问题 这需要在特定位置关闭并重新打开我的应用程序 这是我的问题 1 如何查看我的日志 使用NSLog命令 当我的 iPhone 未连接到 XCode 时 2 是否可以将iPhone模拟器的特定位置 例如市中心 设置为默认位置
  • Ruby on Rails:如何使用 TCP 套接字连接 GPS 设备

    ruby 2 3 0p0 2015 12 25 修订版 53290 x86 64 linux 轨道 4 2 4 我正在使用 cloud9 IDE 和 webrick 服务器 我的项目是实时跟踪GPS 我想使用TCP连接与GPS跟踪设备进行通

随机推荐