gpt4 book ai didi

c++ - gpsd 客户端数据缓冲区

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:29:52 27 4
gpt4 key购买 nike

我正在开发一个 C++ 应用程序,它应该使用 gpsd 检索接收到的 $GPGGA 类型的 NMEA 语句。我的想法是大约每秒从 gpsd 读取一次并解析最后收到的 $GPGGA 语句,提取我感兴趣的两个字段:质量指标和引用站 ID。我使用了 C++ libgpsmm 库,定期调用 gpsmm::read()gpsmm::data(),直接访问客户端数据缓冲区。

起初,我使用 gpsfake 和伪造的 GPS 日志进行了多次测试(指定 gpsfake 选项“-c 0.5”,以便每秒有两个句子)。当对 gpsd 的两次请求之间的时间小于或等于 400ms 时,结果是可以的。如果我尝试更长的时间,结果是出乎意料的,每次阅读 NMEA 句子都有很多重复的数据以及一些截断的句子。当我尝试使用每秒写入约 40 个句子的真实 GPS 时,情况确实更糟:在这种情况下,读取之间的时间应为约 10 毫秒或更短,以便获得正确的结果。

以下是一个更简单的程序,它打印接收到的 NMEA 语句。它适用于模拟甚至真实的 GPS。但是如果我取消注释 usleep() 调用,这会使程序每秒检查一次缓冲区,客户端数据缓冲区不会给出合理的结果。

#include <iostream>

#include "libgpsmm.h"

using namespace std;

#define WAITING_TIME 5000000
#define RETRY_TIME 5
#define ONE_SECOND 1000000

int main(void)
{
for(;;){
//For version 3.7
gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT);

if (gps_rec.stream(WATCH_ENABLE|WATCH_NMEA) == NULL) {
cout << "No GPSD running. Retry to connect in " << RETRY_TIME << " seconds." << endl;
usleep(RETRY_TIME * ONE_SECOND);
continue; // It will try to connect to gpsd again
}

const char* buffer = NULL;

for (;;) {
struct gps_data_t* newdata;

if (!gps_rec.waiting(WAITING_TIME))
continue;

if ((newdata = gps_rec.read()) == NULL) {
cerr << "Read error.\n";
break;
} else {
buffer = gps_rec.data();

// We print the NMEA sentences!
cout << "***********" << endl;
cout << buffer << endl;

//usleep(1000000);
}
}
}
}

这是对 usleep() 调用进行了注释(即持续读取数据)的输出:

$      ./GPSTest1
***********
{"class":"VERSION","release":"3.7","rev":"3.7","proto_major":3,"proto_minor":7}
***********
{"class":"WATCH","enable":true,"json":false,"nmea":true,"raw":0,"scaled":false,"timing":false}
***********
$GPGGA,202010.00,3313.9555651,S,06019.3785868,W,4,09,1.0,39.384,M,16.110,M,10.0,*46<CR><LF>
***********
$GPGGA,202011.00,3313.9555664,S,06019.3785876,W,4,09,1.0,39.386,M,16.110,M,11.0,*4D<CR><LF>
***********
$GPGGA,202012.00,3313.9555668,S,06019.3785882,W,4,09,1.0,39.394,M,16.110,M,12.0,*49<CR><LF>
***********
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,4,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF>
***********
$GPGGA,202014.00,3313.9555670,S,06019.3785907,W,4,09,1.0,39.409,M,16.110,M,14.0,*4F<CR><LF>
***********
$GPGGA,202015.00,3313.9555657,S,06019.3785905,W,4,09,1.0,39.395,M,16.110,M,15.0,*4A<CR><LF>

这是注释该行时的输出(即每秒检查一次缓冲区):

$    ./GPSTest2
***********
{"class":"VERSION","release":"3.7","rev":"3.7","proto_major":3,"proto_minor":7}
***********
{"class":"DEVICE","path":"/dev/pts/0","activated":"2012-11-05T23:48:38.110Z","driver":"Generic NMEA","native":0,"bps":4800,"parity":"N","stopbits":1,"cycle":1.00}
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,1,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF>
0}
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,1,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF>
":"Generic NMEA","native":0,"bps":4800,"parity":"N","stopbits":1,"cycle":1.00}
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,1,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF>

***********
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,1,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF>
***********
$GPGGA,202016.00,3313.9555642,S,06019.3785894,W,1,09,1.0,39.402,M,16.110,M,16.0,*4E<CR><LF>
$GPGGA,202017.00,3313.9555643,S,06019.3785925,W,1,09,1.0,39.404,M,16.110,M,17.0,*42<CR><LF>
$GPGGA,202017.00,3313.9555643,S,06019.3785925,W,1,09,1.0,39.404,M,16.110,M,17.0,*42<CR><LF>
$GPGGA,202017.00,3313.9555643,S,06019.3785925,W,1,09,1.0,39.404,M,16.110,M,17.0,*42<CR><LF>
***********

有什么建议吗?起初,我试图直接分析gps_data_t结构,但在结构的所有字段中,这种方式似乎更难以识别质量指标和引用站ID,与在 NMEA 句子中搜索。

最佳答案

我不熟悉 gpsd 服务,但你所描述的看起来很像接收缓冲区被损坏(覆盖)。 GPS 接收器不断输出 NMEA 信息,当您的应用程序处于休眠状态时,这些字符将累积在缓冲区中,如果接收到太多字符,缓冲区将被覆盖。

要么增加串行端口接收器缓冲区大小(如果可能),要么在唤醒后清除缓冲区,然后等待下一条 GGA 消息(在最坏的情况下可能最多需要一秒)。

GPS 接收器应配置为以 1Hz(每秒一次)的频率输出信息,在这种情况下,设备每秒只能输出大约 8 个句子。如果您看到 40 个句子,那么您的接收器似乎以 5Hz 左右的频率输出信息,这对于您的特殊兴趣来说听起来有点过头了。

关于c++ - gpsd 客户端数据缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13607163/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com