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

Last change on this file since 7297 was 7179, checked in by stuerze, 10 years ago

RINEX v3 filenames can now be formed optionally during RINEX file generation from RTCM observation and navigation streams

File size: 25.9 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}
105
106//
107////////////////////////////////////////////////////////////////////////////
108void RTCM3coDecoder::reset() {
109 memset(&_clkOrb, 0, sizeof(_clkOrb));
110 memset(&_codeBias, 0, sizeof(_codeBias));
111 memset(&_phaseBias, 0, sizeof(_phaseBias));
112 memset(&_vTEC, 0, sizeof(_vTEC));
113}
114
115// Reopen Output File
116////////////////////////////////////////////////////////////////////////
117void RTCM3coDecoder::reopen() {
118
119 if (!_fileNameSkl.isEmpty()) {
120
121 bncSettings settings;
122
123 QDateTime datTim = currentDateAndTimeGPS();
124
125 QString hlpStr = bncRinex::nextEpochStr(datTim,
126 settings.value("corrIntr").toString(), false);
127
128 QString fileNameHlp = _fileNameSkl
129 + QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0'))
130 + hlpStr + datTim.toString(".yyC");
131
132 if (_fileName == fileNameHlp) {
133 return;
134 }
135 else {
136 _fileName = fileNameHlp;
137 }
138
139 delete _out;
140 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked) {
141 _out = new ofstream( _fileName.toAscii().data(), ios_base::out | ios_base::app );
142 }
143 else {
144 _out = new ofstream( _fileName.toAscii().data() );
145 }
146 }
147}
148
149//
150////////////////////////////////////////////////////////////////////////////
151t_irc RTCM3coDecoder::Decode(char* buffer, int bufLen, vector<string>& errmsg) {
152
153 errmsg.clear();
154
155 _buffer.append(QByteArray(buffer,bufLen));
156
157 t_irc retCode = failure;
158
159 while(_buffer.size()) {
160
161 struct ClockOrbit clkOrbSav;
162 struct CodeBias codeBiasSav;
163 struct PhaseBias phaseBiasSav;
164 struct VTEC vTECSav;
165 memcpy(&clkOrbSav, &_clkOrb, sizeof(clkOrbSav)); // save state
166 memcpy(&codeBiasSav, &_codeBias, sizeof(codeBiasSav));
167 memcpy(&phaseBiasSav, &_phaseBias, sizeof(phaseBiasSav));
168 memcpy(&vTECSav, &_vTEC, sizeof(vTECSav));
169
170 int bytesused = 0;
171 GCOB_RETURN irc = GetSSR(&_clkOrb, &_codeBias, &_vTEC, &_phaseBias,
172 _buffer.data(), _buffer.size(), &bytesused);
173
174 if (irc <= -30) { // not enough data - restore state and exit loop
175 memcpy(&_clkOrb, &clkOrbSav, sizeof(clkOrbSav));
176 memcpy(&_codeBias, &codeBiasSav, sizeof(codeBiasSav));
177 memcpy(&_phaseBias, &phaseBiasSav, sizeof(phaseBiasSav));
178 memcpy(&_vTEC, &vTECSav, sizeof(vTECSav));
179 break;
180 }
181
182 else if (irc < 0) { // error - skip 1 byte and retry
183 reset();
184 _buffer = _buffer.mid(bytesused ? bytesused : 1);
185 }
186
187 else { // OK or MESSAGEFOLLOWS
188 _buffer = _buffer.mid(bytesused);
189
190 if (irc == GCOBR_OK || irc == GCOBR_MESSAGEFOLLOWS ) {
191
192 setEpochTime(); // sets _lastTime
193
194 if (_lastTime.valid()) {
195 reopen();
196 checkProviderID();
197 sendResults();
198 retCode = success;
199 }
200 else {
201 retCode = failure;
202 }
203
204 reset();
205 }
206 }
207 }
208
209 return retCode;
210}
211
212//
213////////////////////////////////////////////////////////////////////////////
214void RTCM3coDecoder::sendResults() {
215
216 // Orbit and clock corrections of all satellites
217 // ---------------------------------------------
218 for (unsigned ii = 0; ii < CLOCKORBIT_NUMGPS
219 + CLOCKORBIT_NUMGLONASS
220 + CLOCKORBIT_NUMGALILEO
221 + CLOCKORBIT_NUMQZSS
222 + CLOCKORBIT_NUMSBAS
223 + _clkOrb.NumberOfSat[CLOCKORBIT_SATBDS];
224 ii++) {
225 char sysCh = ' ';
226 int flag = 0;
227 if (ii < _clkOrb.NumberOfSat[CLOCKORBIT_SATGPS]) {
228 sysCh = 'G';
229 }
230 else if (ii >= CLOCKORBIT_OFFSETGLONASS &&
231 ii < CLOCKORBIT_OFFSETGLONASS + _clkOrb.NumberOfSat[CLOCKORBIT_SATGLONASS]) {
232 sysCh = 'R';
233 }
234 else if (ii >= CLOCKORBIT_OFFSETGALILEO &&
235 ii < CLOCKORBIT_OFFSETGALILEO + _clkOrb.NumberOfSat[CLOCKORBIT_SATGALILEO]) {
236 sysCh = 'E';
237 flag = 1; // I/NAV clock has been chosen as reference clock for Galileo SSR corrections
238 }
239 else if (ii >= CLOCKORBIT_OFFSETQZSS &&
240 ii < CLOCKORBIT_OFFSETQZSS + _clkOrb.NumberOfSat[CLOCKORBIT_SATQZSS]) {
241 sysCh = 'J';
242 }
243 else if (ii >= CLOCKORBIT_OFFSETSBAS &&
244 ii < CLOCKORBIT_OFFSETSBAS + _clkOrb.NumberOfSat[CLOCKORBIT_SATSBAS]) {
245 sysCh = 'S';
246 }
247 else if (ii >= CLOCKORBIT_OFFSETBDS &&
248 ii < CLOCKORBIT_OFFSETBDS + _clkOrb.NumberOfSat[CLOCKORBIT_SATBDS]) {
249 sysCh = 'C';
250 }
251 else {
252 continue;
253 }
254 // Orbit correction
255 // ----------------
256 if ( _clkOrb.messageType == COTYPE_GPSCOMBINED ||
257 _clkOrb.messageType == COTYPE_GLONASSCOMBINED ||
258 _clkOrb.messageType == COTYPE_GALILEOCOMBINED ||
259 _clkOrb.messageType == COTYPE_QZSSCOMBINED ||
260 _clkOrb.messageType == COTYPE_SBASCOMBINED ||
261 _clkOrb.messageType == COTYPE_BDSCOMBINED ||
262 _clkOrb.messageType == COTYPE_GPSORBIT ||
263 _clkOrb.messageType == COTYPE_GLONASSORBIT ||
264 _clkOrb.messageType == COTYPE_GALILEOORBIT ||
265 _clkOrb.messageType == COTYPE_QZSSORBIT ||
266 _clkOrb.messageType == COTYPE_SBASORBIT ||
267 _clkOrb.messageType == COTYPE_BDSORBIT ) {
268
269 t_orbCorr orbCorr;
270 orbCorr._prn.set(sysCh, _clkOrb.Sat[ii].ID, flag);
271 orbCorr._staID = _staID.toStdString();
272 orbCorr._iod = _clkOrb.Sat[ii].IOD;
273 orbCorr._time = _lastTime;
274 orbCorr._updateInt = _clkOrb.UpdateInterval;
275 orbCorr._system = sysCh;
276 orbCorr._xr[0] = _clkOrb.Sat[ii].Orbit.DeltaRadial;
277 orbCorr._xr[1] = _clkOrb.Sat[ii].Orbit.DeltaAlongTrack;
278 orbCorr._xr[2] = _clkOrb.Sat[ii].Orbit.DeltaCrossTrack;
279 orbCorr._dotXr[0] = _clkOrb.Sat[ii].Orbit.DotDeltaRadial;
280 orbCorr._dotXr[1] = _clkOrb.Sat[ii].Orbit.DotDeltaAlongTrack;
281 orbCorr._dotXr[2] = _clkOrb.Sat[ii].Orbit.DotDeltaCrossTrack;
282
283 _orbCorrections[_lastTime].push_back(orbCorr);
284
285 _IODs[orbCorr._prn] = _clkOrb.Sat[ii].IOD;
286 }
287
288 // Clock Corrections
289 // -----------------
290 if ( _clkOrb.messageType == COTYPE_GPSCOMBINED ||
291 _clkOrb.messageType == COTYPE_GLONASSCOMBINED ||
292 _clkOrb.messageType == COTYPE_GALILEOCOMBINED ||
293 _clkOrb.messageType == COTYPE_QZSSCOMBINED ||
294 _clkOrb.messageType == COTYPE_SBASCOMBINED ||
295 _clkOrb.messageType == COTYPE_BDSCOMBINED ||
296 _clkOrb.messageType == COTYPE_GPSCLOCK ||
297 _clkOrb.messageType == COTYPE_GLONASSCLOCK ||
298 _clkOrb.messageType == COTYPE_GALILEOCLOCK ||
299 _clkOrb.messageType == COTYPE_QZSSCLOCK ||
300 _clkOrb.messageType == COTYPE_SBASCLOCK ||
301 _clkOrb.messageType == COTYPE_BDSCLOCK) {
302
303 t_clkCorr clkCorr;
304 clkCorr._prn.set(sysCh, _clkOrb.Sat[ii].ID, flag);
305
306 clkCorr._staID = _staID.toStdString();
307 clkCorr._time = _lastTime;
308 clkCorr._updateInt = _clkOrb.UpdateInterval;
309 clkCorr._dClk = _clkOrb.Sat[ii].Clock.DeltaA0 / t_CST::c;
310 clkCorr._dotDClk = _clkOrb.Sat[ii].Clock.DeltaA1 / t_CST::c;
311 clkCorr._dotDotDClk = _clkOrb.Sat[ii].Clock.DeltaA2 / t_CST::c;
312
313 _lastClkCorrections[clkCorr._prn] = clkCorr;
314
315 if (_IODs.contains(clkCorr._prn)) {
316 clkCorr._iod = _IODs[clkCorr._prn];
317 _clkCorrections[_lastTime].push_back(clkCorr);
318 }
319 }
320
321 // High-Resolution Clocks
322 // ----------------------
323 if ( _clkOrb.messageType == COTYPE_GPSHR ||
324 _clkOrb.messageType == COTYPE_GLONASSHR ||
325 _clkOrb.messageType == COTYPE_GALILEOHR ||
326 _clkOrb.messageType == COTYPE_QZSSHR ||
327 _clkOrb.messageType == COTYPE_SBASHR ||
328 _clkOrb.messageType == COTYPE_BDSHR) {
329 t_prn prn(sysCh, _clkOrb.Sat[ii].ID, flag);
330 if (_lastClkCorrections.contains(prn)) {
331 t_clkCorr clkCorr;
332 clkCorr = _lastClkCorrections[prn];
333 clkCorr._time = _lastTime;
334 clkCorr._updateInt = _clkOrb.UpdateInterval;
335 clkCorr._dClk += _clkOrb.Sat[ii].hrclock / t_CST::c;
336 if (_IODs.contains(clkCorr._prn)) {
337 clkCorr._iod = _IODs[clkCorr._prn];
338 _clkCorrections[_lastTime].push_back(clkCorr);
339 }
340 }
341 }
342 }
343
344 // Code Biases
345 // -----------
346 for (unsigned ii = 0; ii < CLOCKORBIT_NUMGPS
347 + CLOCKORBIT_NUMGLONASS
348 + CLOCKORBIT_NUMGALILEO
349 + CLOCKORBIT_NUMQZSS
350 + CLOCKORBIT_NUMSBAS
351 + _codeBias.NumberOfSat[CLOCKORBIT_SATBDS];
352 ii++) {
353 char sysCh = ' ';
354 if (ii < _codeBias.NumberOfSat[CLOCKORBIT_SATGPS]) {
355 sysCh = 'G';
356 }
357 else if (ii >= CLOCKORBIT_OFFSETGLONASS &&
358 ii < CLOCKORBIT_OFFSETGLONASS + _codeBias.NumberOfSat[CLOCKORBIT_SATGLONASS]) {
359 sysCh = 'R';
360 }
361 else if (ii >= CLOCKORBIT_OFFSETGALILEO &&
362 ii < CLOCKORBIT_OFFSETGALILEO + _codeBias.NumberOfSat[CLOCKORBIT_SATGALILEO]) {
363 sysCh = 'E';
364 }
365 else if (ii >= CLOCKORBIT_OFFSETQZSS &&
366 ii < CLOCKORBIT_OFFSETQZSS + _codeBias.NumberOfSat[CLOCKORBIT_SATQZSS]) {
367 sysCh = 'J';
368 }
369 else if (ii >= CLOCKORBIT_OFFSETSBAS &&
370 ii < CLOCKORBIT_OFFSETSBAS + _codeBias.NumberOfSat[CLOCKORBIT_SATSBAS]) {
371 sysCh = 'S';
372 }
373 else if (ii >= CLOCKORBIT_OFFSETBDS &&
374 ii < CLOCKORBIT_OFFSETBDS + _codeBias.NumberOfSat[CLOCKORBIT_SATBDS]) {
375 sysCh = 'C';
376 }
377 else {
378 continue;
379 }
380 t_satCodeBias satCodeBias;
381 satCodeBias._prn.set(sysCh, _codeBias.Sat[ii].ID);
382 satCodeBias._staID = _staID.toStdString();
383 satCodeBias._time = _lastTime;
384 satCodeBias._updateInt = _codeBias.UpdateInterval;
385 for (unsigned jj = 0; jj < _codeBias.Sat[ii].NumberOfCodeBiases; jj++) {
386 const CodeBias::BiasSat::CodeBiasEntry& biasEntry = _codeBias.Sat[ii].Biases[jj];
387 t_frqCodeBias frqCodeBias;
388 frqCodeBias._rnxType2ch = codeTypeToRnxType(sysCh, biasEntry.Type);
389 frqCodeBias._value = biasEntry.Bias;
390 if (!frqCodeBias._rnxType2ch.empty()) {
391 satCodeBias._bias.push_back(frqCodeBias);
392 }
393 }
394 _codeBiases[_lastTime].push_back(satCodeBias);
395 }
396
397 // Phase Biases
398 // -----------
399 for (unsigned ii = 0; ii < CLOCKORBIT_NUMGPS
400 + CLOCKORBIT_NUMGLONASS
401 + CLOCKORBIT_NUMGALILEO
402 + CLOCKORBIT_NUMQZSS
403 + CLOCKORBIT_NUMSBAS
404 + _phaseBias.NumberOfSat[CLOCKORBIT_SATBDS];
405 ii++) {
406 char sysCh = ' ';
407 if (ii < _phaseBias.NumberOfSat[CLOCKORBIT_SATGPS]) {
408 sysCh = 'G';
409 }
410 else if (ii >= CLOCKORBIT_OFFSETGLONASS &&
411 ii < CLOCKORBIT_OFFSETGLONASS + _phaseBias.NumberOfSat[CLOCKORBIT_SATGLONASS]) {
412 sysCh = 'R';
413 }
414 else if (ii >= CLOCKORBIT_OFFSETGALILEO &&
415 ii < CLOCKORBIT_OFFSETGALILEO + _phaseBias.NumberOfSat[CLOCKORBIT_SATGALILEO]) {
416 sysCh = 'E';
417 }
418 else if (ii >= CLOCKORBIT_OFFSETQZSS &&
419 ii < CLOCKORBIT_OFFSETQZSS + _phaseBias.NumberOfSat[CLOCKORBIT_SATQZSS]) {
420 sysCh = 'J';
421 }
422 else if (ii >= CLOCKORBIT_OFFSETSBAS &&
423 ii < CLOCKORBIT_OFFSETSBAS + _phaseBias.NumberOfSat[CLOCKORBIT_SATSBAS]) {
424 sysCh = 'S';
425 }
426 else if (ii >= CLOCKORBIT_OFFSETBDS &&
427 ii < CLOCKORBIT_OFFSETBDS + _phaseBias.NumberOfSat[CLOCKORBIT_SATBDS]) {
428 sysCh = 'C';
429 }
430 else {
431 continue;
432 }
433 t_satPhaseBias satPhaseBias;
434 satPhaseBias._prn.set(sysCh, _phaseBias.Sat[ii].ID);
435 satPhaseBias._staID = _staID.toStdString();
436 satPhaseBias._time = _lastTime;
437 satPhaseBias._updateInt = _phaseBias.UpdateInterval;
438 satPhaseBias._dispBiasConstistInd = _phaseBias.DispersiveBiasConsistencyIndicator;
439 satPhaseBias._MWConsistInd = _phaseBias.MWConsistencyIndicator;
440 satPhaseBias._yawDeg = _phaseBias.Sat[ii].YawAngle * 180.0 / M_PI;
441 satPhaseBias._yawDegRate = _phaseBias.Sat[ii].YawRate * 180.0 / M_PI;
442 for (unsigned jj = 0; jj < _phaseBias.Sat[ii].NumberOfPhaseBiases; jj++) {
443 const PhaseBias::PhaseBiasSat::PhaseBiasEntry& biasEntry = _phaseBias.Sat[ii].Biases[jj];
444 t_frqPhaseBias frqPhaseBias;
445 frqPhaseBias._rnxType2ch = codeTypeToRnxType(sysCh, biasEntry.Type);
446 frqPhaseBias._value = biasEntry.Bias;
447 frqPhaseBias._fixIndicator = biasEntry.SignalIntegerIndicator;
448 frqPhaseBias._fixWideLaneIndicator = biasEntry.SignalsWideLaneIntegerIndicator;
449 frqPhaseBias._jumpCounter = biasEntry.SignalDiscontinuityCounter;
450 if (!frqPhaseBias._rnxType2ch.empty()) {
451 satPhaseBias._bias.push_back(frqPhaseBias);
452 }
453 }
454 _phaseBiases[_lastTime].push_back(satPhaseBias);
455 }
456
457 // Ionospheric Model
458 // -----------------
459 if (_vTEC.NumLayers > 0) {
460 _vTecMap[_lastTime]._time = _lastTime;
461 _vTecMap[_lastTime]._updateInt = _vTEC.UpdateInterval;
462 _vTecMap[_lastTime]._staID = _staID.toStdString();
463 for (unsigned ii = 0; ii < _vTEC.NumLayers; ii++) {
464 const VTEC::IonoLayers& ionoLayer = _vTEC.Layers[ii];
465 t_vTecLayer layer;
466 layer._height = ionoLayer.Height;
467 layer._C.ReSize(ionoLayer.Degree+1, ionoLayer.Order+1);
468 layer._S.ReSize(ionoLayer.Degree+1, ionoLayer.Order+1);
469 for (unsigned iDeg = 0; iDeg <= ionoLayer.Degree; iDeg++) {
470 for (unsigned iOrd = 0; iOrd <= ionoLayer.Order; iOrd++) {
471 layer._C[iDeg][iOrd] = ionoLayer.Cosinus[iDeg][iOrd];
472 layer._S[iDeg][iOrd] = ionoLayer.Sinus[iDeg][iOrd];
473 }
474 }
475 _vTecMap[_lastTime]._layers.push_back(layer);
476 }
477 }
478
479 // Dump all older epochs
480 // ---------------------
481 QMutableMapIterator<bncTime, QList<t_orbCorr> > itOrb(_orbCorrections);
482 while (itOrb.hasNext()) {
483 itOrb.next();
484 if (itOrb.key() < _lastTime) {
485 emit newOrbCorrections(itOrb.value());
486 t_orbCorr::writeEpoch(_out, itOrb.value());
487 itOrb.remove();
488 }
489 }
490 QMutableMapIterator<bncTime, QList<t_clkCorr> > itClk(_clkCorrections);
491 while (itClk.hasNext()) {
492 itClk.next();
493 if (itClk.key() < _lastTime) {
494 emit newClkCorrections(itClk.value());
495 t_clkCorr::writeEpoch(_out, itClk.value());
496 itClk.remove();
497 }
498 }
499 QMutableMapIterator<bncTime, QList<t_satCodeBias> > itCB(_codeBiases);
500 while (itCB.hasNext()) {
501 itCB.next();
502 if (itCB.key() < _lastTime) {
503 emit newCodeBiases(itCB.value());
504 t_satCodeBias::writeEpoch(_out, itCB.value());
505 itCB.remove();
506 }
507 }
508 QMutableMapIterator<bncTime, QList<t_satPhaseBias> > itPB(_phaseBiases);
509 while (itPB.hasNext()) {
510 itPB.next();
511 if (itPB.key() < _lastTime) {
512 emit newPhaseBiases(itPB.value());
513 t_satPhaseBias::writeEpoch(_out, itPB.value());
514 itPB.remove();
515 }
516 }
517 QMutableMapIterator<bncTime, t_vTec> itTec(_vTecMap);
518 while (itTec.hasNext()) {
519 itTec.next();
520 if (itTec.key() < _lastTime) {
521 emit newTec(itTec.value());
522 t_vTec::write(_out, itTec.value());
523 itTec.remove();
524 }
525 }
526}
527
528//
529////////////////////////////////////////////////////////////////////////////
530void RTCM3coDecoder::checkProviderID() {
531
532 if (_clkOrb.SSRProviderID == 0 && _clkOrb.SSRSolutionID == 0 && _clkOrb.SSRIOD == 0) {
533 return;
534 }
535
536 int newProviderID[3];
537 newProviderID[0] = _clkOrb.SSRProviderID;
538 newProviderID[1] = _clkOrb.SSRSolutionID;
539 newProviderID[2] = _clkOrb.SSRIOD;
540
541 bool alreadySet = false;
542 bool different = false;
543
544 for (unsigned ii = 0; ii < 3; ii++) {
545 if (_providerID[ii] != -1) {
546 alreadySet = true;
547 }
548 if (_providerID[ii] != newProviderID[ii]) {
549 different = true;
550 }
551 _providerID[ii] = newProviderID[ii];
552 }
553
554 if (alreadySet && different) {
555 emit newMessage("RTCM3coDecoder: Provider Changed " + _staID.toAscii() + "\n", true);
556 emit providerIDChanged(_staID);
557 }
558}
559
560//
561////////////////////////////////////////////////////////////////////////////
562void RTCM3coDecoder::setEpochTime() {
563
564 _lastTime.reset();
565
566 double epoSecGPS = -1.0;
567 double epoSecGlo = -1.0;
568 double epoSecGal = -1.0;
569 double epoSecQzss = -1.0;
570 double epoSecSbas = -1.0;
571 double epoSecBds = -1.0;
572 if (_clkOrb.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
573 epoSecGPS = _clkOrb.EpochTime[CLOCKORBIT_SATGPS]; // 0 .. 604799 s
574 }
575 else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
576 epoSecGPS = _codeBias.EpochTime[CLOCKORBIT_SATGPS]; // 0 .. 604799 s
577 }
578 else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
579 epoSecGPS = _phaseBias.EpochTime[CLOCKORBIT_SATGPS]; // 0 .. 604799 s
580 }
581 else if (_vTEC.NumLayers > 0) {
582 epoSecGPS = _vTEC.EpochTime; // 0 .. 604799 s
583 }
584 else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
585 epoSecGlo = _clkOrb.EpochTime[CLOCKORBIT_SATGLONASS]; // 0 .. 86399 s
586 }
587 else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
588 epoSecGlo = _codeBias.EpochTime[CLOCKORBIT_SATGLONASS]; // 0 .. 86399 s
589 }
590 else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
591 epoSecGlo = _phaseBias.EpochTime[CLOCKORBIT_SATGLONASS]; // 0 .. 86399 s
592 }
593 else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
594 epoSecGal = _clkOrb.EpochTime[CLOCKORBIT_SATGALILEO];
595 }
596 else if (_codeBias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
597 epoSecGal = _codeBias.EpochTime[CLOCKORBIT_SATGALILEO];
598 }
599 else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
600 epoSecGal = _phaseBias.EpochTime[CLOCKORBIT_SATGALILEO];
601 }
602 else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
603 epoSecQzss = _clkOrb.EpochTime[CLOCKORBIT_SATQZSS];
604 }
605 else if (_codeBias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
606 epoSecQzss = _codeBias.EpochTime[CLOCKORBIT_SATQZSS];
607 }
608 else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
609 epoSecQzss = _phaseBias.EpochTime[CLOCKORBIT_SATQZSS];
610 }
611 else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
612 epoSecSbas = _clkOrb.EpochTime[CLOCKORBIT_SATSBAS];
613 }
614 else if (_codeBias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
615 epoSecSbas = _codeBias.EpochTime[CLOCKORBIT_SATSBAS];
616 }
617 else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
618 epoSecSbas = _phaseBias.EpochTime[CLOCKORBIT_SATSBAS];
619 }
620 else if (_clkOrb.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
621 epoSecBds = _clkOrb.EpochTime[CLOCKORBIT_SATBDS];
622 }
623 else if (_codeBias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
624 epoSecBds = _codeBias.EpochTime[CLOCKORBIT_SATBDS];
625 }
626 else if (_phaseBias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
627 epoSecBds = _phaseBias.EpochTime[CLOCKORBIT_SATBDS];
628 }
629
630 // Retrieve current time
631 // ---------------------
632 int currentWeek = 0;
633 double currentSec = 0.0;
634 currentGPSWeeks(currentWeek, currentSec);
635 bncTime currentTime(currentWeek, currentSec);
636
637 // Set _lastTime close to currentTime
638 // ----------------------------------
639 if (epoSecGPS != -1) {
640 _lastTime.set(currentWeek, epoSecGPS);
641 }
642 else if (epoSecGlo != -1) {
643 QDate date = dateAndTimeFromGPSweek(currentTime.gpsw(), currentTime.gpssec()).date();
644 epoSecGlo = epoSecGlo - 3 * 3600 + gnumleap(date.year(), date.month(), date.day());
645 _lastTime.set(currentWeek, epoSecGlo);
646 }
647 else if (epoSecGal != -1) {
648 _lastTime.set(currentWeek, epoSecGal);
649 }
650 else if (epoSecQzss != -1) {
651 _lastTime.set(currentWeek, epoSecQzss);
652 }
653 else if (epoSecSbas != -1) {
654 _lastTime.set(currentWeek, epoSecSbas);
655 }
656 else if (epoSecBds != -1) {
657 epoSecBds += 14.0;
658 _lastTime.set(currentWeek, epoSecBds);
659 }
660
661 if (_lastTime.valid()) {
662 double maxDiff = 12 * 3600.0;
663 while (_lastTime < currentTime - maxDiff) {
664 _lastTime = _lastTime + maxDiff;
665 }
666 while (_lastTime > currentTime + maxDiff) {
667 _lastTime = _lastTime - maxDiff;
668 }
669 }
670}
671
672//
673////////////////////////////////////////////////////////////////////////////
674string RTCM3coDecoder::codeTypeToRnxType(char system, CodeType type) const {
675 if (system == 'G') {
676 switch (type) {
677 case CODETYPEGPS_L1_CA: return "1C";
678 case CODETYPEGPS_L1_P: return "1P";
679 case CODETYPEGPS_L1_Z: return "1W";
680 case CODETYPEGPS_L2_CA: return "2C";
681 case CODETYPEGPS_SEMI_CODELESS: return "?N"; // which carrier ?
682 case CODETYPEGPS_L2_CM: return "2S";
683 case CODETYPEGPS_L2_CL: return "2L";
684 case CODETYPEGPS_L2_CML: return "2X";
685 case CODETYPEGPS_L2_P: return "2P";
686 case CODETYPEGPS_L2_Z: return "2W";
687 case CODETYPEGPS_L5_I: return "5I";
688 case CODETYPEGPS_L5_Q: return "5Q";
689 default: return "";
690 }
691 }
692 else if (system == 'R') {
693 switch (type) {
694 case CODETYPEGLONASS_L1_CA: return "1C";
695 case CODETYPEGLONASS_L1_P: return "1P";
696 case CODETYPEGLONASS_L2_CA: return "2C";
697 case CODETYPEGLONASS_L2_P: return "2P";
698 default: return "";
699 }
700 }
701 else if (system == 'E') {
702 switch (type) {
703 case CODETYPEGALILEO_E1_A: return "1A";
704 case CODETYPEGALILEO_E1_B: return "1B";
705 case CODETYPEGALILEO_E1_C: return "1C";
706 case CODETYPEGALILEO_E5A_I: return "5I";
707 case CODETYPEGALILEO_E5A_Q: return "5Q";
708 case CODETYPEGALILEO_E5B_I: return "7I";
709 case CODETYPEGALILEO_E5B_Q: return "7Q";
710 case CODETYPEGALILEO_E5_I: return "8I";
711 case CODETYPEGALILEO_E5_Q: return "8Q";
712 case CODETYPEGALILEO_E6_A: return "6A";
713 case CODETYPEGALILEO_E6_B: return "6B";
714 case CODETYPEGALILEO_E6_C: return "6C";
715 default: return "";
716 }
717 }
718 else if (system == 'J') {
719 switch (type) {
720 case CODETYPEQZSS_L1_CA: return "1C";
721 case CODETYPEQZSS_L1C_D: return "1S";
722 case CODETYPEQZSS_L1C_P: return "1L";
723 case CODETYPEQZSS_L1C_DP: return "1X";
724 case CODETYPEQZSS_L2_CM: return "2S";
725 case CODETYPEQZSS_L2_CL: return "2L";
726 case CODETYPEQZSS_L2_CML: return "2X";
727 case CODETYPEQZSS_L5_I: return "5I";
728 case CODETYPEQZSS_L5_Q: return "5Q";
729 case CODETYPEQZSS_L5_IQ: return "5X";
730 case CODETYPEQZSS_LEX_S: return "6S";
731 case CODETYPEQZSS_LEX_L: return "6L";
732 case CODETYPEQZSS_LEX_SL: return "6X";
733 default: return "";
734 }
735 }
736 else if (system == 'S') {
737 switch (type) {
738 case CODETYPE_SBAS_L1_CA: return "1C";
739 case CODETYPE_SBAS_L5_I: return "5I";
740 case CODETYPE_SBAS_L5_Q: return "5Q";
741 case CODETYPE_SBAS_L5_IQ: return "5X";
742 default: return "";
743 }
744 }
745 else if (system == 'C') {
746 switch (type) {
747 case CODETYPE_BDS_B1_I: return "1I";
748 case CODETYPE_BDS_B1_Q: return "1Q";
749 case CODETYPE_BDS_B1_IQ: return "1X";
750 case CODETYPE_BDS_B2_I: return "7I";
751 case CODETYPE_BDS_B2_Q: return "7Q";
752 case CODETYPE_BDS_B2_IQ: return "7X";
753 case CODETYPE_BDS_B3_I: return "6I";
754 case CODETYPE_BDS_B3_Q: return "6Q";
755 case CODETYPE_BDS_B3_IQ: return "6X";
756 default: return "";
757 }
758 }
759 return "";
760};
Note: See TracBrowser for help on using the repository browser.