【问题标题】:Parsing *.nmea file with QNmeaPositionInfoSource class returns timeout.使用 QNmeaPositionInfoSource 类解析 *.nmea 文件会返回超时。
【发布时间】:2015-06-06 14:31:17
【问题描述】:

我正在尝试编写一个简单的应用程序,该应用程序将基于已经获取的*.nmea 日志文件来模拟 GPS 硬件设备。我选择的技术是Qt5.4.1。因为它已经上课了,应该负责我正在尝试做的任务。类名是QNmeaPositionInfoSource。 我认为通过设置适当的更新间隔超时实例QNmeaPositionInfoSource 将通知我有关新位置的信息。但是,当我将时间间隔设置为1s 时,我只得到一个位置,然后通知超时。当我将间隔设置为0 时,我会立即收到有关位置的所有通知。

请在下面找到我的程序代码:

主窗口.cpp

#include <QDebug>
#include <QFile>
#include <QNmeaPositionInfoSource>
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    logFile = new QFile(":/files/dummy.nmea");
    nmeaSource = new QNmeaPositionInfoSource(
        QNmeaPositionInfoSource::SimulationMode);
    nmeaSource->setDevice(logFile);
    nmeaSource->setUpdateInterval(1000);
    connect(nmeaSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
            this, SLOT(positionUpdated(QGeoPositionInfo)));
    connect(nmeaSource, SIGNAL(updateTimeout()), this, SLOT(updateTimeout()));
    connect(nmeaSource,SIGNAL(error(QGeoPositionInfoSource::Error)),
            this,SLOT(error(QGeoPositionInfoSource::Error)));
    nmeaSource->startUpdates();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::positionUpdated(QGeoPositionInfo positionInfo)
{
    qDebug() << __PRETTY_FUNCTION__;
    qDebug() << QString("Lat: %1").arg(QString::number(positionInfo.coordinate().latitude()));
    qDebug() << QString("Lon: %1").arg(QString::number(positionInfo.coordinate().longitude()));
}

void MainWindow::updateTimeout(void)
{
    qDebug() << __PRETTY_FUNCTION__;
}

void MainWindow::error(QGeoPositionInfoSource::Error positioningError)
{
    qDebug() << __PRETTY_FUNCTION__;
    qDebug() << QString::number(positioningError);
}

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGeoPositionInfo>
#include <QGeoPositionInfoSource>

class QFile;
class QNmeaPositionInfoSource;
//class QGeoPositionInfoSource;

namespace Ui
{
        class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QFile *logFile;
    QNmeaPositionInfoSource *nmeaSource;
private slots:
        void positionUpdated(QGeoPositionInfo positionInfo);
        void updateTimeout(void);
        void error(QGeoPositionInfoSource::Error positioningError);
};

#endif // MAINWINDOW_H

dummy.nmea

$GPGGA,222437.000,2734.33926,S,15305.44310,E,1,07,1.3,50.6,M,39.2,M,,*72
$GPGLL,2734.33926,S,15305.44310,E,222437.000,A,A*49
$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D
$GPGST,222437.000,13.3,7.4,6.6,85.1,6.0,6.8,13.7*56
$GPGSV,3,1,10,16,49,115,42,25,39,269,36,23,58,176,29,20,72,335,35*75
$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,30,223,30,27,19,284,35*78
$GPGSV,3,3,10,11,06,337,30,03,13,055,25*7C
$GPRMC,222437.000,A,2734.33926,S,15305.44310,E,33.9,157.8,030308,11.2,W,A*0F
$GPVTG,157.8,T,169.0,M,33.9,N,62.9,K,A*22
$GPGGA,222438.000,2734.34821,S,15305.44697,E,1,07,1.2,50.8,M,39.2,M,,*79
$GPGLL,2734.34821,S,15305.44697,E,222438.000,A,A*4D
$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33
$GPGST,222438.000,12.4,6.4,9.3,16.2,6.1,8.3,16.4*5F
$GPGSV,3,1,10,16,49,115,41,25,39,269,36,23,58,176,28,20,72,335,36*74
$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,28,27,19,284,35*73
$GPGSV,3,3,10,11,06,337,28,03,13,055,25*75
$GPRMC,222438.000,A,2734.34821,S,15305.44697,E,33.8,158.3,030308,11.2,W,A*0E
$GPVTG,158.3,T,169.5,M,33.8,N,62.5,K,A*2E
$GPGGA,222439.000,2734.35696,S,15305.45072,E,1,06,1.7,51.2,M,39.2,M,,*78
$GPGLL,2734.35696,S,15305.45072,E,222439.000,A,A*43
$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A
$GPGST,222439.000,10.3,9.1,12.2,44.6,9.8,9.9,25.2*62
$GPGSV,3,1,10,16,49,115,34,25,39,269,36,23,58,175,29,20,72,335,35*77
$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,27,27,19,284,32*7B
$GPGSV,3,3,10,11,06,337,28,03,14,055,25*72
$GPRMC,222439.000,A,2734.35696,S,15305.45072,E,33.2,158.7,030308,11.2,W,A*0E
$GPVTG,158.7,T,169.9,M,33.2,N,61.5,K,A*2F
$GPGGA,222440.000,2734.36580,S,15305.45446,E,1,07,1.3,52.0,M,39.2,M,,*76
$GPGLL,2734.36580,S,15305.45446,E,222440.000,A,A*49
$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D
$GPGST,222440.000,13.0,8.0,13.4,6.2,7.4,12.2,20.9*64
$GPGSV,3,1,10,16,49,115,40,25,39,269,38,23,58,175,31,20,72,335,34*72
$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,26,27,19,284,30*78
$GPGSV,3,3,10,11,06,337,26,03,14,055,25*7C
$GPRMC,222440.000,A,2734.36580,S,15305.45446,E,33.7,159.1,030308,11.2,W,A*06
$GPVTG,159.1,T,170.3,M,33.7,N,62.4,K,A*2D
$GPGGA,222441.000,2734.37483,S,15305.45825,E,1,07,1.3,52.7,M,39.2,M,,*7A
$GPGLL,2734.37483,S,15305.45825,E,222441.000,A,A*42
$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D
$GPGST,222441.000,14.0,7.6,14.1,17.6,7.7,12.5,21.0*51
$GPGSV,3,1,10,16,49,115,41,25,39,269,39,23,58,175,29,20,72,335,35*7A
$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,24,27,19,284,30*7A
$GPGSV,3,3,10,11,06,337,28,03,14,055,25*72
$GPRMC,222441.000,A,2734.37483,S,15305.45825,E,34.6,159.4,030308,11.2,W,A*0E
$GPVTG,159.4,T,170.6,M,34.6,N,64.1,K,A*28
$GPGGA,222442.000,2734.38407,S,15305.46216,E,1,06,1.3,53.3,M,39.2,M,,*77
$GPGLL,2734.38407,S,15305.46216,E,222442.000,A,A*4B
$GPGSA,A,3,16,25,20,13,27,11,,,,,,,2.3,1.3,1.9*3C
$GPGST,222442.000,16.6,7.0,14.4,14.6,7.0,12.8,21.6*5A
$GPGSV,3,1,10,16,49,115,40,25,39,269,38,23,58,175,22,20,72,335,35*71

