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

Last change on this file since 8844 was 8844, checked in by stuerze, 13 months ago

Harmonization of RTCM3 Signal ID Mapping and RTCM SSR Signal and Tracking Mode Identifiers

File size: 27.7 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      clkCorr._staID      = _staID.toStdString();
313      clkCorr._time       = _lastTime;
314      clkCorr._updateInt  = _clkOrb.UpdateInterval;
315      clkCorr._dClk       = _clkOrb.Sat[ii].Clock.DeltaA0 / t_CST::c;
316      clkCorr._dotDClk    = _clkOrb.Sat[ii].Clock.DeltaA1 / t_CST::c;
317      clkCorr._dotDotDClk = _clkOrb.Sat[ii].Clock.DeltaA2 / t_CST::c;
318
319      _lastClkCorrections[clkCorr._prn] = clkCorr;
320
321      if (_IODs.contains(clkCorr._prn)) {
322        clkCorr._iod = _IODs[clkCorr._prn];
323        _clkCorrections[_lastTime].append(clkCorr);
324      }
325    }
326
327    // High-Resolution Clocks
328    // ----------------------
329    if ( _clkOrb.messageType == COTYPE_GPSHR     ||
330         _clkOrb.messageType == COTYPE_GLONASSHR ||
331         _clkOrb.messageType == COTYPE_GALILEOHR ||
332         _clkOrb.messageType == COTYPE_QZSSHR ||
333         _clkOrb.messageType == COTYPE_SBASHR ||
334         _clkOrb.messageType == COTYPE_BDSHR) {
335      t_prn prn(sysCh, _clkOrb.Sat[ii].ID, flag);
336      if (_lastClkCorrections.contains(prn)) {
337        t_clkCorr clkCorr;
338        clkCorr            = _lastClkCorrections[prn];
339        clkCorr._time      = _lastTime;
340        clkCorr._updateInt = _clkOrb.UpdateInterval;
341        clkCorr._dClk     += _clkOrb.Sat[ii].hrclock / t_CST::c;
342        if (_IODs.contains(clkCorr._prn)) {
343          clkCorr._iod = _IODs[clkCorr._prn];
344          _clkCorrections[_lastTime].push_back(clkCorr);
345        }
346      }
347    }
348  }
349
350  // Code Biases
351  // -----------
352  for (unsigned ii = 0; ii <  CLOCKORBIT_NUMGPS
353                            + CLOCKORBIT_NUMGLONASS
354                            + CLOCKORBIT_NUMGALILEO
355                            + CLOCKORBIT_NUMQZSS
356                            + CLOCKORBIT_NUMSBAS
357                            + _codeBias.NumberOfSat[CLOCKORBIT_SATBDS];
358    ii++) {
359    char sysCh = ' ';
360    if      (ii < _codeBias.NumberOfSat[CLOCKORBIT_SATGPS]) {
361      sysCh = 'G';
362    }
363    else if (ii >= CLOCKORBIT_OFFSETGLONASS &&
364        ii < CLOCKORBIT_OFFSETGLONASS + _codeBias.NumberOfSat[CLOCKORBIT_SATGLONASS]) {
365      sysCh = 'R';
366    }
367    else if (ii >= CLOCKORBIT_OFFSETGALILEO &&
368        ii < CLOCKORBIT_OFFSETGALILEO + _codeBias.NumberOfSat[CLOCKORBIT_SATGALILEO]) {
369      sysCh = 'E';
370    }
371    else if (ii >= CLOCKORBIT_OFFSETQZSS &&
372        ii < CLOCKORBIT_OFFSETQZSS + _codeBias.NumberOfSat[CLOCKORBIT_SATQZSS]) {
373      sysCh = 'J';
374    }
375    else if (ii >= CLOCKORBIT_OFFSETSBAS &&
376        ii < CLOCKORBIT_OFFSETSBAS + _codeBias.NumberOfSat[CLOCKORBIT_SATSBAS]) {
377      sysCh = 'S';
378    }
379    else if (ii >= CLOCKORBIT_OFFSETBDS &&
380        ii < CLOCKORBIT_OFFSETBDS + _codeBias.NumberOfSat[CLOCKORBIT_SATBDS]) {
381      sysCh = 'C';
382    }
383    else {
384      continue;
385    }
386    t_satCodeBias satCodeBias;
387    satCodeBias._prn.set(sysCh, _codeBias.Sat[ii].ID);
388    satCodeBias._staID     = _staID.toStdString();
389    satCodeBias._time      = _lastTime;
390    satCodeBias._updateInt = _codeBias.UpdateInterval;
391    for (unsigned jj = 0; jj < _codeBias.Sat[ii].NumberOfCodeBiases; jj++) {
392      const CodeBias::BiasSat::CodeBiasEntry& biasEntry = _codeBias.Sat[ii].Biases[jj];
393      t_frqCodeBias frqCodeBias;
394      frqCodeBias._rnxType2ch.assign(codeTypeToRnxType(sysCh, biasEntry.Type));
395      frqCodeBias._value      = biasEntry.Bias;
396      if (!frqCodeBias._rnxType2ch.empty()) {
397        satCodeBias._bias.push_back(frqCodeBias);
398      }
399    }
400    _codeBiases[_lastTime].append(satCodeBias);
401  }
402
403  // Phase Biases
404  // -----------
405  for (unsigned ii = 0; ii <  CLOCKORBIT_NUMGPS
406                            + CLOCKORBIT_NUMGLONASS
407                            + CLOCKORBIT_NUMGALILEO
408                            + CLOCKORBIT_NUMQZSS
409                            + CLOCKORBIT_NUMSBAS
410                            + _phaseBias.NumberOfSat[CLOCKORBIT_SATBDS];
411    ii++) {
412    char sysCh = ' ';
413    if      (ii < _phaseBias.NumberOfSat[CLOCKORBIT_SATGPS]) {
414      sysCh = 'G';
415    }
416    else if (ii >= CLOCKORBIT_OFFSETGLONASS &&
417        ii < CLOCKORBIT_OFFSETGLONASS + _phaseBias.NumberOfSat[CLOCKORBIT_SATGLONASS]) {
418      sysCh = 'R';
419    }
420    else if (ii >= CLOCKORBIT_OFFSETGALILEO &&
421        ii < CLOCKORBIT_OFFSETGALILEO + _phaseBias.NumberOfSat[CLOCKORBIT_SATGALILEO]) {
422      sysCh = 'E';
423    }
424    else if (ii >= CLOCKORBIT_OFFSETQZSS &&
425        ii < CLOCKORBIT_OFFSETQZSS + _phaseBias.NumberOfSat[CLOCKORBIT_SATQZSS]) {
426      sysCh = 'J';
427    }
428    else if (ii >= CLOCKORBIT_OFFSETSBAS &&
429        ii < CLOCKORBIT_OFFSETSBAS + _phaseBias.NumberOfSat[CLOCKORBIT_SATSBAS]) {
430      sysCh = 'S';
431    }
432    else if (ii >= CLOCKORBIT_OFFSETBDS &&
433        ii < CLOCKORBIT_OFFSETBDS + _phaseBias.NumberOfSat[CLOCKORBIT_SATBDS]) {
434      sysCh = 'C';
435    }
436    else {
437      continue;
438    }
439    t_satPhaseBias satPhaseBias;
440    satPhaseBias._prn.set(sysCh, _phaseBias.Sat[ii].ID);
441    satPhaseBias._staID      = _staID.toStdString();
442    satPhaseBias._time       = _lastTime;
443    satPhaseBias._updateInt  = _phaseBias.UpdateInterval;
444    satPhaseBias._dispBiasConstistInd = _phaseBias.DispersiveBiasConsistencyIndicator;
445    satPhaseBias._MWConsistInd        = _phaseBias.MWConsistencyIndicator;
446    satPhaseBias._yaw     = _phaseBias.Sat[ii].YawAngle;
447    satPhaseBias._yawRate = _phaseBias.Sat[ii].YawRate;
448    for (unsigned jj = 0; jj < _phaseBias.Sat[ii].NumberOfPhaseBiases; jj++) {
449      const PhaseBias::PhaseBiasSat::PhaseBiasEntry& biasEntry = _phaseBias.Sat[ii].Biases[jj];
450      t_frqPhaseBias frqPhaseBias;
451      frqPhaseBias._rnxType2ch.assign(codeTypeToRnxType(sysCh, biasEntry.Type));
452      frqPhaseBias._value                = biasEntry.Bias;
453      frqPhaseBias._fixIndicator         = biasEntry.SignalIntegerIndicator;
454      frqPhaseBias._fixWideLaneIndicator = biasEntry.SignalsWideLaneIntegerIndicator;
455      frqPhaseBias._jumpCounter          = biasEntry.SignalDiscontinuityCounter;
456      if (!frqPhaseBias._rnxType2ch.empty()) {
457        satPhaseBias._bias.push_back(frqPhaseBias);
458      }
459    }
460    _phaseBiases[_lastTime].append(satPhaseBias);
461  }
462
463  // Ionospheric Model
464  // -----------------
465  if (_vTEC.NumLayers > 0) {
466    _vTecMap[_lastTime]._time  = _lastTime;
467    _vTecMap[_lastTime]._updateInt =  _vTEC.UpdateInterval;
468    _vTecMap[_lastTime]._staID = _staID.toStdString();
469    for (unsigned ii = 0; ii < _vTEC.NumLayers; ii++) {
470      const VTEC::IonoLayers& ionoLayer = _vTEC.Layers[ii];
471      t_vTecLayer layer;
472      layer._height = ionoLayer.Height;
473      layer._C.ReSize(ionoLayer.Degree+1, ionoLayer.Order+1);
474      layer._S.ReSize(ionoLayer.Degree+1, ionoLayer.Order+1);
475      for (unsigned iDeg = 0; iDeg <= ionoLayer.Degree; iDeg++) {
476        for (unsigned iOrd = 0; iOrd <= ionoLayer.Order; iOrd++) {
477          layer._C[iDeg][iOrd] = ionoLayer.Cosinus[iDeg][iOrd];
478          layer._S[iDeg][iOrd] = ionoLayer.Sinus[iDeg][iOrd];
479        }
480      }
481      _vTecMap[_lastTime]._layers.push_back(layer);
482    }
483  }
484
485  // Dump all older epochs
486  // ---------------------
487  QMutableMapIterator<bncTime, QList<t_orbCorr> > itOrb(_orbCorrections);
488  while (itOrb.hasNext()) {
489    itOrb.next();
490    if (itOrb.key() < _lastTime) {
491      emit newOrbCorrections(itOrb.value());
492      t_orbCorr::writeEpoch(_out, itOrb.value());
493      itOrb.remove();
494    }
495  }
496  QMutableMapIterator<bncTime, QList<t_clkCorr> > itClk(_clkCorrections);
497  while (itClk.hasNext()) {
498    itClk.next();
499    if (itClk.key() < _lastTime) {
500      emit newClkCorrections(itClk.value());
501      t_clkCorr::writeEpoch(_out, itClk.value());
502      itClk.remove();
503    }
504  }
505  QMutableMapIterator<bncTime, QList<t_satCodeBias> > itCB(_codeBiases);
506  while (itCB.hasNext()) {
507    itCB.next();
508    if (itCB.key() < _lastTime) {
509      emit newCodeBiases(itCB.value());
510      t_satCodeBias::writeEpoch(_out, itCB.value());
511      itCB.remove();
512    }
513  }
514  QMutableMapIterator<bncTime, QList<t_satPhaseBias> > itPB(_phaseBiases);
515  while (itPB.hasNext()) {
516    itPB.next();
517    if (itPB.key() < _lastTime) {
518      emit newPhaseBiases(itPB.value());
519      t_satPhaseBias::writeEpoch(_out, itPB.value());
520      itPB.remove();
521    }
522  }
523  QMutableMapIterator<bncTime, t_vTec> itTec(_vTecMap);
524  while (itTec.hasNext()) {
525    itTec.next();
526    if (itTec.key() < _lastTime) {
527      emit newTec(itTec.value());
528      t_vTec::write(_out, itTec.value());
529      itTec.remove();
530    }
531  }
532}
533
534//
535////////////////////////////////////////////////////////////////////////////
536void RTCM3coDecoder::checkProviderID() {
537
538  if (_clkOrb.SSRProviderID == 0 && _clkOrb.SSRSolutionID == 0 && _clkOrb.SSRIOD == 0) {
539    return;
540  }
541
542  int newProviderID[3];
543  newProviderID[0] = _clkOrb.SSRProviderID;
544  newProviderID[1] = _clkOrb.SSRSolutionID;
545  newProviderID[2] = _clkOrb.SSRIOD;
546
547  bool alreadySet = false;
548  bool different  = false;
549
550  for (unsigned ii = 0; ii < 3; ii++) {
551    if (_providerID[ii] != -1) {
552      alreadySet = true;
553    }
554    if (_providerID[ii] != newProviderID[ii]) {
555      different = true;
556    }
557    _providerID[ii] = newProviderID[ii];
558  }
559
560  if (alreadySet && different) {
561    emit newMessage("RTCM3coDecoder: Provider Changed: " + _staID.toLatin1(), true);
562    emit providerIDChanged(_staID);
563  }
564}
565
566//
567////////////////////////////////////////////////////////////////////////////
568void RTCM3coDecoder::setEpochTime() {
569
570  _lastTime.reset();
571
572  double epoSecGPS  = -1.0;
573  double epoSecGlo  = -1.0;
574  double epoSecGal  = -1.0;
575  double epoSecQzss = -1.0;
576  double epoSecSbas = -1.0;
577  double epoSecBds  = -1.0;
578  if      (_clkOrb.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
579    epoSecGPS = _clkOrb.EpochTime[CLOCKORBIT_SATGPS];        // 0 .. 604799 s
580  }
581  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
582    epoSecGPS = _codeBias.EpochTime[CLOCKORBIT_SATGPS];      // 0 .. 604799 s
583  }
584  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
585    epoSecGPS = _phaseBias.EpochTime[CLOCKORBIT_SATGPS];     // 0 .. 604799 s
586  }
587  else if (_vTEC.NumLayers > 0) {
588    epoSecGPS = _vTEC.EpochTime;                             // 0 .. 604799 s
589  }
590  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
591    epoSecGlo = _clkOrb.EpochTime[CLOCKORBIT_SATGLONASS];    // 0 .. 86399 s
592  }
593  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
594    epoSecGlo = _codeBias.EpochTime[CLOCKORBIT_SATGLONASS];  // 0 .. 86399 s
595  }
596  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
597    epoSecGlo = _phaseBias.EpochTime[CLOCKORBIT_SATGLONASS]; // 0 .. 86399 s
598  }
599  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
600    epoSecGal = _clkOrb.EpochTime[CLOCKORBIT_SATGALILEO];
601  }
602  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
603    epoSecGal = _codeBias.EpochTime[CLOCKORBIT_SATGALILEO];
604  }
605  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
606    epoSecGal = _phaseBias.EpochTime[CLOCKORBIT_SATGALILEO];
607  }
608  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
609    epoSecQzss = _clkOrb.EpochTime[CLOCKORBIT_SATQZSS];
610  }
611  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
612    epoSecQzss = _codeBias.EpochTime[CLOCKORBIT_SATQZSS];
613  }
614  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
615    epoSecQzss = _phaseBias.EpochTime[CLOCKORBIT_SATQZSS];
616  }
617  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
618    epoSecSbas = _clkOrb.EpochTime[CLOCKORBIT_SATSBAS];
619  }
620  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
621    epoSecSbas = _codeBias.EpochTime[CLOCKORBIT_SATSBAS];
622  }
623  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
624    epoSecSbas = _phaseBias.EpochTime[CLOCKORBIT_SATSBAS];
625  }
626  else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
627    epoSecBds = _clkOrb.EpochTime[CLOCKORBIT_SATBDS];
628  }
629  else if (_codeBias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
630    epoSecBds = _codeBias.EpochTime[CLOCKORBIT_SATBDS];
631  }
632  else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
633    epoSecBds = _phaseBias.EpochTime[CLOCKORBIT_SATBDS];
634  }
635
636  // Retrieve current time
637  // ---------------------
638  int    currentWeek = 0;
639  double currentSec  = 0.0;
640  currentGPSWeeks(currentWeek, currentSec);
641  bncTime currentTime(currentWeek, currentSec);
642
643  // Set _lastTime close to currentTime
644  // ----------------------------------
645  if      (epoSecGPS != -1) {
646    _lastTime.set(currentWeek, epoSecGPS);
647  }
648  else if (epoSecGlo != -1) {
649    QDate date = dateAndTimeFromGPSweek(currentTime.gpsw(), currentTime.gpssec()).date();
650    epoSecGlo = epoSecGlo - 3 * 3600 + gnumleap(date.year(), date.month(), date.day());
651    _lastTime.set(currentWeek, epoSecGlo);
652  }
653  else if (epoSecGal != -1) {
654    _lastTime.set(currentWeek, epoSecGal);
655  }
656  else if (epoSecQzss != -1) {
657    _lastTime.set(currentWeek, epoSecQzss);
658  }
659  else if (epoSecSbas != -1) {
660    _lastTime.set(currentWeek, epoSecSbas);
661  }
662  else if (epoSecBds != -1) {
663    epoSecBds += 14.0;
664    if (epoSecBds > 604800.0) {
665      epoSecBds -= 7.0*24.0*60.0*60.0;
666    }
667    _lastTime.set(currentWeek, epoSecBds);
668  }
669
670  if (_lastTime.valid()) {
671    double maxDiff = 12 * 3600.0;
672    while (_lastTime < currentTime - maxDiff) {
673      _lastTime = _lastTime + maxDiff;
674    }
675    while (_lastTime > currentTime + maxDiff) {
676      _lastTime = _lastTime - maxDiff;
677    }
678  }
679}
680
681//
682////////////////////////////////////////////////////////////////////////////
683string RTCM3coDecoder::codeTypeToRnxType(char system, CodeType type) const {
684  if      (system == 'G') {
685    switch (type) {
686      case CODETYPEGPS_L1_CA:         return "1C";
687      case CODETYPEGPS_L1_P:          return "1P";
688      case CODETYPEGPS_L1_Z:          return "1W";
689      //case CODETYPEGPS_L1_Y:          return "1Y";
690      //case CODETYPEGPS_L1_M:          return "1M";
691      //case CODETYPEGPS_SEMI_CODELESS: return "2D";
692      case CODETYPEGPS_L2_CA:         return "2C";
693      case CODETYPEGPS_L2_P:          return "2P";
694      case CODETYPEGPS_L2_Z:          return "2W";
695
696      case CODETYPEGPS_L2C_M:         return "2S";
697      case CODETYPEGPS_L2C_L:         return "2L";
698      case CODETYPEGPS_L2C_ML:        return "2X";
699
700      //case CODETYPEGPS_L2_Y:          return "2Y";
701      //case CODETYPEGPS_L2_M:          return "2M";
702
703      case CODETYPEGPS_L5_I:          return "5I";
704      case CODETYPEGPS_L5_Q:          return "5Q";
705      case CODETYPEGPS_L5_IQ:         return "5X";
706
707      case CODETYPEGPS_L1C_D:         return "1S";
708      case CODETYPEGPS_L1C_P:         return "1L";
709      case CODETYPEGPS_L1C_DP:        return "1X";
710      default: return "";
711    }
712  }
713  else if (system == 'R') {
714    switch (type) {
715      case CODETYPEGLONASS_L1_CA:     return "1C";
716      case CODETYPEGLONASS_L1_P:      return "1P";
717      case CODETYPEGLONASS_L2_CA:     return "2C";
718      case CODETYPEGLONASS_L2_P:      return "2P";
719      case CODETYPEGLONASS_L1a_OCd:   return "4A";
720      case CODETYPEGLONASS_L1a_OCp:   return "4B";
721      case CODETYPEGLONASS_L1a_OCdp:  return "4X";
722      case CODETYPEGLONASS_L2a_CSI:   return "6A";
723      case CODETYPEGLONASS_L2a_OCp:   return "6B";
724      case CODETYPEGLONASS_L2a_CSIOCp:return "6X";
725      case CODETYPEGLONASS_L3_I:      return "3I";
726      case CODETYPEGLONASS_L3_Q:      return "3Q";
727      case CODETYPEGLONASS_L3_IQ:     return "3X";
728      default: return "";
729    }
730  }
731  else if (system == 'E') {
732    switch (type) {
733      case CODETYPEGALILEO_E1_A:       return "1A";
734      case CODETYPEGALILEO_E1_B:       return "1B";
735      case CODETYPEGALILEO_E1_C:       return "1C";
736      case CODETYPEGALILEO_E1_BC:      return "1X";
737      case CODETYPEGALILEO_E1_ABC:     return "1Z";
738
739      case CODETYPEGALILEO_E5A_I:      return "5I";
740      case CODETYPEGALILEO_E5A_Q:      return "5Q";
741      case CODETYPEGALILEO_E5A_IQ:     return "5X";
742
743      case CODETYPEGALILEO_E5B_I:      return "7I";
744      case CODETYPEGALILEO_E5B_Q:      return "7Q";
745      case CODETYPEGALILEO_E5B_IQ:     return "7X";
746
747      case CODETYPEGALILEO_E5_I:       return "8I";
748      case CODETYPEGALILEO_E5_Q:       return "8Q";
749      case CODETYPEGALILEO_E5_IQ:      return "8X";
750
751      case CODETYPEGALILEO_E6_A:       return "6A";
752      case CODETYPEGALILEO_E6_B:       return "6B";
753      case CODETYPEGALILEO_E6_C:       return "6C";
754      case CODETYPEGALILEO_E6_BC:      return "6X";
755      case CODETYPEGALILEO_E6_ABC:     return "6Z";
756      default: return "";
757    }
758  }
759  else if (system == 'J') {
760    switch (type) {
761      case CODETYPEQZSS_L1_CA:         return "1C";
762
763      case CODETYPEQZSS_L6_D:          return "6S";
764      case CODETYPEQZSS_L6_P:          return "6L";
765      case CODETYPEQZSS_L6_DP:         return "6X";
766
767      case CODETYPEQZSS_L2C_M:         return "2S";
768      case CODETYPEQZSS_L2C_L:         return "2L";
769      case CODETYPEQZSS_L2C_ML:        return "2X";
770
771      case CODETYPEQZSS_L5_I:          return "5I";
772      case CODETYPEQZSS_L5_Q:          return "5Q";
773      case CODETYPEQZSS_L5_IQ:         return "5X";
774
775      case CODETYPEQZSS_L1C_D:         return "1S";
776      case CODETYPEQZSS_L1C_P:         return "1L";
777      case CODETYPEQZSS_L1C_DP:        return "1X";
778      default: return "";
779    }
780  }
781  else if (system == 'S') {
782    switch (type) {
783      case CODETYPE_SBAS_L1_CA:       return "1C";
784
785      case CODETYPE_SBAS_L5_I:        return "5I";
786      case CODETYPE_SBAS_L5_Q:        return "5Q";
787      case CODETYPE_SBAS_L5_IQ:       return "5X";
788      default: return "";
789    }
790  }
791  else if (system == 'C') {
792    switch (type) {
793      case CODETYPE_BDS_B1_I:         return "2I";
794      case CODETYPE_BDS_B1_Q:         return "2Q";
795      case CODETYPE_BDS_B1_IQ:        return "2X";
796      case CODETYPE_BDS_B3_I:         return "6I";
797      case CODETYPE_BDS_B3_Q:         return "6Q";
798      case CODETYPE_BDS_B3_IQ:        return "6X";
799      case CODETYPE_BDS_B2_I:         return "7I";
800      case CODETYPE_BDS_B2_Q:         return "7Q";
801      case CODETYPE_BDS_B2_IQ:        return "7X";
802      case CODETYPE_BDS_B2a_D:        return "5D";
803      case CODETYPE_BDS_B2a_P:        return "5P";
804      case CODETYPE_BDS_B2a_DP:       return "5X";
805      case CODETYPE_BDS_B1C_D:        return "1D";
806      case CODETYPE_BDS_B1C_P:        return "1P";
807      case CODETYPE_BDS_B1C_DP:       return "1X";
808      default: return "";
809    }
810  }
811  return "";
812};
Note: See TracBrowser for help on using the repository browser.