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

Last change on this file since 8794 was 8794, checked in by stuerze, 10 months ago

minor changes for correct marker and receiver numbers in PPP logfile names (rinex v3 style)

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