问题是为什么我会收到超时通知?

【问题讨论】:

  • 你解决了吗?我正在用同样的问题尝试同样的事情:只调用了 updateTimeout() 。它永远不会从中恢复过来。我试图按照其他答案的建议过滤掉除 GPGGA 和 GPRMC 之外的所有内容,但它没有解决这个问题。并且删除或更改更新间隔也没有。谢谢
  • 不,我没有解决这个问题,我只是自己编写了 nmea 解析器。只需查看 Qt 源代码,它就是完成这项任务的良好基础。
  • 只是链接到您打开的票:QTBUG-51824

标签: c++ qt gps nmea


【解决方案1】:

遇到同样的问题。

如果您在 NMEA 文件中仅保留 $GPGGA 和 $GPRMC 行,它将正常工作。 $GPVTG 确实会导致您描述的问题, $GPGSV - 不要(所以您也可以离开它,不重要)。 我没有单独测试过的其他 NMEA 消息。

“纯”NMEA 文件如帮助中所述完美运行:即使不调用 setUpdateInterval()(显然与零参数相同),您也会根据 NMEA 行中的时间戳获得更新间隔。

这显然是 Qt 错误。即使您在桌面上运行 GeoFlickr 示例(以便程序在 SimulationMode 下使用 QNmeaPositionInfoSource 开始工作),您也会看到在第一次单击时按“定位和更新”按钮仅显示一次纬度和经度数据。之后它显示“检索更新”并且没有任何反应,但根据代码它应该。

另一个确认案例可能仅在 $GPVTG 消息中:我使用 GeoFlickr 示例中的“nmealog.txt”而不是您的“dummy.nmea”,并且在超时之前我有两次 positionUpdated 调用。一份用于$GPGGA,一份用于$GPRMC。但是,在您的“dummy.nmea”中,在 $GPVTG 之前只有一条消息 $GPRMC,因此您只通知了一次 positionUpdated 调用。

(以防万一在 Windows 7 上使用 Qt5.5.1)

【讨论】:

  • 这对我不起作用。我试图过滤我的输入流以仅包含 GPGGA 和 GPRMC。但是直到我删除了 GPRMC,我至少得到了一个错误响应,而不是超时说:日期和时间不可用。这表明它确实处理了 nmea 流但没有正确发出信号?
【解决方案2】:

我查看了 Qt 源代码并得出以下结论。 如果您注释 nmeaSource-&gt;setUpdateInterval(1000); 行或设置 0 值,该示例将按预期工作,因为 QGeoPositionInfoSource 的文档说:

如果未设置更新间隔(或设置为 0),源将根据需要提供更新。

尽管您在 SimulationMode 中为 setUpdateInterval() 函数设置了非零值,但源文件 (dummy.nmea) 被一次性读取,因此没有新数据可供读取并且这就是超时发生的原因。来自 Qt 源代码的几行代码:

// some data may already be available
if (m_updateMode == QNmeaPositionInfoSource::SimulationMode) {
    if (m_nmeaReader && m_device->bytesAvailable())
        m_nmeaReader->readAvailableData();

我不确定这是否是一个错误,但我认为可以在 Qt 文档中添加一些关于此的信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    相关资源
    最近更新 更多