source: ntrip/trunk/BNC/src/upload/bncrtnetuploadcaster.cpp@ 9179

Last change on this file since 9179 was 9179, checked in by stuerze, 22 months ago

check if orbit and clock corrections are in defined ranges is added

File size: 38.5 KB
Line 
1/* -------------------------------------------------------------------------
2 * BKG NTRIP Server
3 * -------------------------------------------------------------------------
4 *
5 * Class: bncRtnetUploadCaster
6 *
7 * Purpose: Connection to NTRIP Caster
8 *
9 * Author: L. Mervart
10 *
11 * Created: 29-Mar-2011
12 *
13 * Changes:
14 *
15 * -----------------------------------------------------------------------*/
16
17#include <math.h>
18#include "bncrtnetuploadcaster.h"
19#include "bncsettings.h"
20#include "bncephuser.h"
21#include "bncclockrinex.h"
22#include "bncsp3.h"
23#include "gnss.h"
24
25using namespace std;
26
27// Constructor
28////////////////////////////////////////////////////////////////////////////
29bncRtnetUploadCaster::bncRtnetUploadCaster(const QString& mountpoint,
30 const QString& outHost, int outPort,
31 const QString& ntripVersion,
32 const QString& userName, const QString& password,
33 const QString& crdTrafo, const QString& ssrFormat, bool CoM, const QString& sp3FileName,
34 const QString& rnxFileName, int PID, int SID, int IOD, int iRow) :
35 bncUploadCaster(mountpoint, outHost, outPort, ntripVersion, userName, password, iRow, 0) {
36
37 if (!mountpoint.isEmpty()) {
38 _casterID += mountpoint;
39 }
40 if (!outHost.isEmpty()) {
41 _casterID += " " + outHost;
42 if (outPort) {
43 _casterID += ":" + QString("%1").arg(outPort, 10);
44 }
45 }
46 if (!crdTrafo.isEmpty()) {
47 _casterID += " " + crdTrafo;
48 }
49 if (!sp3FileName.isEmpty()) {
50 _casterID += " " + sp3FileName;
51 }
52 if (!rnxFileName.isEmpty()) {
53 _casterID += " " + rnxFileName;
54 }
55
56 _crdTrafo = crdTrafo;
57
58 _ssrFormat = ssrFormat;
59
60 _ssrCorr = 0;
61 if (_ssrFormat == "IGS-SSR") {
62 _ssrCorr = new SsrCorrIgs();
63 }
64 else if (_ssrFormat == "RTCM-SSR") {
65 _ssrCorr = new SsrCorrRtcm();
66 }
67
68 _CoM = CoM;
69 _PID = PID;
70 _SID = SID;
71 _IOD = IOD;
72
73 // Member that receives the ephemeris
74 // ----------------------------------
75 _ephUser = new bncEphUser(true);
76
77 bncSettings settings;
78 QString intr = settings.value("uploadIntr").toString();
79 QStringList hlp = settings.value("cmbStreams").toStringList();
80 _samplRtcmEphCorr = settings.value("uploadSamplRtcmEphCorr").toDouble();
81 if (hlp.size() > 1) { // combination stream upload
82 _samplRtcmClkCorr = settings.value("cmbSampl").toInt();
83 }
84 else { // single stream upload or sp3 file generation
85 _samplRtcmClkCorr = 5; // default
86 }
87 int samplClkRnx = settings.value("uploadSamplClkRnx").toInt();
88 int samplSp3 = settings.value("uploadSamplSp3").toInt() * 60;
89
90 if (_samplRtcmEphCorr == 0.0) {
91 _usedEph = 0;
92 }
93 else {
94 _usedEph = new QMap<QString, const t_eph*>;
95 }
96
97 // RINEX writer
98 // ------------
99 if (!rnxFileName.isEmpty()) {
100 _rnx = new bncClockRinex(rnxFileName, intr, samplClkRnx);
101 }
102 else {
103 _rnx = 0;
104 }
105
106 // SP3 writer
107 // ----------
108 if (!sp3FileName.isEmpty()) {
109 _sp3 = new bncSP3(sp3FileName, intr, samplSp3);
110 }
111 else {
112 _sp3 = 0;
113 }
114
115 // Set Transformation Parameters
116 // -----------------------------
117 // Transformation Parameters from ITRF2014 to ETRF2000
118 // EUREF Technical Note 1 Relationship and Transformation between the ITRF and ETRF
119 // Zuheir Altamimi, June 28, 2018
120 if (_crdTrafo == "ETRF2000") {
121 _dx = 0.0547;
122 _dy = 0.0522;
123 _dz = -0.0741;
124
125 _dxr = 0.0001;
126 _dyr = 0.0001;
127 _dzr = -0.0019;
128
129 _ox = 0.001701;
130 _oy = 0.010290;
131 _oz = -0.016632;
132
133 _oxr = 0.000081;
134 _oyr = 0.000490;
135 _ozr = -0.000729;
136
137 _sc = 2.12;
138 _scr = 0.11;
139
140 _t0 = 2010.0;
141 }
142 // Transformation Parameters from ITRF2014 to GDA2020 (Ryan Ruddick, GA)
143 else if (_crdTrafo == "GDA2020") {
144 _dx = 0.0;
145 _dy = 0.0;
146 _dz = 0.0;
147
148 _dxr = 0.0;
149 _dyr = 0.0;
150 _dzr = 0.0;
151
152 _ox = 0.0;
153 _oy = 0.0;
154 _oz = 0.0;
155
156 _oxr = 0.00150379;
157 _oyr = 0.00118346;
158 _ozr = 0.00120716;
159
160 _sc = 0.0;
161 _scr = 0.0;
162
163 _t0 = 2020.0;
164 }
165 // Transformation Parameters from IGb14 to SIRGAS2000 (Thanks to Sonia Costa, BRA)
166 // June 29 2020: TX:-0.0027 m TY:-0.0025 m TZ:-0.0042 m SCL:1.20 (ppb) no rotations and no rates.*/
167 else if (_crdTrafo == "SIRGAS2000") {
168 _dx = -0.0027;
169 _dy = -0.0025;
170 _dz = -0.0042;
171
172 _dxr = 0.0000;
173 _dyr = 0.0000;
174 _dzr = 0.0000;
175
176 _ox = 0.000000;
177 _oy = 0.000000;
178 _oz = 0.000000;
179
180 _oxr = 0.000000;
181 _oyr = 0.000000;
182 _ozr = 0.000000;
183
184 _sc = 1.20000;
185 _scr = 0.00000;
186 _t0 = 2000.0;
187 }
188 // Transformation Parameters from ITRF2014 to DREF91
189 else if (_crdTrafo == "DREF91") {
190 _dx = 0.0547;
191 _dy = 0.0522;
192 _dz = -0.0741;
193
194 _dxr = 0.0001;
195 _dyr = 0.0001;
196 _dzr = -0.0019;
197 // ERTF200 + rotation parameters (ETRF200 => DREF91)
198 _ox = 0.001701 + 0.000658;
199 _oy = 0.010290 - 0.000208;
200 _oz = -0.016632 + 0.000755;
201
202 _oxr = 0.000081;
203 _oyr = 0.000490;
204 _ozr = -0.000729;
205
206 _sc = 2.12;
207 _scr = 0.11;
208
209 _t0 = 2010.0;
210 }
211 else if (_crdTrafo == "Custom") {
212 _dx = settings.value("trafo_dx").toDouble();
213 _dy = settings.value("trafo_dy").toDouble();
214 _dz = settings.value("trafo_dz").toDouble();
215 _dxr = settings.value("trafo_dxr").toDouble();
216 _dyr = settings.value("trafo_dyr").toDouble();
217 _dzr = settings.value("trafo_dzr").toDouble();
218 _ox = settings.value("trafo_ox").toDouble();
219 _oy = settings.value("trafo_oy").toDouble();
220 _oz = settings.value("trafo_oz").toDouble();
221 _oxr = settings.value("trafo_oxr").toDouble();
222 _oyr = settings.value("trafo_oyr").toDouble();
223 _ozr = settings.value("trafo_ozr").toDouble();
224 _sc = settings.value("trafo_sc").toDouble();
225 _scr = settings.value("trafo_scr").toDouble();
226 _t0 = settings.value("trafo_t0").toDouble();
227 }
228}
229
230// Destructor
231////////////////////////////////////////////////////////////////////////////
232bncRtnetUploadCaster::~bncRtnetUploadCaster() {
233 if (isRunning()) {
234 wait();
235 }
236 delete _rnx;
237 delete _sp3;
238 delete _ephUser;
239 delete _usedEph;
240 delete _ssrCorr;
241}
242
243//
244////////////////////////////////////////////////////////////////////////////
245void bncRtnetUploadCaster::decodeRtnetStream(char* buffer, int bufLen) {
246
247 QMutexLocker locker(&_mutex);
248
249 // Append to internal buffer
250 // -------------------------
251 _rtnetStreamBuffer.append(QByteArray(buffer, bufLen));
252
253 // Select buffer part that contains last epoch
254 // -------------------------------------------
255 QStringList lines;
256 int iEpoBeg = _rtnetStreamBuffer.lastIndexOf('*'); // begin of last epoch
257 if (iEpoBeg == -1) {
258 _rtnetStreamBuffer.clear();
259 return;
260 }
261 int iEpoBegEarlier = _rtnetStreamBuffer.indexOf('*');
262 if (iEpoBegEarlier != -1 && iEpoBegEarlier < iEpoBeg) { // are there two epoch lines in buffer?
263 _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoBegEarlier);
264 }
265 else {
266 _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoBeg);
267 }
268 int iEpoEnd = _rtnetStreamBuffer.lastIndexOf("EOE"); // end of last epoch
269 if (iEpoEnd == -1) {
270 return;
271 }
272
273 while (_rtnetStreamBuffer.count('*') > 1) { // is there more than 1 epoch line in buffer?
274 QString rtnetStreamBuffer = _rtnetStreamBuffer.mid(1);
275 int nextEpoch = rtnetStreamBuffer.indexOf('*');
276 if (nextEpoch != -1 && nextEpoch < iEpoEnd) {
277 _rtnetStreamBuffer = _rtnetStreamBuffer.mid(nextEpoch);
278 }
279 else if (nextEpoch != -1 && nextEpoch >= iEpoEnd) {
280 break;
281 }
282 }
283
284 lines = _rtnetStreamBuffer.left(iEpoEnd).split('\n',
285 QString::SkipEmptyParts);
286 _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoEnd + 3);
287
288 if (lines.size() < 2) {
289 return;
290 }
291
292 // Read first line (with epoch time)
293 // ---------------------------------
294 QTextStream in(lines[0].toLatin1());
295 QString hlp;
296 int year, month, day, hour, min;
297 double sec;
298 in >> hlp >> year >> month >> day >> hour >> min >> sec;
299 bncTime epoTime;
300 epoTime.set(year, month, day, hour, min, sec);
301
302 emit(newMessage(
303 "bncRtnetUploadCaster: decode " + QByteArray(epoTime.datestr().c_str())
304 + " " + QByteArray(epoTime.timestr().c_str()) + " "
305 + _casterID.toLatin1(), false));
306
307 struct SsrCorr::ClockOrbit co;
308 memset(&co, 0, sizeof(co));
309 co.EpochTime[CLOCKORBIT_SATGPS] = static_cast<int>(epoTime.gpssec());
310 if (_ssrFormat == "RTCM-SSR") {
311 double gt = epoTime.gpssec() + 3 * 3600 - gnumleap(year, month, day);
312 co.EpochTime[CLOCKORBIT_SATGLONASS] = static_cast<int>(fmod(gt, 86400.0));
313 }
314 else if (_ssrFormat == "IGS-SSR") {
315 co.EpochTime[CLOCKORBIT_SATGLONASS] = static_cast<int>(epoTime.gpssec());
316 }
317 co.EpochTime[CLOCKORBIT_SATGALILEO] = static_cast<int>(epoTime.gpssec());
318 co.EpochTime[CLOCKORBIT_SATQZSS] = static_cast<int>(epoTime.gpssec());
319 co.EpochTime[CLOCKORBIT_SATSBAS] = static_cast<int>(epoTime.gpssec());
320 if (_ssrFormat == "RTCM-SSR") {
321 co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.bdssec());
322 }
323 else if (_ssrFormat == "IGS-SSR") {
324 co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.gpssec());
325 }
326 co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
327 co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
328 co.SatRefDatum = _ssrCorr->DATUM_ITRF; // ToDo: to decode from RTNET format
329 co.SSRIOD = _IOD;
330 co.SSRProviderID = _PID; // 256 .. BKG, 257 ... EUREF
331 co.SSRSolutionID = _SID;
332
333 struct SsrCorr::CodeBias bias;
334 memset(&bias, 0, sizeof(bias));
335 bias.EpochTime[CLOCKORBIT_SATGPS] = co.EpochTime[CLOCKORBIT_SATGPS];
336 bias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
337 bias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
338 bias.EpochTime[CLOCKORBIT_SATQZSS] = co.EpochTime[CLOCKORBIT_SATQZSS];
339 bias.EpochTime[CLOCKORBIT_SATSBAS] = co.EpochTime[CLOCKORBIT_SATSBAS];
340 bias.EpochTime[CLOCKORBIT_SATBDS] = co.EpochTime[CLOCKORBIT_SATBDS];
341 bias.SSRIOD = _IOD;
342 bias.SSRProviderID = _PID;
343 bias.SSRSolutionID = _SID;
344
345 struct SsrCorr::PhaseBias phasebias;
346 memset(&phasebias, 0, sizeof(phasebias));
347 unsigned int dispersiveBiasConsistenyIndicator = 0;
348 unsigned int mwConsistencyIndicator = 0;
349 phasebias.EpochTime[CLOCKORBIT_SATGPS] = co.EpochTime[CLOCKORBIT_SATGPS];
350 phasebias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
351 phasebias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
352 phasebias.EpochTime[CLOCKORBIT_SATQZSS] = co.EpochTime[CLOCKORBIT_SATQZSS];
353 phasebias.EpochTime[CLOCKORBIT_SATSBAS] = co.EpochTime[CLOCKORBIT_SATSBAS];
354 phasebias.EpochTime[CLOCKORBIT_SATBDS] = co.EpochTime[CLOCKORBIT_SATBDS];
355 phasebias.SSRIOD = _IOD;
356 phasebias.SSRProviderID = _PID;
357 phasebias.SSRSolutionID = _SID;
358
359 struct SsrCorr::VTEC vtec;
360 memset(&vtec, 0, sizeof(vtec));
361 vtec.EpochTime = static_cast<int>(epoTime.gpssec());
362 vtec.SSRIOD = _IOD;
363 vtec.SSRProviderID = _PID;
364 vtec.SSRSolutionID = _SID;
365
366 // Default Update Interval
367 // -----------------------
368 int clkUpdInd = 2; // 5 sec
369 int ephUpdInd = clkUpdInd; // default
370
371 if (_samplRtcmClkCorr > 5.0 && _samplRtcmEphCorr <= 5.0) { // combined orb and clock
372 ephUpdInd = determineUpdateInd(_samplRtcmClkCorr);
373 }
374 if (_samplRtcmClkCorr > 5.0) {
375 clkUpdInd = determineUpdateInd(_samplRtcmClkCorr);
376 }
377 if (_samplRtcmEphCorr > 5.0) {
378 ephUpdInd = determineUpdateInd(_samplRtcmEphCorr);
379 }
380
381 co.UpdateInterval = clkUpdInd;
382 bias.UpdateInterval = ephUpdInd;
383 phasebias.UpdateInterval = ephUpdInd;
384
385 for (int ii = 1; ii < lines.size(); ii++) {
386 QString key; // prn or key VTEC, IND (phase bias indicators)
387 double rtnUra = 0.0; // [m]
388 ColumnVector rtnAPC; rtnAPC.ReSize(3); rtnAPC = 0.0; // [m, m, m]
389 ColumnVector rtnVel; rtnVel.ReSize(3); rtnVel = 0.0; // [m/s, m/s, m/s]
390 ColumnVector rtnCoM; rtnCoM.ReSize(3); rtnCoM = 0.0; // [m, m, m]
391 ColumnVector rtnClk; rtnClk.ReSize(3); rtnClk = 0.0; // [m, m/s, m/s²]
392 ColumnVector rtnClkSig; rtnClkSig.ReSize(3); rtnClkSig = 0.0; // [m, m/s, m/s²]
393 t_prn prn;
394
395 QTextStream in(lines[ii].toLatin1());
396
397 in >> key;
398
399 // non-satellite specific parameters
400 if (key.contains("IND", Qt::CaseSensitive)) {
401 in >> dispersiveBiasConsistenyIndicator >> mwConsistencyIndicator;
402 continue;
403 }
404 // non-satellite specific parameters
405 if (key.contains("VTEC", Qt::CaseSensitive)) {
406 double ui;
407 in >> ui >> vtec.NumLayers;
408 vtec.UpdateInterval = (unsigned int) determineUpdateInd(ui);
409 for (unsigned ll = 0; ll < vtec.NumLayers; ll++) {
410 int dummy;
411 in >> dummy >> vtec.Layers[ll].Degree >> vtec.Layers[ll].Order
412 >> vtec.Layers[ll].Height;
413 for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
414 for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
415 in >> vtec.Layers[ll].Cosinus[iDeg][iOrd];
416 }
417 }
418 for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
419 for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
420 in >> vtec.Layers[ll].Sinus[iDeg][iOrd];
421 }
422 }
423 }
424 continue;
425 }
426 // satellite specific parameters
427 char sys = key.mid(0, 1).at(0).toLatin1();
428 int number = key.mid(1, 2).toInt();
429 int flags = 0;
430 if (sys == 'E') { // I/NAV
431 flags = 1;
432 }
433 prn.set(sys, number, flags);
434 QString prnInternalStr = QString::fromStdString(prn.toInternalString());
435 QString prnStr = QString::fromStdString(prn.toString());
436
437 const t_eph* ephLast = _ephUser->ephLast(prnInternalStr);
438 const t_eph* ephPrev = _ephUser->ephPrev(prnInternalStr);
439 const t_eph* eph = ephLast;
440 if (eph) {
441
442 // Use previous ephemeris if the last one is too recent
443 // ----------------------------------------------------
444 const int MINAGE = 60; // seconds
445 if (ephPrev && eph->receptDateTime().isValid()
446 && eph->receptDateTime().secsTo(currentDateAndTimeGPS()) < MINAGE) {
447 eph = ephPrev;
448 }
449
450 // Make sure the clock messages refer to same IOD as orbit messages
451 // ----------------------------------------------------------------
452 if (_usedEph) {
453 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
454 (*_usedEph)[prnInternalStr] = eph;
455 }
456 else {
457 eph = 0;
458 if (_usedEph->contains(prnInternalStr)) {
459 const t_eph* usedEph = _usedEph->value(prnInternalStr);
460 if (usedEph == ephLast) {
461 eph = ephLast;
462 }
463 else if (usedEph == ephPrev) {
464 eph = ephPrev;
465 }
466 }
467 }
468 }
469 }
470
471 if (eph &&
472 eph->checkState() != t_eph::bad &&
473 eph->checkState() != t_eph::unhealthy &&
474 eph->checkState() != t_eph::outdated) {
475 QMap<QString, double> codeBiases;
476 QList<phaseBiasSignal> phaseBiasList;
477 phaseBiasesSat pbSat;
478 _phaseBiasInformationDecoded = false;
479
480 while (true) {
481 QString key;
482 int numVal = 0;
483 in >> key;
484 if (in.status() != QTextStream::Ok) {
485 break;
486 }
487 if (key == "APC") {
488 in >> numVal;
489 rtnAPC.ReSize(3); rtnAPC = 0.0;
490 for (int ii = 0; ii < numVal; ii++) {
491 in >> rtnAPC[ii];
492 }
493 }
494 else if (key == "Ura") {
495 in >> numVal;
496 if (numVal == 1)
497 in >> rtnUra;
498 }
499 else if (key == "Clk") {
500 in >> numVal;
501 rtnClk.ReSize(3); rtnClk = 0.0;
502 for (int ii = 0; ii < numVal; ii++) {
503 in >> rtnClk[ii];
504 }
505 }
506 else if (key == "ClkSig") {
507 in >> numVal;
508 rtnClkSig.ReSize(3); rtnClkSig = 0.0;
509 for (int ii = 0; ii < numVal; ii++) {
510 in >> rtnClkSig[ii];
511 }
512 }
513 else if (key == "Vel") {
514 in >> numVal;
515 rtnVel.ReSize(3); rtnVel = 0.0;
516 for (int ii = 0; ii < numVal; ii++) {
517 in >> rtnVel[ii];
518 }
519 }
520 else if (key == "CoM") {
521 in >> numVal;
522 rtnCoM.ReSize(3); rtnCoM = 0.0;
523 for (int ii = 0; ii < numVal; ii++) {
524 in >> rtnCoM[ii];
525 }
526 }
527 else if (key == "CodeBias") {
528 in >> numVal;
529 for (int ii = 0; ii < numVal; ii++) {
530 QString type;
531 double value;
532 in >> type >> value;
533 codeBiases[type] = value;
534 }
535 }
536 else if (key == "YawAngle") {
537 _phaseBiasInformationDecoded = true;
538 in >> numVal >> pbSat.yawAngle;
539 if (pbSat.yawAngle < 0.0) {
540 pbSat.yawAngle += (2*M_PI);
541 }
542 else if (pbSat.yawAngle > 2*M_PI) {
543 pbSat.yawAngle -= (2*M_PI);
544 }
545 }
546 else if (key == "YawRate") {
547 _phaseBiasInformationDecoded = true;
548 in >> numVal >> pbSat.yawRate;
549 }
550 else if (key == "PhaseBias") {
551 _phaseBiasInformationDecoded = true;
552 in >> numVal;
553 for (int ii = 0; ii < numVal; ii++) {
554 phaseBiasSignal pb;
555 in >> pb.type >> pb.bias >> pb.integerIndicator
556 >> pb.wlIndicator >> pb.discontinuityCounter;
557 phaseBiasList.append(pb);
558 }
559 }
560 else {
561 in >> numVal;
562 for (int ii = 0; ii < numVal; ii++) {
563 double dummy;
564 in >> dummy;
565 }
566 emit(newMessage(" RTNET format error: "
567 + lines[ii].toLatin1(), false));
568 }
569 }
570
571 struct SsrCorr::ClockOrbit::SatData* sd = 0;
572 if (prn.system() == 'G') {
573 sd = co.Sat + co.NumberOfSat[CLOCKORBIT_SATGPS];
574 ++co.NumberOfSat[CLOCKORBIT_SATGPS];
575 }
576 else if (prn.system() == 'R') {
577 sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfSat[CLOCKORBIT_SATGLONASS];
578 ++co.NumberOfSat[CLOCKORBIT_SATGLONASS];
579 }
580 else if (prn.system() == 'E') {
581 sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
582 + co.NumberOfSat[CLOCKORBIT_SATGALILEO];
583 ++co.NumberOfSat[CLOCKORBIT_SATGALILEO];
584 }
585 else if (prn.system() == 'J') {
586 sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
587 + CLOCKORBIT_NUMGALILEO
588 + co.NumberOfSat[CLOCKORBIT_SATQZSS];
589 ++co.NumberOfSat[CLOCKORBIT_SATQZSS];
590 }
591 else if (prn.system() == 'S') {
592 sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
593 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
594 + co.NumberOfSat[CLOCKORBIT_SATSBAS];
595 ++co.NumberOfSat[CLOCKORBIT_SATSBAS];
596 }
597 else if (prn.system() == 'C') {
598 sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
599 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
600 + CLOCKORBIT_NUMSBAS
601 + co.NumberOfSat[CLOCKORBIT_SATBDS];
602 ++co.NumberOfSat[CLOCKORBIT_SATBDS];
603 }
604 if (sd) {
605 QString outLine;
606 t_irc irc = processSatellite(eph, epoTime.gpsw(), epoTime.gpssec(), prnStr, rtnAPC,
607 rtnUra, rtnClk, rtnVel, rtnCoM, rtnClkSig, sd, outLine);
608 if (irc != success) {/*
609 // very few cases: check states bad and unhealthy are excluded earlier
610 sd->ID = prnStr.mid(1).toInt(); // to prevent G00, R00 entries
611 sd->IOD = eph->IOD();
612 */
613 continue;
614 }
615 }
616
617 // Code Biases
618 // -----------
619 struct SsrCorr::CodeBias::BiasSat* biasSat = 0;
620 if (!codeBiases.isEmpty()) {
621 if (prn.system() == 'G') {
622 biasSat = bias.Sat + bias.NumberOfSat[CLOCKORBIT_SATGPS];
623 ++bias.NumberOfSat[CLOCKORBIT_SATGPS];
624 }
625 else if (prn.system() == 'R') {
626 biasSat = bias.Sat + CLOCKORBIT_NUMGPS
627 + bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
628 ++bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
629 }
630 else if (prn.system() == 'E') {
631 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
632 + bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
633 ++bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
634 }
635 else if (prn.system() == 'J') {
636 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
637 + CLOCKORBIT_NUMGALILEO
638 + bias.NumberOfSat[CLOCKORBIT_SATQZSS];
639 ++bias.NumberOfSat[CLOCKORBIT_SATQZSS];
640 }
641 else if (prn.system() == 'S') {
642 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
643 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
644 + bias.NumberOfSat[CLOCKORBIT_SATSBAS];
645 ++bias.NumberOfSat[CLOCKORBIT_SATSBAS];
646 }
647 else if (prn.system() == 'C') {
648 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
649 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
650 + CLOCKORBIT_NUMSBAS
651 + bias.NumberOfSat[CLOCKORBIT_SATBDS];
652 ++bias.NumberOfSat[CLOCKORBIT_SATBDS];
653 }
654 }
655
656 if (biasSat) {
657 biasSat->ID = prn.number();
658 biasSat->NumberOfCodeBiases = 0;
659 QMapIterator<QString, double> it(codeBiases);
660 while (it.hasNext()) {
661 it.next();
662 int ii = biasSat->NumberOfCodeBiases;
663 if (ii >= CLOCKORBIT_NUMBIAS)
664 break;
665 SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), it.key().toStdString());
666 if (type != _ssrCorr->RESERVED) {
667 biasSat->NumberOfCodeBiases += 1;
668 biasSat->Biases[ii].Type = type;
669 biasSat->Biases[ii].Bias = it.value();
670 }
671 }
672 }
673
674 // Phase Biases
675 // ------------
676 struct SsrCorr::PhaseBias::PhaseBiasSat* phasebiasSat = 0;
677 if (prn.system() == 'G') {
678 phasebiasSat = phasebias.Sat
679 + phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
680 ++phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
681 }
682 else if (prn.system() == 'R') {
683 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS
684 + phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
685 ++phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
686 }
687 else if (prn.system() == 'E') {
688 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
689 + phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
690 ++phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
691 }
692 else if (prn.system() == 'J') {
693 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
694 + CLOCKORBIT_NUMGALILEO
695 + phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
696 ++phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
697 }
698 else if (prn.system() == 'S') {
699 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
700 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
701 + phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
702 ++phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
703 }
704 else if (prn.system() == 'C') {
705 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
706 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
707 + CLOCKORBIT_NUMSBAS
708 + phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
709 ++phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
710 }
711
712 if (phasebiasSat && _phaseBiasInformationDecoded) {
713 phasebias.DispersiveBiasConsistencyIndicator = dispersiveBiasConsistenyIndicator;
714 phasebias.MWConsistencyIndicator = mwConsistencyIndicator;
715 phasebiasSat->ID = prn.number();
716 phasebiasSat->NumberOfPhaseBiases = 0;
717 phasebiasSat->YawAngle = pbSat.yawAngle;
718 phasebiasSat->YawRate = pbSat.yawRate;
719 QListIterator<phaseBiasSignal> it(phaseBiasList);
720 while (it.hasNext()) {
721 const phaseBiasSignal &pbSig = it.next();
722 int ii = phasebiasSat->NumberOfPhaseBiases;
723 if (ii >= CLOCKORBIT_NUMBIAS)
724 break;
725 SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), pbSig.type.toStdString());
726 if (type != _ssrCorr->RESERVED) {
727 phasebiasSat->NumberOfPhaseBiases += 1;
728 phasebiasSat->Biases[ii].Type = type;
729 phasebiasSat->Biases[ii].Bias = pbSig.bias;
730 phasebiasSat->Biases[ii].SignalIntegerIndicator = pbSig.integerIndicator;
731 phasebiasSat->Biases[ii].SignalsWideLaneIntegerIndicator = pbSig.wlIndicator;
732 phasebiasSat->Biases[ii].SignalDiscontinuityCounter = pbSig.discontinuityCounter;
733 }
734 }
735 }
736 }
737 }
738
739 QByteArray hlpBufferCo;
740
741 // Orbit and Clock Corrections together
742 // ------------------------------------
743 if (_samplRtcmEphCorr == 0.0) {
744 if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0
745 || co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
746 || co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
747 || co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
748 || co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
749 || co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
750 char obuffer[CLOCKORBIT_BUFFERSIZE];
751 int len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
752 if (len > 0) {
753 hlpBufferCo = QByteArray(obuffer, len);
754 }
755 }
756 }
757
758 // Orbit and Clock Corrections separately
759 // --------------------------------------
760 else {
761 if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
762 char obuffer[CLOCKORBIT_BUFFERSIZE];
763 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
764 co.UpdateInterval = ephUpdInd;
765 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSORBIT, 1, obuffer,
766 sizeof(obuffer));
767 co.UpdateInterval = clkUpdInd;
768 if (len1 > 0) {
769 hlpBufferCo += QByteArray(obuffer, len1);
770 }
771 }
772 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0 ||
773 co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
774 co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
775 co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0 ||
776 co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ) ? 1 : 0;
777 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSCLOCK, mmsg, obuffer,
778 sizeof(obuffer));
779 if (len2 > 0) {
780 hlpBufferCo += QByteArray(obuffer, len2);
781 }
782 }
783 if (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
784 char obuffer[CLOCKORBIT_BUFFERSIZE];
785 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
786 co.UpdateInterval = ephUpdInd;
787 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSORBIT, 1, obuffer,
788 sizeof(obuffer));
789 co.UpdateInterval = clkUpdInd;
790 if (len1 > 0) {
791 hlpBufferCo += QByteArray(obuffer, len1);
792 }
793 }
794 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
795 co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
796 co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0 ||
797 co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ) ? 1 : 0;
798 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSCLOCK, mmsg, obuffer,
799 sizeof(obuffer));
800 if (len2 > 0) {
801 hlpBufferCo += QByteArray(obuffer, len2);
802 }
803 }
804 if (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
805 char obuffer[CLOCKORBIT_BUFFERSIZE];
806 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
807 co.UpdateInterval = ephUpdInd;
808 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOORBIT, 1, obuffer,
809 sizeof(obuffer));
810 co.UpdateInterval = clkUpdInd;
811 if (len1 > 0) {
812 hlpBufferCo += QByteArray(obuffer, len1);
813 }
814 }
815 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
816 co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0 ||
817 co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ) ? 1 : 0;
818 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOCLOCK, mmsg, obuffer,
819 sizeof(obuffer));
820 if (len2 > 0) {
821 hlpBufferCo += QByteArray(obuffer, len2);
822 }
823 }
824 if (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
825 char obuffer[CLOCKORBIT_BUFFERSIZE];
826 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
827 co.UpdateInterval = ephUpdInd;
828 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSORBIT, 1, obuffer,
829 sizeof(obuffer));
830 co.UpdateInterval = clkUpdInd;
831 if (len1 > 0) {
832 hlpBufferCo += QByteArray(obuffer, len1);
833 }
834 }
835 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0 ||
836 co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ) ? 1 : 0;
837 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSCLOCK, mmsg, obuffer,
838 sizeof(obuffer));
839 if (len2 > 0) {
840 hlpBufferCo += QByteArray(obuffer, len2);
841 }
842 }
843 if (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
844 char obuffer[CLOCKORBIT_BUFFERSIZE];
845 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
846 co.UpdateInterval = ephUpdInd;
847 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASORBIT, 1, obuffer,
848 sizeof(obuffer));
849 co.UpdateInterval = clkUpdInd;
850 if (len1 > 0) {
851 hlpBufferCo += QByteArray(obuffer, len1);
852 }
853 }
854 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) ? 1 : 0;
855 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASCLOCK, mmsg, obuffer,
856 sizeof(obuffer));
857 if (len2 > 0) {
858 hlpBufferCo += QByteArray(obuffer, len2);
859 }
860 }
861 if (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
862 char obuffer[CLOCKORBIT_BUFFERSIZE];
863 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
864 co.UpdateInterval = ephUpdInd;
865 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSORBIT, 1, obuffer,
866 sizeof(obuffer));
867 co.UpdateInterval = clkUpdInd;
868 if (len1 > 0) {
869 hlpBufferCo += QByteArray(obuffer, len1);
870 }
871 }
872 int mmsg = 0;
873 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSCLOCK, mmsg, obuffer,
874 sizeof(obuffer));
875 if (len2 > 0) {
876 hlpBufferCo += QByteArray(obuffer, len2);
877 }
878 }
879 }
880
881 // Code Biases
882 // -----------
883 QByteArray hlpBufferBias;
884 if (bias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
885 || bias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
886 || bias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
887 || bias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
888 || bias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
889 || bias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
890 char obuffer[CLOCKORBIT_BUFFERSIZE];
891 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
892 int len = _ssrCorr->MakeCodeBias(&bias, _ssrCorr->CBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
893 if (len > 0) {
894 hlpBufferBias = QByteArray(obuffer, len);
895 }
896 }
897 }
898
899 // Phase Biases
900 // ------------
901 QByteArray hlpBufferPhaseBias;
902 if ((phasebias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
903 || phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
904 || phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
905 || phasebias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
906 || phasebias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
907 || phasebias.NumberOfSat[CLOCKORBIT_SATBDS] > 0)
908 && (_phaseBiasInformationDecoded)) {
909 char obuffer[CLOCKORBIT_BUFFERSIZE];
910 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
911 int len = _ssrCorr->MakePhaseBias(&phasebias, _ssrCorr->PBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
912 if (len > 0) {
913 hlpBufferPhaseBias = QByteArray(obuffer, len);
914 }
915 }
916 }
917
918 // VTEC
919 // ----
920 QByteArray hlpBufferVtec;
921 if (vtec.NumLayers > 0) {
922 char obuffer[CLOCKORBIT_BUFFERSIZE];
923 int len = _ssrCorr->MakeVTEC(&vtec, 0, obuffer, sizeof(obuffer));
924 if (len > 0) {
925 hlpBufferVtec = QByteArray(obuffer, len);
926 }
927 }
928
929 _outBuffer += hlpBufferCo + hlpBufferBias + hlpBufferPhaseBias
930 + hlpBufferVtec;
931}
932
933//
934////////////////////////////////////////////////////////////////////////////
935t_irc bncRtnetUploadCaster::processSatellite(const t_eph* eph, int GPSweek,
936 double GPSweeks, const QString& prn, const ColumnVector& rtnAPC,
937 double rtnUra, const ColumnVector& rtnClk, const ColumnVector& rtnVel,
938 const ColumnVector& rtnCoM, const ColumnVector& rtnClkSig,
939 struct SsrCorr::ClockOrbit::SatData* sd, QString& outLine) {
940
941 // Broadcast Position and Velocity
942 // -------------------------------
943 ColumnVector xB(6);
944 ColumnVector vB(3);
945 t_irc irc = eph->getCrd(bncTime(GPSweek, GPSweeks), xB, vB, false);
946
947 if (irc != success) {
948 return irc;
949 }
950
951 // Precise Position
952 // ----------------
953 ColumnVector xP = _CoM ? rtnCoM : rtnAPC;
954
955 if (xP.size() == 0) {
956 return failure;
957 }
958
959 double dc = 0.0;
960 if (_crdTrafo != "IGS14") {
961 crdTrafo(GPSweek, xP, dc);
962 }
963
964 // Difference in xyz
965 // -----------------
966 ColumnVector dx = xB.Rows(1, 3) - xP;
967 ColumnVector dv = vB - rtnVel;
968
969 // Difference in RSW
970 // -----------------
971 ColumnVector rsw(3);
972 XYZ_to_RSW(xB.Rows(1, 3), vB, dx, rsw);
973
974 ColumnVector dotRsw(3);
975 XYZ_to_RSW(xB.Rows(1, 3), vB, dv, dotRsw);
976
977 // Clock Correction
978 // ----------------
979 double dClkA0 = rtnClk(1) - (xB(4) - dc) * t_CST::c;
980 double dClkA1 = 0.0;
981 if (rtnClk(2)) {
982 dClkA1 = rtnClk(2) - xB(5) * t_CST::c;
983 }
984 double dClkA2 = 0.0;
985 if (rtnClk(3)) {
986 dClkA2 = rtnClk(3) - xB(6) * t_CST::c;
987 }
988
989 if (sd) {
990 sd->ID = prn.mid(1).toInt();
991 sd->IOD = eph->IOD();
992 sd->Clock.DeltaA0 = dClkA0;
993 sd->Clock.DeltaA1 = dClkA1;
994 sd->Clock.DeltaA2 = dClkA2;
995 sd->UserRangeAccuracy = rtnUra;
996 sd->Orbit.DeltaRadial = rsw(1);
997 sd->Orbit.DeltaAlongTrack = rsw(2);
998 sd->Orbit.DeltaCrossTrack = rsw(3);
999 sd->Orbit.DotDeltaRadial = dotRsw(1);
1000 sd->Orbit.DotDeltaAlongTrack = dotRsw(2);
1001 sd->Orbit.DotDeltaCrossTrack = dotRsw(3);
1002
1003 if (corrIsOutOfRange(sd)) {
1004 return failure;
1005 }
1006 }
1007
1008 outLine.sprintf("%d %.1f %s %u %10.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n", GPSweek,
1009 GPSweeks, eph->prn().toString().c_str(), eph->IOD(), dClkA0, dClkA1, dClkA2,
1010 rsw(1), rsw(2), rsw(3)); //fprintf(stderr, "%s\n", outLine.toStdString().c_str());
1011
1012 // RTNET full clock for RINEX and SP3 file
1013 // ---------------------------------------
1014 double relativity = -2.0 * DotProduct(xP, rtnVel) / t_CST::c;
1015 double clkRnx = (rtnClk[0] - relativity) / t_CST::c; // [s]
1016 double clkRnxRate = rtnClk[1] / t_CST::c; // [s/s = -]
1017 double clkRnxAcc = rtnClk[2] / t_CST::c; // [s/s² ) -/s]
1018
1019 if (_rnx) {
1020 double clkRnxSig, clkRnxRateSig, clkRnxAccSig;
1021 int s = rtnClkSig.size();
1022 switch (s) {
1023 case 1:
1024 clkRnxSig = rtnClkSig[0] / t_CST::c; // [s]
1025 clkRnxRateSig = 0.0; // [s/s = -]
1026 clkRnxAccSig = 0.0; // [s/s² ) -/s]
1027 break;
1028 case 2:
1029 clkRnxSig = rtnClkSig[0] / t_CST::c; // [s]
1030 clkRnxRateSig = rtnClkSig[1] / t_CST::c; // [s/s = -]
1031 clkRnxAccSig = 0.0; // [s/s² ) -/s]
1032 break;
1033 case 3:
1034 clkRnxSig = rtnClkSig[0] / t_CST::c; // [s]
1035 clkRnxRateSig = rtnClkSig[1] / t_CST::c; // [s/s = -]
1036 clkRnxAccSig = rtnClkSig[2] / t_CST::c; // [s/s² ) -/s]
1037 break;
1038 }
1039 _rnx->write(GPSweek, GPSweeks, prn, clkRnx, clkRnxRate, clkRnxAcc,
1040 clkRnxSig, clkRnxRateSig, clkRnxAccSig);
1041 }
1042 if (_sp3) {
1043 _sp3->write(GPSweek, GPSweeks, prn, rtnCoM, clkRnx, rtnVel, clkRnxRate);
1044 }
1045 return success;
1046}
1047
1048// Transform Coordinates
1049////////////////////////////////////////////////////////////////////////////
1050void bncRtnetUploadCaster::crdTrafo(int GPSWeek, ColumnVector& xyz,
1051 double& dc) {
1052
1053 // Current epoch minus 2000.0 in years
1054 // ------------------------------------
1055 double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
1056
1057 ColumnVector dx(3);
1058
1059 dx(1) = _dx + dt * _dxr;
1060 dx(2) = _dy + dt * _dyr;
1061 dx(3) = _dz + dt * _dzr;
1062
1063 static const double arcSec = 180.0 * 3600.0 / M_PI;
1064
1065 double ox = (_ox + dt * _oxr) / arcSec;
1066 double oy = (_oy + dt * _oyr) / arcSec;
1067 double oz = (_oz + dt * _ozr) / arcSec;
1068
1069 double sc = 1.0 + _sc * 1e-9 + dt * _scr * 1e-9;
1070
1071 // Specify approximate center of area
1072 // ----------------------------------
1073 ColumnVector meanSta(3);
1074
1075 if (_crdTrafo == "ETRF2000") {
1076 meanSta(1) = 3661090.0;
1077 meanSta(2) = 845230.0;
1078 meanSta(3) = 5136850.0;
1079 }
1080 else if (_crdTrafo == "GDA2020") {
1081 meanSta(1) = -4052050.0;
1082 meanSta(2) = 4212840.0;
1083 meanSta(3) = -2545110.0;
1084 }
1085 else if (_crdTrafo == "SIRGAS2000") {
1086 meanSta(1) = 3740860.0;
1087 meanSta(2) = -4964290.0;
1088 meanSta(3) = -1425420.0;
1089 }
1090 else if (_crdTrafo == "DREF91") {
1091 meanSta(1) = 3959579.0;
1092 meanSta(2) = 721719.0;
1093 meanSta(3) = 4931539.0;
1094 }
1095 else if (_crdTrafo == "Custom") {
1096 meanSta(1) = 0.0; // TODO
1097 meanSta(2) = 0.0; // TODO
1098 meanSta(3) = 0.0; // TODO
1099 }
1100
1101 // Clock correction proportional to topocentric distance to satellites
1102 // -------------------------------------------------------------------
1103 double rho = (xyz - meanSta).NormFrobenius();
1104 dc = rho * (sc - 1.0) / sc / t_CST::c;
1105
1106 Matrix rMat(3, 3);
1107 rMat(1, 1) = 1.0;
1108 rMat(1, 2) = -oz;
1109 rMat(1, 3) = oy;
1110 rMat(2, 1) = oz;
1111 rMat(2, 2) = 1.0;
1112 rMat(2, 3) = -ox;
1113 rMat(3, 1) = -oy;
1114 rMat(3, 2) = ox;
1115 rMat(3, 3) = 1.0;
1116
1117 xyz = sc * rMat * xyz + dx;
1118}
1119
1120int bncRtnetUploadCaster::determineUpdateInd(double samplingRate) {
1121
1122 if (samplingRate == 10.0) {
1123 return 3;
1124 }
1125 else if (samplingRate == 15.0) {
1126 return 4;
1127 }
1128 else if (samplingRate == 30.0) {
1129 return 5;
1130 }
1131 else if (samplingRate == 60.0) {
1132 return 6;
1133 }
1134 else if (samplingRate == 120.0) {
1135 return 7;
1136 }
1137 else if (samplingRate == 240.0) {
1138 return 8;
1139 }
1140 else if (samplingRate == 300.0) {
1141 return 9;
1142 }
1143 else if (samplingRate == 600.0) {
1144 return 10;
1145 }
1146 else if (samplingRate == 900.0) {
1147 return 11;
1148 }
1149 else if (samplingRate == 1800.0) {
1150 return 12;
1151 }
1152 else if (samplingRate == 3600.0) {
1153 return 13;
1154 }
1155 else if (samplingRate == 7200.0) {
1156 return 14;
1157 }
1158 else if (samplingRate == 10800.0) {
1159 return 15;
1160 }
1161 return 2; // default
1162}
1163
1164bool bncRtnetUploadCaster::corrIsOutOfRange(struct SsrCorr::ClockOrbit::SatData* sd) {
1165
1166 if (fabs(sd->Clock.DeltaA0) > 209.7151) {return true;}
1167 if (fabs(sd->Clock.DeltaA1) > 1.048575) {return true;}
1168 if (fabs(sd->Clock.DeltaA2) > 1.34217726) {return true;}
1169
1170 if (fabs(sd->Orbit.DeltaRadial) > 209.7151) {return true;}
1171 if (fabs(sd->Orbit.DeltaAlongTrack) > 209.7148) {return true;}
1172 if (fabs(sd->Orbit.DeltaCrossTrack) > 209.7148) {return true;}
1173
1174 if (fabs(sd->Orbit.DotDeltaRadial) > 1.048575) {return true;}
1175 if (fabs(sd->Orbit.DotDeltaAlongTrack) > 1.048572) {return true;}
1176 if (fabs(sd->Orbit.DotDeltaCrossTrack) > 1.048572) {return true;}
1177
1178 return false;
1179}
1180
Note: See TracBrowser for help on using the repository browser.