source: ntrip/branches/BNC_2.12/src/RTCM3/RTCM3coDecoder.cpp @ 8842

Last change on this file since 8842 was 8842, checked in by stuerze, 9 months ago

minor changes

File size: 28.0 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.toAscii().data(), ios_base::out | ios_base::app );
149    }
150    else {
151      _out = new ofstream( _fileName.toAscii().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._yawDeg     = _phaseBias.Sat[ii].YawAngle * 180.0 / M_PI;
447    satPhaseBias._yawDegRate = _phaseBias.Sat[ii].YawRate * 180.0 / M_PI;
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.toAscii(), 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_L2_CA:         return "2C";
692      case CODETYPEGPS_SEMI_CODELESS: return "2D";
693      case CODETYPEGPS_L2C_M:         return "2S";
694      case CODETYPEGPS_L2C_L:         return "2L";
695      case CODETYPEGPS_L2C_ML:        return "2X";
696      case CODETYPEGPS_L2_P:          return "2P";
697      case CODETYPEGPS_L2_Z:          return "2W";
698      case CODETYPEGPS_L2_Y:          return "2Y";
699      case CODETYPEGPS_L2_M:          return "2M";
700      case CODETYPEGPS_L5_I:          return "5I";
701      case CODETYPEGPS_L5_Q:          return "5Q";
702      case CODETYPEGPS_L5_IQ:         return "5X";
703      case CODETYPEGPS_L1C_D:         return "1S";
704      case CODETYPEGPS_L1C_P:         return "1L";
705      case CODETYPEGPS_L1C_DP:        return "1X";
706      default: return "";
707    }
708  }
709  else if (system == 'R') {
710    switch (type) {
711      case CODETYPEGLONASS_L1_CA:     return "1C";
712      case CODETYPEGLONASS_L1_P:      return "1P";
713      case CODETYPEGLONASS_L2_CA:     return "2C";
714      case CODETYPEGLONASS_L2_P:      return "2P";
715      case CODETYPEGLONASS_L1a_OCd:   return "4A";
716      case CODETYPEGLONASS_L1a_OCp:   return "4B";
717      case CODETYPEGLONASS_L1a_OCdp:  return "4X";
718      case CODETYPEGLONASS_L2a_CSI:   return "6A";
719      case CODETYPEGLONASS_L2a_OCp:   return "6B";
720      case CODETYPEGLONASS_L2a_CSIOCp:return "6X";
721      case CODETYPEGLONASS_L3_I:      return "3I";
722      case CODETYPEGLONASS_L3_Q:      return "3Q";
723      case CODETYPEGLONASS_L3_IQ:     return "3X";
724      default: return "";
725    }
726  }
727  else if (system == 'E') {
728    switch (type) {
729      case CODETYPEGALILEO_E1_A:      return "1A";
730      case CODETYPEGALILEO_E1_B:      return "1B";
731      case CODETYPEGALILEO_E1_C:      return "1C";
732      case CODETYPEGALILEO_E1_BC:     return "1X";
733      case CODETYPEGALILEO_E1_ABC:    return "1Z";
734      case CODETYPEGALILEO_E5A_I:     return "5I";
735      case CODETYPEGALILEO_E5A_Q:     return "5Q";
736      case CODETYPEGALILEO_E5A_IQ:    return "5X";
737      case CODETYPEGALILEO_E5B_I:     return "7I";
738      case CODETYPEGALILEO_E5B_Q:     return "7Q";
739      case CODETYPEGALILEO_E5B_IQ:    return "7X";
740      case CODETYPEGALILEO_E5_I:      return "8I";
741      case CODETYPEGALILEO_E5_Q:      return "8Q";
742      case CODETYPEGALILEO_E5_IQ:     return "8X";
743      case CODETYPEGALILEO_E6_A:      return "6A";
744      case CODETYPEGALILEO_E6_B:      return "6B";
745      case CODETYPEGALILEO_E6_C:      return "6C";
746      case CODETYPEGALILEO_E6_BC:     return "6X";
747      case CODETYPEGALILEO_E6_ABC:    return "6Z";
748      default: return "";
749    }
750  }
751  else if (system == 'J') {
752    switch (type) {
753      case CODETYPEQZSS_L1_CA:         return "1C";
754      case CODETYPEQZSS_L1C_D:         return "1S";
755      case CODETYPEQZSS_L1C_P:         return "1L";
756      case CODETYPEQZSS_L2C_M:         return "2S";
757      case CODETYPEQZSS_L2C_L:         return "2L";
758      case CODETYPEQZSS_L2C_ML:        return "2X";
759      case CODETYPEQZSS_L5_I:          return "5I";
760      case CODETYPEQZSS_L5_Q:          return "5Q";
761      case CODETYPEQZSS_L5_IQ:         return "5X";
762      case CODETYPEQZSS_L6_D:          return "6S";
763      case CODETYPEQZSS_L6_P:          return "6L";
764      case CODETYPEQZSS_L6_DP:         return "6X";
765      case CODETYPEQZSS_L1C_DP:        return "1X";
766      case CODETYPEQZSS_L1_S:          return "1Z";
767      case CODETYPEQZSS_L5_D:          return "5D";
768      case CODETYPEQZSS_L5_P:          return "5P";
769      case CODETYPEQZSS_L5_DP:         return "5Z";
770      case CODETYPEQZSS_L6_E:          return "6E";
771      case CODETYPEQZSS_L6_DE:         return "6Z";
772      default: return "";
773    }
774  }
775  else if (system == 'S') {
776    switch (type) {
777      case CODETYPE_SBAS_L1_CA:       return "1C";
778      case CODETYPE_SBAS_L5_I:        return "5I";
779      case CODETYPE_SBAS_L5_Q:        return "5Q";
780      case CODETYPE_SBAS_L5_IQ:       return "5X";
781      default: return "";
782    }
783  }
784  else if (system == 'C') {
785    switch (type) {
786      case CODETYPE_BDS_B1_I:         return "2I";
787      case CODETYPE_BDS_B1_Q:         return "2Q";
788      case CODETYPE_BDS_B1_IQ:        return "2X";
789      case CODETYPE_BDS_B3_I:         return "6I";
790      case CODETYPE_BDS_B3_Q:         return "6Q";
791      case CODETYPE_BDS_B3_IQ:        return "6X";
792      case CODETYPE_BDS_B2_I:         return "7I";
793      case CODETYPE_BDS_B2_Q:         return "7Q";
794      case CODETYPE_BDS_B2_IQ:        return "7X";
795      case CODETYPE_BDS_B2a_D:        return "5D";
796      case CODETYPE_BDS_B2a_P:        return "5P";
797      case CODETYPE_BDS_B2a_DP:       return "5X";
798      case CODETYPE_BDS_B1C_D:        return "1D";
799      case CODETYPE_BDS_B1C_P:        return "1P";
800      case CODETYPE_BDS_B1C_DP:       return "1X";
801      default: return "";
802    }
803  }
804  return "";
805};
Note: See TracBrowser for help on using the repository browser.