source: ntrip/trunk/BNC/src/pppRun.cpp@ 7959

Last change on this file since 7959 was 7943, checked in by stuerze, 10 years ago

the approach how to wait for clock corrections in PPP mode, which was well proven in BNC verson 2.11 is now re-implemented

File size: 20.1 KB
RevLine 
[5860]1
2// Part of BNC, a utility for retrieving decoding and
3// converting GNSS data streams from NTRIP broadcasters.
4//
5// Copyright (C) 2007
6// German Federal Agency for Cartography and Geodesy (BKG)
7// http://www.bkg.bund.de
8// Czech Technical University Prague, Department of Geodesy
9// http://www.fsv.cvut.cz
10//
11// Email: euref-ip@bkg.bund.de
12//
13// This program is free software; you can redistribute it and/or
14// modify it under the terms of the GNU General Public License
15// as published by the Free Software Foundation, version 2.
16//
17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU General Public License for more details.
21//
22// You should have received a copy of the GNU General Public License
23// along with this program; if not, write to the Free Software
24// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26/* -------------------------------------------------------------------------
27 * BKG NTRIP Client
28 * -------------------------------------------------------------------------
29 *
[5883]30 * Class: t_pppRun
[5860]31 *
32 * Purpose: Single Real-Time PPP Client
33 *
34 * Author: L. Mervart
35 *
36 * Created: 29-Jul-2014
37 *
[7278]38 * Changes:
[5860]39 *
40 * -----------------------------------------------------------------------*/
41
42
43#include <iostream>
44#include <iomanip>
[5980]45#include <sstream>
[5860]46#include <string.h>
47#include <map>
48
[5883]49#include "pppRun.h"
[5891]50#include "pppThread.h"
[5860]51#include "bnccore.h"
52#include "bncephuser.h"
[5953]53#include "bncsettings.h"
[5984]54#include "bncoutf.h"
[6653]55#include "bncsinextro.h"
[5883]56#include "rinex/rnxobsfile.h"
57#include "rinex/rnxnavfile.h"
58#include "rinex/corrfile.h"
[7299]59#include "combination/bnccomb.h"
[5860]60
61using namespace BNC_PPP;
62using namespace std;
63
64// Constructor
65////////////////////////////////////////////////////////////////////////////
[5883]66t_pppRun::t_pppRun(const t_pppOptions* opt) {
67
[5860]68 _opt = opt;
[5883]69
[7278]70 connect(this, SIGNAL(newMessage(QByteArray,bool)),
[5860]71 BNC_CORE, SLOT(slotMessage(const QByteArray,bool)));
[5883]72
[5991]73 connect(this, SIGNAL(newPosition(QByteArray, bncTime, QVector<double>)),
[5954]74 BNC_CORE, SIGNAL(newPosition(QByteArray, bncTime, QVector<double>)));
[5949]75
[5991]76 connect(this, SIGNAL(newNMEAstr(QByteArray, QByteArray)),
77 BNC_CORE, SIGNAL(newNMEAstr(QByteArray, QByteArray)));
78
[5883]79 _pppClient = new t_pppClient(_opt);
80
[5984]81 bncSettings settings;
82
[5860]83 if (_opt->_realTime) {
[5945]84 Qt::ConnectionType conType = Qt::AutoConnection;
85 if (BNC_CORE->mode() == t_bncCore::batchPostProcessing) {
86 conType = Qt::BlockingQueuedConnection;
87 }
88
[6137]89 connect(BNC_CORE->caster(), SIGNAL(newObs(QByteArray, QList<t_satObs>)),
90 this, SLOT(slotNewObs(QByteArray, QList<t_satObs>)),conType);
[5860]91
[6433]92 connect(BNC_CORE, SIGNAL(newGPSEph(t_ephGPS)),
93 this, SLOT(slotNewGPSEph(t_ephGPS)),conType);
[7278]94
[6433]95 connect(BNC_CORE, SIGNAL(newGlonassEph(t_ephGlo)),
96 this, SLOT(slotNewGlonassEph(t_ephGlo)),conType);
[7278]97
[6433]98 connect(BNC_CORE, SIGNAL(newGalileoEph(t_ephGal)),
99 this, SLOT(slotNewGalileoEph(t_ephGal)),conType);
[5860]100
[6966]101 connect(BNC_CORE, SIGNAL(newBDSEph(t_ephBDS)),
102 this, SLOT(slotNewBDSEph(t_ephBDS)),conType);
103
[7231]104 connect(BNC_CORE, SIGNAL(newTec(t_vTec)),
105 this, SLOT(slotNewTec(t_vTec)),conType);
106
[6141]107 connect(BNC_CORE, SIGNAL(newOrbCorrections(QList<t_orbCorr>)),
108 this, SLOT(slotNewOrbCorrections(QList<t_orbCorr>)),conType);
109
110 connect(BNC_CORE, SIGNAL(newClkCorrections(QList<t_clkCorr>)),
111 this, SLOT(slotNewClkCorrections(QList<t_clkCorr>)),conType);
[6478]112
113 connect(BNC_CORE, SIGNAL(newCodeBiases(QList<t_satCodeBias>)),
114 this, SLOT(slotNewCodeBiases(QList<t_satCodeBias>)),conType);
[7288]115
116 connect(BNC_CORE, SIGNAL(newPhaseBiases(QList<t_satPhaseBias>)),
117 this, SLOT(slotNewPhaseBiases(QList<t_satPhaseBias>)),conType);
[7299]118
119 connect(BNC_CMB, SIGNAL(newOrbCorrections(QList<t_orbCorr>)),
120 this, SLOT(slotNewOrbCorrections(QList<t_orbCorr>)),conType);
121
122 connect(BNC_CMB, SIGNAL(newClkCorrections(QList<t_clkCorr>)),
123 this, SLOT(slotNewClkCorrections(QList<t_clkCorr>)),conType);
[5860]124 }
125 else {
[5889]126 _rnxObsFile = 0;
127 _rnxNavFile = 0;
128 _corrFile = 0;
[5953]129 _speed = settings.value("PPP/mapSpeedSlider").toInt();
[5941]130 connect(this, SIGNAL(progressRnxPPP(int)), BNC_CORE, SIGNAL(progressRnxPPP(int)));
131 connect(this, SIGNAL(finishedRnxPPP()), BNC_CORE, SIGNAL(finishedRnxPPP()));
[7278]132 connect(BNC_CORE, SIGNAL(mapSpeedSliderChanged(int)),
[5950]133 this, SLOT(slotSetSpeed(int)));
[5973]134 connect(BNC_CORE, SIGNAL(stopRinexPPP()), this, SLOT(slotSetStopFlag()));
[5860]135 }
[7278]136
[5973]137 _stopFlag = false;
[5984]138
[7506]139 QString roverName(_opt->_roverName.c_str()), fullRoverName("");
140 QString country;
141 QString monNum = "0";
142 QString recNum = "0";
143 QString intr = "1 day";
144 int sampl = 0;
145 QListIterator<QString> it(settings.value("mountPoints").toStringList());
146 while (it.hasNext()) {
147 QStringList hlp = it.next().split(" ");
148 if (hlp.size() < 7)
149 continue;
150 if (hlp.join(" ").indexOf(roverName, 0) != -1) {
151 country = hlp[2];
152 }
153 }
154 fullRoverName = roverName.left(4) +
155 QString("%1").arg(monNum, 1, 10) +
156 QString("%1").arg(recNum, 1, 10) +
157 country;
[5988]158
[7506]159 bool v3filenames = settings.value("PPP/v3filenames").toBool();
160 QString logFileSkl = settings.value("PPP/logPath").toString();
[7520]161 int l = logFileSkl.length();
[5988]162 if (logFileSkl.isEmpty()) {
163 _logFile = 0;
[5987]164 }
165 else {
[7520]166 if (l && logFileSkl[l-1] != QDir::separator() ) {
167 logFileSkl += QDir::separator();
168 }
[7506]169 if (v3filenames) {
170 logFileSkl = logFileSkl + fullRoverName + "${V3}" + ".ppp";
[5988]171 }
172 else {
[7506]173 logFileSkl = logFileSkl + roverName.left(4) + "${GPSWD}" + ".ppp";
[5988]174 }
[7506]175 _logFile = new bncoutf(logFileSkl, intr, sampl);
[5987]176 }
[5988]177
[7506]178 QString nmeaFileSkl = settings.value("PPP/nmeaPath").toString();
[7520]179 l = nmeaFileSkl.length();
[5988]180 if (nmeaFileSkl.isEmpty()) {
181 _nmeaFile = 0;
182 }
183 else {
[7520]184 if (l > 0 && nmeaFileSkl[l-1] != QDir::separator() ) {
185 nmeaFileSkl += QDir::separator();
186 }
[7506]187 if (v3filenames) {
188 nmeaFileSkl = nmeaFileSkl + fullRoverName + "${V3}" + ".nmea";
[5988]189 }
190 else {
[7506]191 nmeaFileSkl = nmeaFileSkl + roverName.left(4) + "${GPSWD}" + ".nmea";
[5988]192 }
[7506]193 _nmeaFile = new bncoutf(nmeaFileSkl, intr, sampl);
[5988]194 }
[6608]195
[7506]196 QString snxtroFileSkl = settings.value("PPP/snxtroPath").toString();
[7520]197 l = snxtroFileSkl.length();
[6608]198 if (snxtroFileSkl.isEmpty()) {
199 _snxtroFile = 0;
200 }
201 else {
[7520]202 if (l > 0 && snxtroFileSkl[l-1] != QDir::separator() ) {
203 snxtroFileSkl += QDir::separator();
204 }
[7506]205 if (v3filenames) {
206 snxtroFileSkl = snxtroFileSkl + fullRoverName + "${V3}" + ".tra";
[6608]207 }
208 else {
[7506]209 snxtroFileSkl = snxtroFileSkl + roverName.left(4) + "${GPSWD}" + ".tro";
[6608]210 }
[7506]211 sampl = settings.value("PPP/snxtroSampl").toInt();
212 intr = settings.value("PPP/snxtroIntr").toString();
213 _snxtroFile = new bncSinexTro(_opt, snxtroFileSkl, intr, sampl);
[6608]214 }
[5860]215}
216
[6608]217
218
[5860]219// Destructor
220////////////////////////////////////////////////////////////////////////////
[5883]221t_pppRun::~t_pppRun() {
[5984]222 delete _logFile;
[5988]223 delete _nmeaFile;
[6608]224 delete _snxtroFile;
[7655]225 while (!_epoData.empty()) {
[7926]226 delete _epoData.front();
[7655]227 _epoData.pop_front();
228 }
[5860]229}
230
[7278]231//
[5860]232////////////////////////////////////////////////////////////////////////////
[6433]233void t_pppRun::slotNewGPSEph(t_ephGPS eph) {
[5860]234 QMutexLocker locker(&_mutex);
235 _pppClient->putEphemeris(&eph);
236}
237
[7278]238//
[5860]239////////////////////////////////////////////////////////////////////////////
[6433]240void t_pppRun::slotNewGlonassEph(t_ephGlo eph) {
[5860]241 QMutexLocker locker(&_mutex);
242 _pppClient->putEphemeris(&eph);
243}
[7278]244
245//
[5860]246////////////////////////////////////////////////////////////////////////////
[6433]247void t_pppRun::slotNewGalileoEph(t_ephGal eph) {
[5860]248 QMutexLocker locker(&_mutex);
249 _pppClient->putEphemeris(&eph);
250}
251
252//
253////////////////////////////////////////////////////////////////////////////
[6966]254void t_pppRun::slotNewBDSEph(t_ephBDS eph) {
255 QMutexLocker locker(&_mutex);
256 _pppClient->putEphemeris(&eph);
257}
258
259//
260////////////////////////////////////////////////////////////////////////////
[6137]261void t_pppRun::slotNewObs(QByteArray staID, QList<t_satObs> obsList) {
[5860]262 QMutexLocker locker(&_mutex);
263
264 if (string(staID.data()) != _opt->_roverName) {
265 return;
266 }
267
[7278]268 // Loop over all observations (possible different epochs)
[5860]269 // -----------------------------------------------------
[6137]270 QListIterator<t_satObs> it(obsList);
[5860]271 while (it.hasNext()) {
[6137]272 const t_satObs& oldObs = it.next();
273 t_satObs* newObs = new t_satObs(oldObs);
[5860]274
275 // Find the corresponding data epoch or create a new one
276 // -----------------------------------------------------
277 t_epoData* epoch = 0;
278 deque<t_epoData*>::const_iterator it;
279 for (it = _epoData.begin(); it != _epoData.end(); it++) {
280 if (newObs->_time == (*it)->_time) {
281 epoch = *it;
282 break;
283 }
284 }
285 if (epoch == 0) {
286 if (_epoData.empty() || newObs->_time > _epoData.back()->_time) {
287 epoch = new t_epoData;
288 epoch->_time = newObs->_time;
289 _epoData.push_back(epoch);
290 }
291 }
292
[6137]293 // Put data into the epoch
294 // -----------------------
[5860]295 if (epoch != 0) {
296 epoch->_satObs.push_back(newObs);
297 }
[6137]298 else {
299 delete newObs;
300 }
[5860]301 }
302
[7943]303 // Make sure the buffer does not grow beyond any limit
304 // ---------------------------------------------------
305 const unsigned MAX_EPODATA_SIZE = 120;
306 if (_epoData.size() > MAX_EPODATA_SIZE) {
307 delete _epoData.front();
308 _epoData.pop_front();
309 }
310
[5860]311 // Process the oldest epochs
312 // ------------------------
[7943]313 while (_epoData.size()) {
[5860]314
315 const vector<t_satObs*>& satObs = _epoData.front()->_satObs;
316
[7943]317 // No corrections yet, skip the epoch
318 // ----------------------------------
319 if (_opt->_corrWaitTime && !_lastClkCorrTime.valid()) {
320 return;
[5873]321 }
322
[7943]323 // Process the front epoch
324 // -----------------------
325 if (_opt->_corrWaitTime == 0 ||
326 _epoData.front()->_time - _lastClkCorrTime < _opt->_corrWaitTime) {
[7278]327
[7943]328 t_output output;
329 _pppClient->processEpoch(satObs, &output);
[5980]330
[7943]331 if (!output._error) {
332 QVector<double> xx(6);
333 xx.data()[0] = output._xyzRover[0];
334 xx.data()[1] = output._xyzRover[1];
335 xx.data()[2] = output._xyzRover[2];
336 xx.data()[3] = output._neu[0];
337 xx.data()[4] = output._neu[1];
338 xx.data()[5] = output._neu[2];
339 emit newPosition(staID, output._epoTime, xx);
340 }
[5984]341
[7943]342 delete _epoData.front();
343 _epoData.pop_front();
344
345 ostringstream log;
346 if (output._error) {
347 log << output._log;
[5989]348 }
[7943]349 else {
350 log.setf(ios::fixed);
351 log << string(output._epoTime) << ' ' << staID.data()
352 << " X = " << setprecision(4) << output._xyzRover[0]
353 << " Y = " << setprecision(4) << output._xyzRover[1]
354 << " Z = " << setprecision(4) << output._xyzRover[2]
355 << " NEU: " << showpos << setw(8) << setprecision(4) << output._neu[0]
356 << " " << showpos << setw(8) << setprecision(4) << output._neu[1]
357 << " " << showpos << setw(8) << setprecision(4) << output._neu[2]
358 << " TRP: " << showpos << setw(8) << setprecision(4) << output._trp0
359 << " " << showpos << setw(8) << setprecision(4) << output._trp;
[7815]360 }
[7943]361
362 if (_logFile && output._epoTime.valid()) {
363 _logFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(),
364 QString(output._log.c_str()));
365 }
366
367 if (!output._error) {
368 QString rmcStr = nmeaString('R', output);
369 QString ggaStr = nmeaString('G', output);
370 if (_nmeaFile) {
371 _nmeaFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(), rmcStr);
372 _nmeaFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(), ggaStr);
373 }
374 emit newNMEAstr(staID, rmcStr.toAscii());
375 emit newNMEAstr(staID, ggaStr.toAscii());
376 if (_snxtroFile && output._epoTime.valid()) {
377 _snxtroFile->write(staID, int(output._epoTime.gpsw()), output._epoTime.gpssec(),
378 output._trp0 + output._trp, output._trpStdev);
379 }
380 }
381 emit newMessage(QByteArray(log.str().c_str()), true);
[5989]382 }
[7943]383 else {
384 return;
385 }
[5860]386 }
387}
[7231]388
389//
390////////////////////////////////////////////////////////////////////////////
391void t_pppRun::slotNewTec(t_vTec vTec) {
392 if (vTec._layers.size() == 0) {
393 return;
394 }
395
396 if (_opt->_realTime) {
397 if (_opt->_corrMount.empty() || _opt->_corrMount != vTec._staID) {
398 return;
399 }
400 }
401
402 _pppClient->putTec(&vTec);
403}
404
[7278]405//
[5860]406////////////////////////////////////////////////////////////////////////////
[6141]407void t_pppRun::slotNewOrbCorrections(QList<t_orbCorr> orbCorr) {
408 if (orbCorr.size() == 0) {
409 return;
410 }
[5860]411
[5937]412 if (_opt->_realTime) {
[6141]413 if (_opt->_corrMount.empty() || _opt->_corrMount != orbCorr[0]._staID) {
[5937]414 return;
415 }
[5860]416 }
[6141]417 vector<t_orbCorr*> corrections;
418 for (int ii = 0; ii < orbCorr.size(); ii++) {
419 corrections.push_back(new t_orbCorr(orbCorr[ii]));
420 }
[5860]421
[7278]422 _pppClient->putOrbCorrections(corrections);
423
424 for (unsigned ii = 0; ii < corrections.size(); ii++) {
425 delete corrections[ii];
426 }
[6141]427}
428
[7278]429//
[6141]430////////////////////////////////////////////////////////////////////////////
431void t_pppRun::slotNewClkCorrections(QList<t_clkCorr> clkCorr) {
432 if (clkCorr.size() == 0) {
[5860]433 return;
434 }
435
[7301]436 if (_opt->_realTime) {
[6141]437 if (_opt->_corrMount.empty() || _opt->_corrMount != clkCorr[0]._staID) {
438 return;
[5860]439 }
440 }
[6141]441 vector<t_clkCorr*> corrections;
442 for (int ii = 0; ii < clkCorr.size(); ii++) {
443 corrections.push_back(new t_clkCorr(clkCorr[ii]));
[6991]444 _lastClkCorrTime = clkCorr[ii]._time;
[6141]445 }
[7278]446 _pppClient->putClkCorrections(corrections);
447
448 for (unsigned ii = 0; ii < corrections.size(); ii++) {
449 delete corrections[ii];
450 }
[5860]451}
[5883]452
[7278]453//
[5883]454////////////////////////////////////////////////////////////////////////////
[6478]455void t_pppRun::slotNewCodeBiases(QList<t_satCodeBias> codeBiases) {
456 if (codeBiases.size() == 0) {
457 return;
458 }
459
460 if (_opt->_realTime) {
461 if (_opt->_corrMount.empty() || _opt->_corrMount != codeBiases[0]._staID) {
462 return;
463 }
464 }
465 vector<t_satCodeBias*> biases;
466 for (int ii = 0; ii < codeBiases.size(); ii++) {
467 biases.push_back(new t_satCodeBias(codeBiases[ii]));
468 }
469
[7278]470 _pppClient->putCodeBiases(biases);
471
472 for (unsigned ii = 0; ii < biases.size(); ii++) {
473 delete biases[ii];
474 }
[6478]475}
476
[7278]477//
[6478]478////////////////////////////////////////////////////////////////////////////
[7288]479void t_pppRun::slotNewPhaseBiases(QList<t_satPhaseBias> phaseBiases) {
480 if (phaseBiases.size() == 0) {
481 return;
482 }
483
484 if (_opt->_realTime) {
485 if (_opt->_corrMount.empty() || _opt->_corrMount != phaseBiases[0]._staID) {
486 return;
487 }
488 }
489 vector<t_satPhaseBias*> biases;
490 for (int ii = 0; ii < phaseBiases.size(); ii++) {
491 biases.push_back(new t_satPhaseBias(phaseBiases[ii]));
492 }
493
494 _pppClient->putPhaseBiases(biases);
495
496 for (unsigned ii = 0; ii < biases.size(); ii++) {
497 delete biases[ii];
498 }
499}
500
501//
502////////////////////////////////////////////////////////////////////////////
[5883]503void t_pppRun::processFiles() {
504
505 try {
[5889]506 _rnxObsFile = new t_rnxObsFile(QString(_opt->_rinexObs.c_str()), t_rnxObsFile::input);
[5883]507 }
508 catch (...) {
509 delete _rnxObsFile; _rnxObsFile = 0;
[5940]510 emit finishedRnxPPP();
[5883]511 return;
512 }
513
[5889]514 _rnxNavFile = new t_rnxNavFile(QString(_opt->_rinexNav.c_str()), t_rnxNavFile::input);
[5883]515
[5889]516 if (!_opt->_corrFile.empty()) {
517 _corrFile = new t_corrFile(QString(_opt->_corrFile.c_str()));
[7231]518 connect(_corrFile, SIGNAL(newTec(t_vTec)),
519 this, SLOT(slotNewTec(t_vTec)));
[6145]520 connect(_corrFile, SIGNAL(newOrbCorrections(QList<t_orbCorr>)),
521 this, SLOT(slotNewOrbCorrections(QList<t_orbCorr>)));
[6185]522 connect(_corrFile, SIGNAL(newClkCorrections(QList<t_clkCorr>)),
523 this, SLOT(slotNewClkCorrections(QList<t_clkCorr>)));
[6478]524 connect(_corrFile, SIGNAL(newCodeBiases(QList<t_satCodeBias>)),
525 this, SLOT(slotNewCodeBiases(QList<t_satCodeBias>)));
[7288]526 connect(_corrFile, SIGNAL(newPhaseBiases(QList<t_satPhaseBias>)),
527 this, SLOT(slotNewPhaseBiases(QList<t_satPhaseBias>)));
[5883]528 }
529
530 // Read/Process Observations
531 // -------------------------
532 int nEpo = 0;
533 const t_rnxObsFile::t_rnxEpo* epo = 0;
[5973]534 while ( !_stopFlag && (epo = _rnxObsFile->nextEpoch()) != 0 ) {
[5883]535 ++nEpo;
536
[5951]537 if (_speed < 100) {
538 double sleepTime = 2.0 / _speed;
[6537]539 t_pppThread::msleep(int(sleepTime*1.e3));
[5883]540 }
541
542 // Get Corrections
543 // ---------------
544 if (_corrFile) {
[6510]545 try {
546 _corrFile->syncRead(epo->tt);
547 }
548 catch (const char* msg) {
549 emit newMessage(QByteArray(msg), true);
550 break;
551 }
552 catch (const string& msg) {
553 emit newMessage(QByteArray(msg.c_str()), true);
554 break;
555 }
556 catch (...) {
557 emit newMessage("unknown exceptions in corrFile", true);
558 break;
559 }
[5883]560 }
561
562 // Get Ephemerides
563 // ----------------
564 t_eph* eph = 0;
[7169]565 const QMap<QString, unsigned int>* corrIODs = _corrFile ? &_corrFile->corrIODs() : 0;
[5883]566 while ( (eph = _rnxNavFile->getNextEph(epo->tt, corrIODs)) != 0 ) {
[5889]567 _pppClient->putEphemeris(eph);
568 delete eph; eph = 0;
[5883]569 }
570
[5890]571 // Create list of observations and start epoch processing
572 // ------------------------------------------------------
[6137]573 QList<t_satObs> obsList;
[5883]574 for (unsigned iObs = 0; iObs < epo->rnxSat.size(); iObs++) {
575 const t_rnxObsFile::t_rnxSat& rnxSat = epo->rnxSat[iObs];
[7278]576
[6137]577 t_satObs obs;
[5883]578 t_rnxObsFile::setObsFromRnx(_rnxObsFile, epo, rnxSat, obs);
[5890]579 obsList << obs;
580 }
581 slotNewObs(QByteArray(_opt->_roverName.c_str()), obsList);
[5883]582
[5890]583
[5883]584 if (nEpo % 10 == 0) {
[5940]585 emit progressRnxPPP(nEpo);
[5883]586 }
[7278]587
[5950]588 QCoreApplication::processEvents();
[5883]589 }
590
[5940]591 emit finishedRnxPPP();
[5927]592
[5883]593 if (BNC_CORE->mode() != t_bncCore::interactive) {
594 qApp->exit(0);
595 }
[5944]596 else {
597 BNC_CORE->stopPPP();
598 }
[5883]599}
600
[7278]601//
[5883]602////////////////////////////////////////////////////////////////////////////
603void t_pppRun::slotSetSpeed(int speed) {
604 QMutexLocker locker(&_mutex);
605 _speed = speed;
606}
[5973]607
[7278]608//
[5973]609////////////////////////////////////////////////////////////////////////////
610void t_pppRun::slotSetStopFlag() {
611 QMutexLocker locker(&_mutex);
612 _stopFlag = true;
613}
[5989]614
[7278]615//
[5989]616////////////////////////////////////////////////////////////////////////////
[5990]617QString t_pppRun::nmeaString(char strType, const t_output& output) {
[5989]618
[7278]619 double ell[3];
[5989]620 xyz2ell(output._xyzRover, ell);
621 double phiDeg = ell[0] * 180 / M_PI;
622 double lamDeg = ell[1] * 180 / M_PI;
623
[7926]624 unsigned year, month, day;
625 output._epoTime.civil_date(year, month, day);
626 double gps_utc = gnumleap(year, month, day);
627
[5989]628 char phiCh = 'N';
629 if (phiDeg < 0) {
630 phiDeg = -phiDeg;
631 phiCh = 'S';
[7278]632 }
[5989]633 char lamCh = 'E';
634 if (lamDeg < 0) {
635 lamDeg = -lamDeg;
636 lamCh = 'W';
[7278]637 }
[5989]638
[5990]639 ostringstream out;
640 out.setf(ios::fixed);
[5989]641
[5990]642 if (strType == 'R') {
643 string datestr = output._epoTime.datestr(0); // yyyymmdd
[7278]644 out << "GPRMC,"
[7926]645 << (output._epoTime - gps_utc).timestr(3,0) << ",A,"
[7278]646 << setw(2) << setfill('0') << int(phiDeg)
647 << setw(6) << setprecision(3) << setfill('0')
[5990]648 << fmod(60*phiDeg,60) << ',' << phiCh << ','
[7278]649 << setw(3) << setfill('0') << int(lamDeg)
650 << setw(6) << setprecision(3) << setfill('0')
[5990]651 << fmod(60*lamDeg,60) << ',' << lamCh << ",,,"
652 << datestr[6] << datestr[7] << datestr[4] << datestr[5]
653 << datestr[2] << datestr[3] << ",,";
654 }
655 else if (strType == 'G') {
[7278]656 out << "GPGGA,"
[7926]657 << (output._epoTime - gps_utc).timestr(2,0) << ','
[7278]658 << setw(2) << setfill('0') << int(phiDeg)
659 << setw(10) << setprecision(7) << setfill('0')
[5990]660 << fmod(60*phiDeg,60) << ',' << phiCh << ','
[7278]661 << setw(3) << setfill('0') << int(lamDeg)
662 << setw(10) << setprecision(7) << setfill('0')
663 << fmod(60*lamDeg,60) << ',' << lamCh
[5990]664 << ",1," << setw(2) << setfill('0') << output._numSat << ','
[7926]665 << setw(3) << setprecision(1) << output._hDop << ','
[5990]666 << setprecision(3) << ell[2] << ",M,0.0,M,,";
667 }
668 else {
669 return "";
670 }
[5989]671
[5990]672 QString nmStr(out.str().c_str());
[5989]673 unsigned char XOR = 0;
674 for (int ii = 0; ii < nmStr.length(); ii++) {
675 XOR ^= (unsigned char) nmStr[ii].toAscii();
676 }
677
678 return '$' + nmStr + QString("*%1\n").arg(int(XOR), 0, 16).toUpper();
679}
Note: See TracBrowser for help on using the repository browser.