使用QNmeaPositionInfoSource类解析* .nmea文件将返回超时。

时间:2015-06-06 14:31:17

标签: c++ qt gps nmea

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

请在下面找到我的计划代码:

mainwindow.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);
}

mainwindow.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

问题是我收到超时通知的原因?

2 个答案:

答案 0 :(得分:0)

遇到同样的问题。

如果您只在NMEA文件中留下$ GPGGA和$ GPRMC行,它将起作用。 $ GPVTG会导致你所描述的问题,$ GPGSV - 不要(所以你也可以留下它,不重要)。 其他NMEA消息我没有单独测试过。

“Pure”NMEA文件完美地与help中描述的一样:即使不调用setUpdateInterval()(显然与零参数相同),您也会根据NMEA行中的时间戳获得更新间隔。

这显然是Qt的bug。即使您在Desktop上运行GeoFlickr示例(以便程序开始使用SimulationMode中的QNmeaPositionInfoSource),您也会看到按“locate&amp; update”按钮仅在第一次单击时显示纬度和经度数据一次。之后它显示“检索更新”并没有任何反应,但根据代码它应该。

另一个确认案例可能只是在$ GPVTG消息中:我使用了来自GeoFlickr示例的“dummy.nmea”而不是“nmealog.txt”,我在超时之前有两次positionUpdated调用。一个用于$ GPGGA,另一个用于$ GPRMC。但是在你的“dummy.nmea”中,$ GPVTG之前只有一条消息$ GPRMC,所以你只通过了一次positionUpdated调用。

(以防万一在Windows 7上的Qt5.5.1上播放)

答案 1 :(得分:0)

我查看了Qt资料并得出以下结论。 如果您对行nmeaSource->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文档中添加一些相关信息。