source: ntrip/trunk/BNC/src/RTCM3/RTCM3coDecoder.cpp @ 8204

Last change on this file since 8204 was 8204, checked in by wiese, 21 months ago

CHANGE: #105 toAscii deprecated

File size: 27.1 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class:      RTCM3coDecoder
30 *
31 * Purpose:    RTCM3 Clock Orbit Decoder
32 *
33 * Author:     L. Mervart
34 *
35 * Created:    05-May-2008
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <stdio.h>
42#include <math.h>
43
44#include "RTCM3coDecoder.h"
45#include "bncutils.h"
46#include "bncrinex.h"
47#include "bnccore.h"
48#include "bncsettings.h"
49#include "bnctime.h"
50
51using namespace std;
52
53// Constructor
54////////////////////////////////////////////////////////////////////////////
55RTCM3coDecoder::RTCM3coDecoder(const QString& staID) {
56
57  _staID = staID;
58
59  // File Output
60  // -----------
61  bncSettings settings;
62  QString path = settings.value("corrPath").toString();
63  if (!path.isEmpty()) {
64    expandEnvVar(path);
65    if ( path.length() > 0 && path[path.length()-1] != QDir::separator() ) {
66      path += QDir::separator();
67    }
68    _fileNameSkl = path + staID;
69  }
70  _out = 0;
71
72  connect(this, SIGNAL(newOrbCorrections(QList<t_orbCorr>)),
73          BNC_CORE, SLOT(slotNewOrbCorrections(QList<t_orbCorr>)));
74
75  connect(this, SIGNAL(newClkCorrections(QList<t_clkCorr>)),
76          BNC_CORE, SLOT(slotNewClkCorrections(QList<t_clkCorr>)));
77
78  connect(this, SIGNAL(newCodeBiases(QList<t_satCodeBias>)),
79          BNC_CORE, SLOT(slotNewCodeBiases(QList<t_satCodeBias>)));
80
81  connect(this, SIGNAL(newPhaseBiases(QList<t_satPhaseBias>)),
82          BNC_CORE, SLOT(slotNewPhaseBiases(QList<t_satPhaseBias>)));
83
84  connect(this, SIGNAL(newTec(t_vTec)),
85          BNC_CORE, SLOT(slotNewTec(t_vTec)));
86
87  connect(this, SIGNAL(providerIDChanged(QString)),
88          BNC_CORE, SIGNAL(providerIDChanged(QString)));
89
90  connect(this, SIGNAL(newMessage(QByteArray,bool)),
91          BNC_CORE, SLOT(slotMessage(const QByteArray,bool)));
92
93  reset();
94
95  _providerID[0] = -1;
96  _providerID[1] = -1;
97  _providerID[2] = -1;
98}
99
100// Destructor
101////////////////////////////////////////////////////////////////////////////
102RTCM3coDecoder::~RTCM3coDecoder() {
103  delete _out;
104  _IODs.clear();
105  _orbCorrections.clear();
106  _clkCorrections.clear();
107  _lastClkCorrections.clear();
108  _codeBiases.clear();
109  _phaseBiases.clear();
110  _vTecMap.clear();
111}
112
113//
114////////////////////////////////////////////////////////////////////////////
115void RTCM3coDecoder::reset() {
116  memset(&_clkOrb,    0, sizeof(_clkOrb));
117  memset(&_codeBias,  0, sizeof(_codeBias));
118  memset(&_phaseBias, 0, sizeof(_phaseBias));
119  memset(&_vTEC,      0, sizeof(_vTEC));
120}
121
122// Reopen Output File
123////////////////////////////////////////////////////////////////////////
124void RTCM3coDecoder::reopen() {
125
126  if (!_fileNameSkl.isEmpty()) {
127
128    bncSettings settings;
129
130    QDateTime datTim = currentDateAndTimeGPS();
131
132    QString hlpStr = bncRinex::nextEpochStr(datTim,
133                                      settings.value("corrIntr").toString(), false);
134
135    QString fileNameHlp = _fileNameSkl
136      + QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0'))
137      + hlpStr + datTim.toString(".yyC");
138
139    if (_fileName == fileNameHlp) {
140      return;
141    }
142    else {
143      _fileName = fileNameHlp;
144    }
145
146    delete _out;
147    if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked) {
148      _out = new ofstream( _fileName.toLatin1().data(), ios_base::out | ios_base::app );
149    }
150    else {
151      _out = new ofstream( _fileName.toLatin1().data() );
152    }
153  }
154}
155
156//
157////////////////////////////////////////////////////////////////////////////
158t_irc RTCM3coDecoder::Decode(char* buffer, int bufLen, vector<string>& errmsg) {
159
160  errmsg.clear();
161
162  _buffer.append(QByteArray(buffer,bufLen));
163
164  t_irc retCode = failure;
165
166  while(_buffer.size()) {
167
168    struct ClockOrbit clkOrbSav;
169    struct CodeBias   codeBiasSav;
170    struct PhaseBias  phaseBiasSav;
171    struct VTEC       vTECSav;
172    memcpy(&clkOrbSav,    &_clkOrb,    sizeof(clkOrbSav)); // save state
173    memcpy(&codeBiasSav,  &_codeBias,  sizeof(codeBiasSav));
174    memcpy(&phaseBiasSav, &_phaseBias, sizeof(phaseBiasSav));
175    memcpy(&vTECSav,      &_vTEC,      sizeof(vTECSav));
176
177    int bytesused = 0;
178    GCOB_RETURN irc = GetSSR(&_clkOrb, &_codeBias, &_vTEC, &_phaseBias,
179                             _buffer.data(), _buffer.size(), &bytesused);
180
181    if      (irc <= -30) { // not enough data - restore state and exit loop
182      memcpy(&_clkOrb,    &clkOrbSav,    sizeof(clkOrbSav));
183      memcpy(&_codeBias,  &codeBiasSav,  sizeof(codeBiasSav));
184      memcpy(&_phaseBias, &phaseBiasSav, sizeof(phaseBiasSav));
185      memcpy(&_vTEC,      &vTECSav,      sizeof(vTECSav));
186      break;
187    }
188
189    else if (irc < 0) {    // error  - skip 1 byte and retry
190      reset();
191      _buffer = _buffer.mid(bytesused ? bytesused : 1);
192    }
193
194    else {                 // OK or MESSAGEFOLLOWS
195      _buffer = _buffer.mid(bytesused);
196
197      if (irc == GCOBR_OK || irc == GCOBR_MESSAGEFOLLOWS ) {
198
199        setEpochTime(); // sets _lastTime
200
201        if (_lastTime.valid()) {
202          reopen();
203          checkProviderID();
204          sendResults();
205          retCode = success;
206        }
207        else {
208          retCode = failure;
209        }
210
211        reset();
212      }
213    }
214  }
215
216  return retCode;
217}
218
219//
220////////////////////////////////////////////////////////////////////////////
221void RTCM3coDecoder::sendResults() {
222
223  // Orbit and clock corrections of all satellites
224  // ---------------------------------------------
225  for (unsigned ii = 0; ii <  CLOCKORBIT_NUMGPS
226                            + CLOCKORBIT_NUMGLONASS
227                            + CLOCKORBIT_NUMGALILEO
228                            + CLOCKORBIT_NUMQZSS
229                            + CLOCKORBIT_NUMSBAS
230                            + _clkOrb.NumberOfSat[CLOCKORBIT_SATBDS];
231    ii++) {
232    char sysCh = ' ';
233    int flag = 0;
234    if      (ii < _clkOrb.NumberOfSat[CLOCKORBIT_SATGPS]) {
235      sysCh = 'G';
236    }
237    else if (ii >= CLOCKORBIT_OFFSETGLONASS &&
238        ii < CLOCKORBIT_OFFSETGLONASS + _clkOrb.NumberOfSat[CLOCKORBIT_SATGLONASS]) {
239      sysCh = 'R';
240    }
241    else if (ii >= CLOCKORBIT_OFFSETGALILEO &&
242        ii < CLOCKORBIT_OFFSETGALILEO + _clkOrb.NumberOfSat[CLOCKORBIT_SATGALILEO]) {
243      sysCh = 'E';
244      flag = 1; // I/NAV clock has been chosen as reference clock for Galileo SSR corrections
245    }
246    else if (ii >= CLOCKORBIT_OFFSETQZSS &&
247        ii < CLOCKORBIT_OFFSETQZSS + _clkOrb.NumberOfSat[CLOCKORBIT_SATQZSS]) {
248      sysCh = 'J';
249    }
250    else if (ii >= CLOCKORBIT_OFFSETSBAS &&
251        ii < CLOCKORBIT_OFFSETSBAS + _clkOrb.NumberOfSat[CLOCKORBIT_SATSBAS]) {
252      sysCh = 'S';
253    }
254    else if (ii >= CLOCKORBIT_OFFSETBDS &&
255        ii < CLOCKORBIT_OFFSETBDS + _clkOrb.NumberOfSat[CLOCKORBIT_SATBDS]) {
256      sysCh = 'C';
257    }
258    else {
259      continue;
260    }
261    // Orbit correction
262    // ----------------
263    if ( _clkOrb.messageType == COTYPE_GPSCOMBINED     ||
264         _clkOrb.messageType == COTYPE_GLONASSCOMBINED ||
265         _clkOrb.messageType == COTYPE_GALILEOCOMBINED ||
266         _clkOrb.messageType == COTYPE_QZSSCOMBINED ||
267         _clkOrb.messageType == COTYPE_SBASCOMBINED ||
268         _clkOrb.messageType == COTYPE_BDSCOMBINED ||
269         _clkOrb.messageType == COTYPE_GPSORBIT ||
270         _clkOrb.messageType == COTYPE_GLONASSORBIT ||
271         _clkOrb.messageType == COTYPE_GALILEOORBIT ||
272         _clkOrb.messageType == COTYPE_QZSSORBIT ||
273         _clkOrb.messageType == COTYPE_SBASORBIT ||
274         _clkOrb.messageType == COTYPE_BDSORBIT ) {
275
276      t_orbCorr orbCorr;
277      orbCorr._prn.set(sysCh, _clkOrb.Sat[ii].ID, flag);
278      orbCorr._staID     = _staID.toStdString();
279      orbCorr._iod       = _clkOrb.Sat[ii].IOD;
280      orbCorr._time      = _lastTime;
281      orbCorr._updateInt = _clkOrb.UpdateInterval;
282      orbCorr._system    = sysCh;
283      orbCorr._xr[0]     = _clkOrb.Sat[ii].Orbit.DeltaRadial;
284      orbCorr._xr[1]     = _clkOrb.Sat[ii].Orbit.DeltaAlongTrack;
285      orbCorr._xr[2]     = _clkOrb.Sat[ii].Orbit.DeltaCrossTrack;
286      orbCorr._dotXr[0]  = _clkOrb.Sat[ii].Orbit.DotDeltaRadial;
287      orbCorr._dotXr[1]  = _clkOrb.Sat[ii].Orbit.DotDeltaAlongTrack;
288      orbCorr._dotXr[2]  = _clkOrb.Sat[ii].Orbit.DotDeltaCrossTrack;
289
290      _orbCorrections[_lastTime].append(orbCorr);
291
292      _IODs[orbCorr._prn] = _clkOrb.Sat[ii].IOD;
293    }
294
295    // Clock Corrections
296    // -----------------
297    if ( _clkOrb.messageType == COTYPE_GPSCOMBINED     ||
298         _clkOrb.messageType == COTYPE_GLONASSCOMBINED ||
299         _clkOrb.messageType == COTYPE_GALILEOCOMBINED ||
300         _clkOrb.messageType == COTYPE_QZSSCOMBINED ||
301         _clkOrb.messageType == COTYPE_SBASCOMBINED ||
302         _clkOrb.messageType == COTYPE_BDSCOMBINED ||
303         _clkOrb.messageType == COTYPE_GPSCLOCK ||
304         _clkOrb.messageType == COTYPE_GLONASSCLOCK ||
305         _clkOrb.messageType == COTYPE_GALILEOCLOCK ||
306         _clkOrb.messageType == COTYPE_QZSSCLOCK ||
307         _clkOrb.messageType == COTYPE_SBASCLOCK ||
308         _clkOrb.messageType == COTYPE_BDSCLOCK) {
309
310      t_clkCorr clkCorr;
311      clkCorr._prn.set(sysCh, _clkOrb.Sat[ii].ID, flag);
312
313      clkCorr._staID      = _staID.toStdString();
314      clkCorr._time       = _lastTime;
315      clkCorr._updateInt  = _clkOrb.UpdateInterval;
316      clkCorr._dClk       = _clkOrb.Sat[ii].Clock.DeltaA0 / t_CST::c;
317      clkCorr._dotDClk    = _clkOrb.Sat[ii].Clock.DeltaA1 / t_CST::c;
318      clkCorr._dotDotDClk = _clkOrb.Sat[ii].Clock.DeltaA2 / t_CST::c;
319
320      _lastClkCorrections[clkCorr._prn] = clkCorr;
321
322      if (_IODs.contains(clkCorr._prn)) {
323        clkCorr._iod = _IODs[clkCorr._prn];
324        _clkCorrections[_lastTime].append(clkCorr);
325      }
326    }
327
328    // High-Resolution Clocks
329    // ----------------------
330    if ( _clkOrb.messageType == COTYPE_GPSHR     ||
331         _clkOrb.messageType == COTYPE_GLONASSHR ||
332         _clkOrb.messageType == COTYPE_GALILEOHR ||
333         _clkOrb.messageType == COTYPE_QZSSHR ||
334         _clkOrb.messageType == COTYPE_SBASHR ||
335         _clkOrb.messageType == COTYPE_BDSHR) {
336      t_prn prn(sysCh, _clkOrb.Sat[ii].ID, flag);
337      if (_lastClkCorrections.contains(prn)) {
338        t_clkCorr clkCorr;
339        clkCorr            = _lastClkCorrections[prn];
340        clkCorr._time      = _lastTime;
341        clkCorr._updateInt = _clkOrb.UpdateInterval;
342        clkCorr._dClk     += _clkOrb.Sat[ii].hrclock / t_CST::c;
343        if (_IODs.contains(clkCorr._prn)) {
344          clkCorr._iod = _IODs[clkCorr._prn];
345          _clkCorrections[_lastTime].push_back(clkCorr);
346        }
347      }
348    }
349  }
350
351  // Code Biases
352  // -----------
353  for (unsigned ii = 0; ii <  CLOCKORBIT_NUMGPS
354                            + CLOCKORBIT_NUMGLONASS
355                            + CLOCKORBIT_NUMGALILEO
356                            + CLOCKORBIT_NUMQZSS
357                            + CLOCKORBIT_NUMSBAS
358                            + _codeBias.NumberOfSat[CLOCKORBIT_SATBDS];
359    ii++) {
360    char sysCh = ' ';
361    if      (ii < _codeBias.NumberOfSat[CLOCKORBIT_SATGPS]) {
362      sysCh = 'G';
363    }
364    else if (ii >= CLOCKORBIT_OFFSETGLONASS &&
365        ii < CLOCKORBIT_OFFSETGLONASS + _codeBias.NumberOfSat[CLOCKORBIT_SATGLONASS]) {
366      sysCh = 'R';
367    }
368    else if (ii >= CLOCKORBIT_OFFSETGALILEO &&
369        ii < CLOCKORBIT_OFFSETGALILEO + _codeBias.NumberOfSat[CLOCKORBIT_SATGALILEO]) {
370      sysCh = 'E';
371    }
372    else if (ii >= CLOCKORBIT_OFFSETQZSS &&
373        ii < CLOCKORBIT_OFFSETQZSS + _codeBias.NumberOfSat[CLOCKORBIT_SATQZSS]) {
374      sysCh = 'J';
375    }
376    else if (ii >= CLOCKORBIT_OFFSETSBAS &&
377        ii < CLOCKORBIT_OFFSETSBAS + _codeBias.NumberOfSat[CLOCKORBIT_SATSBAS]) {
378      sysCh = 'S';
379    }
380    else if (ii >= CLOCKORBIT_OFFSETBDS &&
381        ii < CLOCKORBIT_OFFSETBDS + _codeBias.NumberOfSat[CLOCKORBIT_SATBDS]) {
382      sysCh = 'C';
383    }
384    else {
385      continue;
386    }
387    t_satCodeBias satCodeBias;
388    satCodeBias._prn.set(sysCh, _codeBias.Sat[ii].ID);
389    satCodeBias._staID     = _staID.toStdString();
390    satCodeBias._time      = _lastTime;
391    satCodeBias._updateInt = _codeBias.UpdateInterval;
392    for (unsigned jj = 0; jj < _codeBias.Sat[ii].NumberOfCodeBiases; jj++) {
393      const CodeBias::BiasSat::CodeBiasEntry& biasEntry = _codeBias.Sat[ii].Biases[jj];
394      t_frqCodeBias frqCodeBias;
395      frqCodeBias._rnxType2ch.assign(codeTypeToRnxType(sysCh, biasEntry.Type));
396      frqCodeBias._value      = biasEntry.Bias;
397      if (!frqCodeBias._rnxType2ch.empty()) {
398        satCodeBias._bias.push_back(frqCodeBias);
399      }
400    }
401    _codeBiases[_lastTime].append(satCodeBias);
402  }
403
404  // Phase Biases
405  // -----------
406  for (unsigned ii = 0; ii <  CLOCKORBIT_NUMGPS
407                            + CLOCKORBIT_NUMGLONASS
408                            + CLOCKORBIT_NUMGALILEO
409                            + CLOCKORBIT_NUMQZSS
410                            + CLOCKORBIT_NUMSBAS
411                            + _phaseBias.NumberOfSat[CLOCKORBIT_SATBDS];
412    ii++) {
413    char sysCh = ' ';
414    if      (ii < _phaseBias.NumberOfSat[CLOCKORBIT_SATGPS]) {
415      sysCh = 'G';
416    }
417    else if (ii >= CLOCKORBIT_OFFSETGLONASS &&
418        ii < CLOCKORBIT_OFFSETGLONASS + _phaseBias.NumberOfSat[CLOCKORBIT_SATGLONASS]) {
419      sysCh = 'R';
420    }
421    else if (ii >= CLOCKORBIT_OFFSETGALILEO &&
422        ii < CLOCKORBIT_OFFSETGALILEO + _phaseBias.NumberOfSat[CLOCKORBIT_SATGALILEO]) {
423      sysCh = 'E';
424    }
425    else if (ii >= CLOCKORBIT_OFFSETQZSS &&
426        ii < CLOCKORBIT_OFFSETQZSS + _phaseBias.NumberOfSat[CLOCKORBIT_SATQZSS]) {
427      sysCh = 'J';
428    }
429    else if (ii >= CLOCKORBIT_OFFSETSBAS &&
430        ii < CLOCKORBIT_OFFSETSBAS + _phaseBias.NumberOfSat[CLOCKORBIT_SATSBAS]) {
431      sysCh = 'S';
432    }
433    else if (ii >= CLOCKORBIT_OFFSETBDS &&
434        ii < CLOCKORBIT_OFFSETBDS + _phaseBias.NumberOfSat[CLOCKORBIT_SATBDS]) {
435      sysCh = 'C';
436    }
437    else {
438      continue;
439    }
440    t_satPhaseBias satPhaseBias;
441    satPhaseBias._prn.set(sysCh, _phaseBias.Sat[ii].ID);
442    satPhaseBias._staID      = _staID.toStdString();
443    satPhaseBias._time       = _lastTime;
444    satPhaseBias._updateInt  = _phaseBias.UpdateInterval;
445    satPhaseBias._dispBiasConstistInd = _phaseBias.DispersiveBiasConsistencyIndicator;
446    satPhaseBias._MWConsistInd        = _phaseBias.MWConsistencyIndicator;
447    satPhaseBias._yawDeg     = _phaseBias.Sat[ii].YawAngle * 180.0 / M_PI;
448    satPhaseBias._yawDegRate = _phaseBias.Sat[ii].YawRate * 180.0 / M_PI;
449    for (unsigned jj = 0; jj < _phaseBias.Sat[ii].NumberOfPhaseBiases; jj++) {
450      const PhaseBias::PhaseBiasSat::PhaseBiasEntry& biasEntry = _phaseBias.Sat[ii].Biases[jj];
451      t_frqPhaseBias frqPhaseBias;
452      frqPhaseBias._rnxType2ch.assign(codeTypeToRnxType(sysCh, biasEntry.Type));
453      frqPhaseBias._value                = biasEntry.Bias;
454      frqPhaseBias._fixIndicator         = biasEntry.SignalIntegerIndicator;
455      frqPhaseBias._fixWideLaneIndicator = biasEntry.SignalsWideLaneIntegerIndicator;
456      frqPhaseBias._jumpCounter          = biasEntry.SignalDiscontinuityCounter;
457      if (!frqPhaseBias._rnxType2ch.empty()) {
458        satPhaseBias._bias.push_back(frqPhaseBias);
459      }
460    }
461    _phaseBiases[_lastTime].append(satPhaseBias);
462  }
463
464  // Ionospheric Model
465  // -----------------
466  if (_vTEC.NumLayers > 0) {
467    _vTecMap[_lastTime]._time  = _lastTime;
468    _vTecMap[_lastTime]._updateInt =  _vTEC.UpdateInterval;
469    _vTecMap[_lastTime]._staID = _staID.toStdString();
470    for (unsigned ii = 0; ii < _vTEC.NumLayers; ii++) {
471      const VTEC::IonoLayers& ionoLayer = _vTEC.Layers[ii];
472      t_vTecLayer layer;
473      layer._height = ionoLayer.Height;
474      layer._C.ReSize(ionoLayer.Degree+1, ionoLayer.Order+1);
475      layer._S.ReSize(ionoLayer.Degree+1, ionoLayer.Order+1);
476      for (unsigned iDeg = 0; iDeg <= ionoLayer.Degree; iDeg++) {
477        for (unsigned iOrd = 0; iOrd <= ionoLayer.Order; iOrd++) {
478          layer._C[iDeg][iOrd] = ionoLayer.Cosinus[iDeg][iOrd];
479          layer._S[iDeg][iOrd] = ionoLayer.Sinus[iDeg][iOrd];
480        }
481      }
482      _vTecMap[_lastTime]._layers.push_back(layer);
483    }
484  }
485
486  // Dump all older epochs
487  // ---------------------
488  QMutableMapIterator<bncTime, QList<t_orbCorr> > itOrb(_orbCorrections);
489  while (itOrb.hasNext()) {
490    itOrb.next();
491    if (itOrb.key() < _lastTime) {
492      emit newOrbCorrections(itOrb.value());
493      t_orbCorr::writeEpoch(_out, itOrb.value());
494      itOrb.remove();
495    }
496  }
497  QMutableMapIterator<bncTime, QList<t_clkCorr> > itClk(_clkCorrections);
498  while (itClk.hasNext()) {
499    itClk.next();
500    if (itClk.key() < _lastTime) {
501      emit newClkCorrections(itClk.value());
502      t_clkCorr::writeEpoch(_out, itClk.value());
503      itClk.remove();
504    }
505  }
506  QMutableMapIterator<bncTime, QList<t_satCodeBias> > itCB(_codeBiases);
507  while (itCB.hasNext()) {
508    itCB.next();
509    if (itCB.key() < _lastTime) {
510      emit newCodeBiases(itCB.value());
511      t_satCodeBias::writeEpoch(_out, itCB.value());
512      itCB.remove();
513    }
514  }
515  QMutableMapIterator<bncTime, QList<t_satPhaseBias> > itPB(_phaseBiases);
516  while (itPB.hasNext()) {
517    itPB.next();
518    if (itPB.key() < _lastTime) {
519      emit newPhaseBiases(itPB.value());
520      t_satPhaseBias::writeEpoch(_out, itPB.value());
521      itPB.remove();
522    }
523  }
524  QMutableMapIterator<bncTime, t_vTec> itTec(_vTecMap);
525  while (itTec.hasNext()) {
526    itTec.next();
527    if (itTec.key() < _lastTime) {
528      emit newTec(itTec.value());
529      t_vTec::write(_out, itTec.value());
530      itTec.remove();
531    }
532  }
533}
534
535//
536////////////////////////////////////////////////////////////////////////////
537void RTCM3coDecoder::checkProviderID() {
538
539  if (_clkOrb.SSRProviderID == 0 && _clkOrb.SSRSolutionID == 0 && _clkOrb.SSRIOD == 0) {
540    return;
541  }
542
543  int newProviderID[3];
544  newProviderID[0] = _clkOrb.SSRProviderID;
545  newProviderID[1] = _clkOrb.SSRSolutionID;
546  newProviderID[2] = _clkOrb.SSRIOD;
547
548  bool alreadySet = false;
549  bool different  = false;
550
551  for (unsigned ii = 0; ii < 3; ii++) {
552    if (_providerID[ii] != -1) {
553      alreadySet = true;
554    }
555    if (_providerID[ii] != newProviderID[ii]) {
556      different = true;
557    }
558    _providerID[ii] = newProviderID[ii];
559  }
560
561  if (alreadySet && different) {
562    emit newMessage("RTCM3coDecoder: Provider Changed: " + _staID.toLatin1(), true);
563    emit providerIDChanged(_staID);
564  }
565}
566
567//
568////////////////////////////////////////////////////////////////////////////
569void RTCM3coDecoder::setEpochTime() {
570
571  _lastTime.reset();
572
573  double epoSecGPS  = -1.0;
574  double epoSecGlo  = -1.0;
575  double epoSecGal  = -1.0;
576  double epoSecQzss = -1.0;
577  double epoSecSbas = -1.0;
578  double epoSecBds  = -1.0;
579  if      (_clkOrb.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
580    epoSecGPS = _clkOrb.EpochTime[CLOCKORBIT_SATGPS];        // 0 .. 604799 s
581  }
582  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
583    epoSecGPS = _codeBias.EpochTime[CLOCKORBIT_SATGPS];      // 0 .. 604799 s
584  }
585  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
586    epoSecGPS = _phaseBias.EpochTime[CLOCKORBIT_SATGPS];     // 0 .. 604799 s
587  }
588  else if (_vTEC.NumLayers > 0) {
589    epoSecGPS = _vTEC.EpochTime;                             // 0 .. 604799 s
590  }
591  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
592    epoSecGlo = _clkOrb.EpochTime[CLOCKORBIT_SATGLONASS];    // 0 .. 86399 s
593  }
594  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
595    epoSecGlo = _codeBias.EpochTime[CLOCKORBIT_SATGLONASS];  // 0 .. 86399 s
596  }
597  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
598    epoSecGlo = _phaseBias.EpochTime[CLOCKORBIT_SATGLONASS]; // 0 .. 86399 s
599  }
600  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
601    epoSecGal = _clkOrb.EpochTime[CLOCKORBIT_SATGALILEO];
602  }
603  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
604    epoSecGal = _codeBias.EpochTime[CLOCKORBIT_SATGALILEO];
605  }
606  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
607    epoSecGal = _phaseBias.EpochTime[CLOCKORBIT_SATGALILEO];
608  }
609  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
610    epoSecQzss = _clkOrb.EpochTime[CLOCKORBIT_SATQZSS];
611  }
612  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
613    epoSecQzss = _codeBias.EpochTime[CLOCKORBIT_SATQZSS];
614  }
615  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
616    epoSecQzss = _phaseBias.EpochTime[CLOCKORBIT_SATQZSS];
617  }
618  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
619    epoSecSbas = _clkOrb.EpochTime[CLOCKORBIT_SATSBAS];
620  }
621  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
622    epoSecSbas = _codeBias.EpochTime[CLOCKORBIT_SATSBAS];
623  }
624  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
625    epoSecSbas = _phaseBias.EpochTime[CLOCKORBIT_SATSBAS];
626  }
627  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
628    epoSecBds = _clkOrb.EpochTime[CLOCKORBIT_SATBDS];
629  }
630  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
631    epoSecBds = _codeBias.EpochTime[CLOCKORBIT_SATBDS];
632  }
633  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
634    epoSecBds = _phaseBias.EpochTime[CLOCKORBIT_SATBDS];
635  }
636
637  // Retrieve current time
638  // ---------------------
639  int    currentWeek = 0;
640  double currentSec  = 0.0;
641  currentGPSWeeks(currentWeek, currentSec);
642  bncTime currentTime(currentWeek, currentSec);
643
644  // Set _lastTime close to currentTime
645  // ----------------------------------
646  if      (epoSecGPS != -1) {
647    _lastTime.set(currentWeek, epoSecGPS);
648  }
649  else if (epoSecGlo != -1) {
650    QDate date = dateAndTimeFromGPSweek(currentTime.gpsw(), currentTime.gpssec()).date();
651    epoSecGlo = epoSecGlo - 3 * 3600 + gnumleap(date.year(), date.month(), date.day());
652    _lastTime.set(currentWeek, epoSecGlo);
653  }
654  else if (epoSecGal != -1) {
655    _lastTime.set(currentWeek, epoSecGal);
656  }
657  else if (epoSecQzss != -1) {
658    _lastTime.set(currentWeek, epoSecQzss);
659  }
660  else if (epoSecSbas != -1) {
661    _lastTime.set(currentWeek, epoSecSbas);
662  }
663  else if (epoSecBds != -1) {
664    epoSecBds += 14.0;
665    if (epoSecBds > 604800.0) {
666      epoSecBds -= 7.0*24.0*60.0*60.0;
667    }
668    _lastTime.set(currentWeek, epoSecBds);
669  }
670
671  if (_lastTime.valid()) {
672    double maxDiff = 12 * 3600.0;
673    while (_lastTime < currentTime - maxDiff) {
674      _lastTime = _lastTime + maxDiff;
675    }
676    while (_lastTime > currentTime + maxDiff) {
677      _lastTime = _lastTime - maxDiff;
678    }
679  }
680}
681
682//
683////////////////////////////////////////////////////////////////////////////
684string RTCM3coDecoder::codeTypeToRnxType(char system, CodeType type) const {
685  if      (system == 'G') {
686    switch (type) {
687      case CODETYPEGPS_L1_CA:         return "1C";
688      case CODETYPEGPS_L1_P:          return "1P";
689      case CODETYPEGPS_L1_Z:          return "1W";
690      //case CODETYPEGPS_L1_Y:          return "1Y";
691      //case CODETYPEGPS_L1_M:          return "1M";
692      case CODETYPEGPS_L2_CA:         return "2C";
693      case CODETYPEGPS_SEMI_CODELESS: return "2D";
694      case CODETYPEGPS_L2_CM:         return "2S";
695      case CODETYPEGPS_L2_CL:         return "2L";
696      case CODETYPEGPS_L2_CML:        return "2X";
697      case CODETYPEGPS_L2_P:          return "2P";
698      case CODETYPEGPS_L2_Z:          return "2W";
699      //case CODETYPEGPS_L2_Y:          return "2Y";
700      //case CODETYPEGPS_L2_M:          return "2M";
701      case CODETYPEGPS_L5_I:          return "5I";
702      case CODETYPEGPS_L5_Q:          return "5Q";
703      case CODETYPEGPS_L5_IQ:         return "5X";
704      case CODETYPEGPS_L1C_D:         return "1S";
705      case CODETYPEGPS_L1C_P:         return "1L";
706      case CODETYPEGPS_L1C_DP:        return "1X";
707      default: return "";
708    }
709  }
710  else if (system == 'R') {
711    switch (type) {
712      case CODETYPEGLONASS_L1_CA:     return "1C";
713      case CODETYPEGLONASS_L1_P:      return "1P";
714      case CODETYPEGLONASS_L2_CA:     return "2C";
715      case CODETYPEGLONASS_L2_P:      return "2P";
716      case CODETYPEGLONASS_L3_I:      return "3I";
717      case CODETYPEGLONASS_L3_Q:      return "3Q";
718      case CODETYPEGLONASS_L3_IQ:     return "3X";
719      default: return "";
720    }
721  }
722  else if (system == 'E') {
723    switch (type) {
724      case CODETYPEGALILEO_E1_A:       return "1A";
725      case CODETYPEGALILEO_E1_B:       return "1B";
726      case CODETYPEGALILEO_E1_C:       return "1C";
727      case CODETYPEGALILEO_E1_BC:      return "1X";
728      case CODETYPEGALILEO_E1_ABC:     return "1Z";
729      case CODETYPEGALILEO_E5A_I:      return "5I";
730      case CODETYPEGALILEO_E5A_Q:      return "5Q";
731      case CODETYPEGALILEO_E5A_IQ:     return "5X";
732      case CODETYPEGALILEO_E5B_I:      return "7I";
733      case CODETYPEGALILEO_E5B_Q:      return "7Q";
734      case CODETYPEGALILEO_E5B_IQ:     return "7X";
735      case CODETYPEGALILEO_E5_I:       return "8I";
736      case CODETYPEGALILEO_E5_Q:       return "8Q";
737      case CODETYPEGALILEO_E5_IQ:      return "8X";
738      case CODETYPEGALILEO_E6_A:       return "6A";
739      case CODETYPEGALILEO_E6_B:       return "6B";
740      case CODETYPEGALILEO_E6_C:       return "6C";
741      case CODETYPEGALILEO_E6_BC:      return "6X";
742      case CODETYPEGALILEO_E6_ABC:     return "6Z";
743      default: return "";
744    }
745  }
746  else if (system == 'J') {
747    switch (type) {
748      case CODETYPEQZSS_L1_CA:         return "1C";
749      case CODETYPEQZSS_L1C_D:         return "1S";
750      case CODETYPEQZSS_L1C_P:         return "1L";
751      case CODETYPEQZSS_L1C_DP:        return "1X";
752      case CODETYPEQZSS_L2C_M:         return "2S";
753      case CODETYPEQZSS_L2C_L:         return "2L";
754      case CODETYPEQZSS_L2C_ML:        return "2X";
755      case CODETYPEQZSS_L5_I:          return "5I";
756      case CODETYPEQZSS_L5_Q:          return "5Q";
757      case CODETYPEQZSS_L5_IQ:         return "5X";
758      case CODETYPEQZSS_LEX_S:         return "6S";
759      case CODETYPEQZSS_LEX_L:         return "6L";
760      case CODETYPEQZSS_LEX_SL:        return "6X";
761      default: return "";
762    }
763  }
764  else if (system == 'S') {
765    switch (type) {
766      case CODETYPE_SBAS_L1_CA:       return "1C";
767      case CODETYPE_SBAS_L5_I:        return "5I";
768      case CODETYPE_SBAS_L5_Q:        return "5Q";
769      case CODETYPE_SBAS_L5_IQ:       return "5X";
770      default: return "";
771    }
772  }
773  else if (system == 'C') {
774    switch (type) {
775      case CODETYPE_BDS_B1_I:         return "2I";
776      case CODETYPE_BDS_B1_Q:         return "2Q";
777      case CODETYPE_BDS_B1_IQ:        return "2X";
778      case CODETYPE_BDS_B2_I:         return "7I";
779      case CODETYPE_BDS_B2_Q:         return "7Q";
780      case CODETYPE_BDS_B2_IQ:        return "7X";
781      case CODETYPE_BDS_B3_I:         return "6I";
782      case CODETYPE_BDS_B3_Q:         return "6Q";
783      case CODETYPE_BDS_B3_IQ:        return "6X";
784      default: return "";
785    }
786  }
787  return "";
788};
Note: See TracBrowser for help on using the repository browser.