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

Last change on this file since 9868 was 9868, checked in by stuerze, 18 months ago

minor changes

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