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

Last change on this file since 8308 was 8308, checked in by stuerze, 19 months ago

consideration of DF range 0-63 for SSR Satellite IDs as defined in DF463, DF466 (first BDS or SBAS satellite is 0)

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