source: ntrip/branches/BNC_2.12/src/upload/bncrtnetuploadcaster.cpp@ 9180

Last change on this file since 9180 was 9180, checked in by stuerze, 21 months ago

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

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