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

Last change on this file since 9249 was 9249, checked in by stuerze, 20 months ago

another check is added, to prevent the usage of not updated nav data sets during ssr upload

File size: 38.6 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#include "bncutils.h"
25
26using namespace std;
27
28// Constructor
29////////////////////////////////////////////////////////////////////////////
30bncRtnetUploadCaster::bncRtnetUploadCaster(const QString& mountpoint,
31 const QString& outHost, int outPort,
32 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, 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].toAscii());
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.toAscii(), 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;
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].toAscii());
396 in >> key;
397
398 // non-satellite specific parameters
399 if (key.contains("IND", Qt::CaseSensitive)) {
400 in >> dispersiveBiasConsistenyIndicator >> mwConsistencyIndicator;
401 continue;
402 }
403 // non-satellite specific parameters
404 if (key.contains("VTEC", Qt::CaseSensitive)) {
405 double ui;
406 in >> ui >> vtec.NumLayers;
407 vtec.UpdateInterval = (unsigned int) determineUpdateInd(ui);
408 for (unsigned ll = 0; ll < vtec.NumLayers; ll++) {
409 int dummy;
410 in >> dummy >> vtec.Layers[ll].Degree >> vtec.Layers[ll].Order
411 >> vtec.Layers[ll].Height;
412 for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
413 for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
414 in >> vtec.Layers[ll].Cosinus[iDeg][iOrd];
415 }
416 }
417 for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
418 for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
419 in >> vtec.Layers[ll].Sinus[iDeg][iOrd];
420 }
421 }
422 }
423 continue;
424 }
425 // satellite specific parameters
426 char sys = key.mid(0, 1).at(0).toAscii();
427 int number = key.mid(1, 2).toInt();
428 int flags = 0;
429 if (sys == 'E') { // I/NAV
430 flags = 1;
431 }
432 prn.set(sys, number, flags);
433 QString prnInternalStr = QString::fromStdString(prn.toInternalString());
434 QString prnStr = QString::fromStdString(prn.toString());
435
436 const t_eph* ephLast = _ephUser->ephLast(prnInternalStr);
437 const t_eph* ephPrev = _ephUser->ephPrev(prnInternalStr);
438 const t_eph* eph = ephLast;
439 if (eph) {
440
441 // Use previous ephemeris if the last one is too recent
442 // ----------------------------------------------------
443 const int MINAGE = 60; // seconds
444 if (ephPrev && eph->receptDateTime().isValid()
445 && eph->receptDateTime().secsTo(currentDateAndTimeGPS()) < MINAGE) {
446 eph = ephPrev;
447 }
448
449 // Make sure the clock messages refer to same IOD as orbit messages
450 // ----------------------------------------------------------------
451 if (_usedEph) {
452 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
453 (*_usedEph)[prnInternalStr] = eph;
454 }
455 else {
456 eph = 0;
457 if (_usedEph->contains(prnInternalStr)) {
458 const t_eph* usedEph = _usedEph->value(prnInternalStr);
459 if (usedEph == ephLast) {
460 eph = ephLast;
461 }
462 else if (usedEph == ephPrev) {
463 eph = ephPrev;
464 }
465 }
466 }
467 }
468 }
469
470 if (eph && !outDatedBcep(eph) && // detected from storage because of no update
471 eph->checkState() != t_eph::bad &&
472 eph->checkState() != t_eph::unhealthy &&
473 eph->checkState() != t_eph::outdated) { // detected during reception (bncephuser)
474 QMap<QString, double> codeBiases;
475 QList<phaseBiasSignal> phaseBiasList;
476 phaseBiasesSat pbSat;
477 _phaseBiasInformationDecoded = false;
478
479 while (true) {
480 QString key;
481 int numVal = 0;
482 in >> key;
483 if (in.status() != QTextStream::Ok) {
484 break;
485 }
486 if (key == "APC") {
487 in >> numVal;
488 rtnAPC.ReSize(3); rtnAPC = 0.0;
489 for (int ii = 0; ii < numVal; ii++) {
490 in >> rtnAPC[ii];
491 }
492 }
493 else if (key == "Ura") {
494 in >> numVal;
495 if (numVal == 1)
496 in >> rtnUra;
497 }
498 else if (key == "Clk") {
499 in >> numVal;
500 rtnClk.ReSize(3); rtnClk = 0.0;
501 for (int ii = 0; ii < numVal; ii++) {
502 in >> rtnClk[ii];
503 }
504 }
505 else if (key == "ClkSig") {
506 in >> numVal;
507 rtnClkSig.ReSize(3); rtnClkSig = 0.0;
508 for (int ii = 0; ii < numVal; ii++) {
509 in >> rtnClkSig[ii];
510 }
511 }
512 else if (key == "Vel") {
513 in >> numVal;
514 rtnVel.ReSize(3); rtnVel = 0.0;
515 for (int ii = 0; ii < numVal; ii++) {
516 in >> rtnVel[ii];
517 }
518 }
519 else if (key == "CoM") {
520 in >> numVal;
521 rtnCoM.ReSize(3); rtnCoM = 0.0;
522 for (int ii = 0; ii < numVal; ii++) {
523 in >> rtnCoM[ii];
524 }
525 }
526 else if (key == "CodeBias") {
527 in >> numVal;
528 for (int ii = 0; ii < numVal; ii++) {
529 QString type;
530 double value;
531 in >> type >> value;
532 codeBiases[type] = value;
533 }
534 }
535 else if (key == "YawAngle") {
536 _phaseBiasInformationDecoded = true;
537 in >> numVal >> pbSat.yawAngle;
538 if (pbSat.yawAngle < 0.0) {
539 pbSat.yawAngle += (2*M_PI);
540 }
541 else if (pbSat.yawAngle > 2*M_PI) {
542 pbSat.yawAngle -= (2*M_PI);
543 }
544 }
545 else if (key == "YawRate") {
546 _phaseBiasInformationDecoded = true;
547 in >> numVal >> pbSat.yawRate;
548 }
549 else if (key == "PhaseBias") {
550 _phaseBiasInformationDecoded = true;
551 in >> numVal;
552 for (int ii = 0; ii < numVal; ii++) {
553 phaseBiasSignal pb;
554 in >> pb.type >> pb.bias >> pb.integerIndicator
555 >> pb.wlIndicator >> pb.discontinuityCounter;
556 phaseBiasList.append(pb);
557 }
558 }
559 else {
560 in >> numVal;
561 for (int ii = 0; ii < numVal; ii++) {
562 double dummy;
563 in >> dummy;
564 }
565 emit(newMessage(" RTNET format error: "
566 + lines[ii].toAscii(), false));
567 }
568 }
569
570 struct SsrCorr::ClockOrbit::SatData* sd = 0;
571 if (prn.system() == 'G') {
572 sd = co.Sat + co.NumberOfSat[CLOCKORBIT_SATGPS];
573 ++co.NumberOfSat[CLOCKORBIT_SATGPS];
574 }
575 else if (prn.system() == 'R') {
576 sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfSat[CLOCKORBIT_SATGLONASS];
577 ++co.NumberOfSat[CLOCKORBIT_SATGLONASS];
578 }
579 else if (prn.system() == 'E') {
580 sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
581 + co.NumberOfSat[CLOCKORBIT_SATGALILEO];
582 ++co.NumberOfSat[CLOCKORBIT_SATGALILEO];
583 }
584 else if (prn.system() == 'J') {
585 sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
586 + CLOCKORBIT_NUMGALILEO
587 + co.NumberOfSat[CLOCKORBIT_SATQZSS];
588 ++co.NumberOfSat[CLOCKORBIT_SATQZSS];
589 }
590 else if (prn.system() == 'S') {
591 sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
592 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
593 + co.NumberOfSat[CLOCKORBIT_SATSBAS];
594 ++co.NumberOfSat[CLOCKORBIT_SATSBAS];
595 }
596 else if (prn.system() == 'C') {
597 sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
598 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
599 + CLOCKORBIT_NUMSBAS
600 + co.NumberOfSat[CLOCKORBIT_SATBDS];
601 ++co.NumberOfSat[CLOCKORBIT_SATBDS];
602 }
603 if (sd) {
604 QString outLine;
605 t_irc irc = processSatellite(eph, epoTime.gpsw(), epoTime.gpssec(), prnStr, rtnAPC,
606 rtnUra, rtnClk, rtnVel, rtnCoM, rtnClkSig, sd, outLine);
607 if (irc != success) {/*
608 // very few cases: check states bad and unhealthy are excluded earlier
609 sd->ID = prnStr.mid(1).toInt(); // to prevent G00, R00 entries
610 sd->IOD = eph->IOD();
611 */
612 continue;
613 }
614 }
615
616 // Code Biases
617 // -----------
618 struct SsrCorr::CodeBias::BiasSat* biasSat = 0;
619 if (!codeBiases.isEmpty()) {
620 if (prn.system() == 'G') {
621 biasSat = bias.Sat + bias.NumberOfSat[CLOCKORBIT_SATGPS];
622 ++bias.NumberOfSat[CLOCKORBIT_SATGPS];
623 }
624 else if (prn.system() == 'R') {
625 biasSat = bias.Sat + CLOCKORBIT_NUMGPS
626 + bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
627 ++bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
628 }
629 else if (prn.system() == 'E') {
630 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
631 + bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
632 ++bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
633 }
634 else if (prn.system() == 'J') {
635 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
636 + CLOCKORBIT_NUMGALILEO
637 + bias.NumberOfSat[CLOCKORBIT_SATQZSS];
638 ++bias.NumberOfSat[CLOCKORBIT_SATQZSS];
639 }
640 else if (prn.system() == 'S') {
641 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
642 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
643 + bias.NumberOfSat[CLOCKORBIT_SATSBAS];
644 ++bias.NumberOfSat[CLOCKORBIT_SATSBAS];
645 }
646 else if (prn.system() == 'C') {
647 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
648 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
649 + CLOCKORBIT_NUMSBAS
650 + bias.NumberOfSat[CLOCKORBIT_SATBDS];
651 ++bias.NumberOfSat[CLOCKORBIT_SATBDS];
652 }
653 }
654
655 if (biasSat) {
656 biasSat->ID = prn.number();
657 biasSat->NumberOfCodeBiases = 0;
658 QMapIterator<QString, double> it(codeBiases);
659 while (it.hasNext()) {
660 it.next();
661 int ii = biasSat->NumberOfCodeBiases;
662 if (ii >= CLOCKORBIT_NUMBIAS)
663 break;
664 SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), it.key().toStdString());
665 if (type != _ssrCorr->RESERVED) {
666 biasSat->NumberOfCodeBiases += 1;
667 biasSat->Biases[ii].Type = type;
668 biasSat->Biases[ii].Bias = it.value();
669 }
670 }
671 }
672
673 // Phase Biases
674 // ------------
675 struct SsrCorr::PhaseBias::PhaseBiasSat* phasebiasSat = 0;
676 if (prn.system() == 'G') {
677 phasebiasSat = phasebias.Sat
678 + phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
679 ++phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
680 }
681 else if (prn.system() == 'R') {
682 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS
683 + phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
684 ++phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
685 }
686 else if (prn.system() == 'E') {
687 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
688 + phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
689 ++phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
690 }
691 else if (prn.system() == 'J') {
692 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
693 + CLOCKORBIT_NUMGALILEO
694 + phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
695 ++phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
696 }
697 else if (prn.system() == 'S') {
698 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
699 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
700 + phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
701 ++phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
702 }
703 else if (prn.system() == 'C') {
704 phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
705 + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
706 + CLOCKORBIT_NUMSBAS
707 + phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
708 ++phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
709 }
710
711 if (phasebiasSat && _phaseBiasInformationDecoded) {
712 phasebias.DispersiveBiasConsistencyIndicator = dispersiveBiasConsistenyIndicator;
713 phasebias.MWConsistencyIndicator = mwConsistencyIndicator;
714 phasebiasSat->ID = prn.number();
715 phasebiasSat->NumberOfPhaseBiases = 0;
716 phasebiasSat->YawAngle = pbSat.yawAngle;
717 phasebiasSat->YawRate = pbSat.yawRate;
718 QListIterator<phaseBiasSignal> it(phaseBiasList);
719 while (it.hasNext()) {
720 const phaseBiasSignal &pbSig = it.next();
721 int ii = phasebiasSat->NumberOfPhaseBiases;
722 if (ii >= CLOCKORBIT_NUMBIAS)
723 break;
724 SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), pbSig.type.toStdString());
725 if (type != _ssrCorr->RESERVED) {
726 phasebiasSat->NumberOfPhaseBiases += 1;
727 phasebiasSat->Biases[ii].Type = type;
728 phasebiasSat->Biases[ii].Bias = pbSig.bias;
729 phasebiasSat->Biases[ii].SignalIntegerIndicator = pbSig.integerIndicator;
730 phasebiasSat->Biases[ii].SignalsWideLaneIntegerIndicator = pbSig.wlIndicator;
731 phasebiasSat->Biases[ii].SignalDiscontinuityCounter = pbSig.discontinuityCounter;
732 }
733 }
734 }
735 }
736 }
737
738 QByteArray hlpBufferCo;
739
740 // Orbit and Clock Corrections together
741 // ------------------------------------
742 if (_samplRtcmEphCorr == 0.0) {
743 if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0
744 || co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
745 || co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
746 || co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
747 || co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
748 || co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
749 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
750 int len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
751 if (len > 0) {
752 hlpBufferCo = QByteArray(obuffer, len);
753 }
754 }
755 }
756
757 // Orbit and Clock Corrections separately
758 // --------------------------------------
759 else {
760 if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
761 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
762 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
763 co.UpdateInterval = ephUpdInd;
764 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSORBIT, 1, obuffer,
765 sizeof(obuffer));
766 co.UpdateInterval = clkUpdInd;
767 if (len1 > 0) {
768 hlpBufferCo += QByteArray(obuffer, len1);
769 }
770 }
771 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0 ||
772 co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
773 co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
774 co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0 ||
775 co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ) ? 1 : 0;
776 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSCLOCK, mmsg, obuffer,
777 sizeof(obuffer));
778 if (len2 > 0) {
779 hlpBufferCo += QByteArray(obuffer, len2);
780 }
781 }
782 if (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
783 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
784 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
785 co.UpdateInterval = ephUpdInd;
786 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSORBIT, 1, obuffer,
787 sizeof(obuffer));
788 co.UpdateInterval = clkUpdInd;
789 if (len1 > 0) {
790 hlpBufferCo += QByteArray(obuffer, len1);
791 }
792 }
793 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
794 co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
795 co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0 ||
796 co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ) ? 1 : 0;
797 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSCLOCK, mmsg, obuffer,
798 sizeof(obuffer));
799 if (len2 > 0) {
800 hlpBufferCo += QByteArray(obuffer, len2);
801 }
802 }
803 if (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
804 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
805 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
806 co.UpdateInterval = ephUpdInd;
807 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOORBIT, 1, obuffer,
808 sizeof(obuffer));
809 co.UpdateInterval = clkUpdInd;
810 if (len1 > 0) {
811 hlpBufferCo += QByteArray(obuffer, len1);
812 }
813 }
814 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
815 co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0 ||
816 co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ) ? 1 : 0;
817 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOCLOCK, mmsg, obuffer,
818 sizeof(obuffer));
819 if (len2 > 0) {
820 hlpBufferCo += QByteArray(obuffer, len2);
821 }
822 }
823 if (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
824 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
825 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
826 co.UpdateInterval = ephUpdInd;
827 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSORBIT, 1, obuffer,
828 sizeof(obuffer));
829 co.UpdateInterval = clkUpdInd;
830 if (len1 > 0) {
831 hlpBufferCo += QByteArray(obuffer, len1);
832 }
833 }
834 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0 ||
835 co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ) ? 1 : 0;
836 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSCLOCK, mmsg, obuffer,
837 sizeof(obuffer));
838 if (len2 > 0) {
839 hlpBufferCo += QByteArray(obuffer, len2);
840 }
841 }
842 if (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
843 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
844 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
845 co.UpdateInterval = ephUpdInd;
846 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASORBIT, 1, obuffer,
847 sizeof(obuffer));
848 co.UpdateInterval = clkUpdInd;
849 if (len1 > 0) {
850 hlpBufferCo += QByteArray(obuffer, len1);
851 }
852 }
853 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) ? 1 : 0;
854 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASCLOCK, mmsg, obuffer,
855 sizeof(obuffer));
856 if (len2 > 0) {
857 hlpBufferCo += QByteArray(obuffer, len2);
858 }
859 }
860 if (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
861 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
862 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
863 co.UpdateInterval = ephUpdInd;
864 int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSORBIT, 1, obuffer,
865 sizeof(obuffer));
866 co.UpdateInterval = clkUpdInd;
867 if (len1 > 0) {
868 hlpBufferCo += QByteArray(obuffer, len1);
869 }
870 }
871 int mmsg = 0;
872 int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSCLOCK, mmsg, obuffer,
873 sizeof(obuffer));
874 if (len2 > 0) {
875 hlpBufferCo += QByteArray(obuffer, len2);
876 }
877 }
878 }
879
880 // Code Biases
881 // -----------
882 QByteArray hlpBufferBias;
883 if (bias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
884 || bias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
885 || bias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
886 || bias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
887 || bias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
888 || bias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
889 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
890 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
891 int len = _ssrCorr->MakeCodeBias(&bias, _ssrCorr->CBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
892 if (len > 0) {
893 hlpBufferBias = QByteArray(obuffer, len);
894 }
895 }
896 }
897
898 // Phase Biases
899 // ------------
900 QByteArray hlpBufferPhaseBias;
901 if ((phasebias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
902 || phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
903 || phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
904 || phasebias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
905 || phasebias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
906 || phasebias.NumberOfSat[CLOCKORBIT_SATBDS] > 0)
907 && (_phaseBiasInformationDecoded)) {
908 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
909 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
910 int len = _ssrCorr->MakePhaseBias(&phasebias, _ssrCorr->PBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
911 if (len > 0) {
912 hlpBufferPhaseBias = QByteArray(obuffer, len);
913 }
914 }
915 }
916
917 // VTEC
918 // ----
919 QByteArray hlpBufferVtec;
920 if (vtec.NumLayers > 0) {
921 char obuffer[CLOCKORBIT_BUFFERSIZE] = {0};
922 int len = _ssrCorr->MakeVTEC(&vtec, 0, obuffer, sizeof(obuffer));
923 if (len > 0) {
924 hlpBufferVtec = QByteArray(obuffer, len);
925 }
926 }
927
928 _outBuffer += hlpBufferCo + hlpBufferBias + hlpBufferPhaseBias
929 + hlpBufferVtec + '\0';
930}
931
932//
933////////////////////////////////////////////////////////////////////////////
934t_irc bncRtnetUploadCaster::processSatellite(const t_eph* eph, int GPSweek,
935 double GPSweeks, const QString& prn, const ColumnVector& rtnAPC,
936 double rtnUra, const ColumnVector& rtnClk, const ColumnVector& rtnVel,
937 const ColumnVector& rtnCoM, const ColumnVector& rtnClkSig,
938 struct SsrCorr::ClockOrbit::SatData* sd, QString& outLine) {
939
940 // Broadcast Position and Velocity
941 // -------------------------------
942 ColumnVector xB(6);
943 ColumnVector vB(3);
944 t_irc irc = eph->getCrd(bncTime(GPSweek, GPSweeks), xB, vB, false);
945
946 if (irc != success) {
947 return irc;
948 }
949
950 // Precise Position
951 // ----------------
952 ColumnVector xP = _CoM ? rtnCoM : rtnAPC;
953
954 if (xP.size() == 0) {
955 return failure;
956 }
957
958 double dc = 0.0;
959 if (_crdTrafo != "IGS14") {
960 crdTrafo(GPSweek, xP, dc);
961 }
962
963 // Difference in xyz
964 // -----------------
965 ColumnVector dx = xB.Rows(1, 3) - xP;
966 ColumnVector dv = vB - rtnVel;
967
968 // Difference in RSW
969 // -----------------
970 ColumnVector rsw(3);
971 XYZ_to_RSW(xB.Rows(1, 3), vB, dx, rsw);
972
973 ColumnVector dotRsw(3);
974 XYZ_to_RSW(xB.Rows(1, 3), vB, dv, dotRsw);
975
976 // Clock Correction
977 // ----------------
978 double dClkA0 = rtnClk(1) - (xB(4) - dc) * t_CST::c;
979 double dClkA1 = 0.0;
980 if (rtnClk(2)) {
981 dClkA1 = rtnClk(2) - xB(5) * t_CST::c;
982 }
983 double dClkA2 = 0.0;
984 if (rtnClk(3)) {
985 dClkA2 = rtnClk(3) - xB(6) * t_CST::c;
986 }
987
988 if (sd) {
989 sd->ID = prn.mid(1).toInt();
990 sd->IOD = eph->IOD();
991 sd->Clock.DeltaA0 = dClkA0;
992 sd->Clock.DeltaA1 = dClkA1;
993 sd->Clock.DeltaA2 = dClkA2;
994 sd->UserRangeAccuracy = rtnUra;
995 sd->Orbit.DeltaRadial = rsw(1);
996 sd->Orbit.DeltaAlongTrack = rsw(2);
997 sd->Orbit.DeltaCrossTrack = rsw(3);
998 sd->Orbit.DotDeltaRadial = dotRsw(1);
999 sd->Orbit.DotDeltaAlongTrack = dotRsw(2);
1000 sd->Orbit.DotDeltaCrossTrack = dotRsw(3);
1001
1002 if (corrIsOutOfRange(sd)) {
1003 return failure;
1004 }
1005 }
1006
1007 outLine.sprintf("%d %.1f %s %u %10.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n", GPSweek,
1008 GPSweeks, eph->prn().toString().c_str(), eph->IOD(), dClkA0, dClkA1, dClkA2,
1009 rsw(1), rsw(2), rsw(3)); //fprintf(stderr, "%s\n", outLine.toStdString().c_str());
1010
1011 // RTNET full clock for RINEX and SP3 file
1012 // ---------------------------------------
1013 double relativity = -2.0 * DotProduct(xP, rtnVel) / t_CST::c;
1014 double clkRnx = (rtnClk[0] - relativity) / t_CST::c; // [s]
1015 double clkRnxRate = rtnClk[1] / t_CST::c; // [s/s = -]
1016 double clkRnxAcc = rtnClk[2] / t_CST::c; // [s/s² ) -/s]
1017
1018 if (_rnx) {
1019 double clkRnxSig, clkRnxRateSig, clkRnxAccSig;
1020 int s = rtnClkSig.size();
1021 switch (s) {
1022 case 1:
1023 clkRnxSig = rtnClkSig[0] / t_CST::c; // [s]
1024 clkRnxRateSig = 0.0; // [s/s = -]
1025 clkRnxAccSig = 0.0; // [s/s² ) -/s]
1026 break;
1027 case 2:
1028 clkRnxSig = rtnClkSig[0] / t_CST::c; // [s]
1029 clkRnxRateSig = rtnClkSig[1] / t_CST::c; // [s/s = -]
1030 clkRnxAccSig = 0.0; // [s/s² ) -/s]
1031 break;
1032 case 3:
1033 clkRnxSig = rtnClkSig[0] / t_CST::c; // [s]
1034 clkRnxRateSig = rtnClkSig[1] / t_CST::c; // [s/s = -]
1035 clkRnxAccSig = rtnClkSig[2] / t_CST::c; // [s/s² ) -/s]
1036 break;
1037 }
1038 _rnx->write(GPSweek, GPSweeks, prn, clkRnx, clkRnxRate, clkRnxAcc,
1039 clkRnxSig, clkRnxRateSig, clkRnxAccSig);
1040 }
1041 if (_sp3) {
1042 _sp3->write(GPSweek, GPSweeks, prn, rtnCoM, clkRnx, rtnVel, clkRnxRate);
1043 }
1044 return success;
1045}
1046
1047// Transform Coordinates
1048////////////////////////////////////////////////////////////////////////////
1049void bncRtnetUploadCaster::crdTrafo(int GPSWeek, ColumnVector& xyz,
1050 double& dc) {
1051
1052 // Current epoch minus 2000.0 in years
1053 // ------------------------------------
1054 double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
1055
1056 ColumnVector dx(3);
1057
1058 dx(1) = _dx + dt * _dxr;
1059 dx(2) = _dy + dt * _dyr;
1060 dx(3) = _dz + dt * _dzr;
1061
1062 static const double arcSec = 180.0 * 3600.0 / M_PI;
1063
1064 double ox = (_ox + dt * _oxr) / arcSec;
1065 double oy = (_oy + dt * _oyr) / arcSec;
1066 double oz = (_oz + dt * _ozr) / arcSec;
1067
1068 double sc = 1.0 + _sc * 1e-9 + dt * _scr * 1e-9;
1069
1070 // Specify approximate center of area
1071 // ----------------------------------
1072 ColumnVector meanSta(3);
1073
1074 if (_crdTrafo == "ETRF2000") {
1075 meanSta(1) = 3661090.0;
1076 meanSta(2) = 845230.0;
1077 meanSta(3) = 5136850.0;
1078 }
1079 else if (_crdTrafo == "GDA2020") {
1080 meanSta(1) = -4052050.0;
1081 meanSta(2) = 4212840.0;
1082 meanSta(3) = -2545110.0;
1083 }
1084 else if (_crdTrafo == "SIRGAS2000") {
1085 meanSta(1) = 3740860.0;
1086 meanSta(2) = -4964290.0;
1087 meanSta(3) = -1425420.0;
1088 }
1089 else if (_crdTrafo == "DREF91") {
1090 meanSta(1) = 3959579.0;
1091 meanSta(2) = 721719.0;
1092 meanSta(3) = 4931539.0;
1093 }
1094 else if (_crdTrafo == "Custom") {
1095 meanSta(1) = 0.0; // TODO
1096 meanSta(2) = 0.0; // TODO
1097 meanSta(3) = 0.0; // TODO
1098 }
1099
1100 // Clock correction proportional to topocentric distance to satellites
1101 // -------------------------------------------------------------------
1102 double rho = (xyz - meanSta).norm_Frobenius();
1103 dc = rho * (sc - 1.0) / sc / t_CST::c;
1104
1105 Matrix rMat(3, 3);
1106 rMat(1, 1) = 1.0;
1107 rMat(1, 2) = -oz;
1108 rMat(1, 3) = oy;
1109 rMat(2, 1) = oz;
1110 rMat(2, 2) = 1.0;
1111 rMat(2, 3) = -ox;
1112 rMat(3, 1) = -oy;
1113 rMat(3, 2) = ox;
1114 rMat(3, 3) = 1.0;
1115
1116 xyz = sc * rMat * xyz + dx;
1117}
1118
1119int bncRtnetUploadCaster::determineUpdateInd(double samplingRate) {
1120
1121 if (samplingRate == 10.0) {
1122 return 3;
1123 }
1124 else if (samplingRate == 15.0) {
1125 return 4;
1126 }
1127 else if (samplingRate == 30.0) {
1128 return 5;
1129 }
1130 else if (samplingRate == 60.0) {
1131 return 6;
1132 }
1133 else if (samplingRate == 120.0) {
1134 return 7;
1135 }
1136 else if (samplingRate == 240.0) {
1137 return 8;
1138 }
1139 else if (samplingRate == 300.0) {
1140 return 9;
1141 }
1142 else if (samplingRate == 600.0) {
1143 return 10;
1144 }
1145 else if (samplingRate == 900.0) {
1146 return 11;
1147 }
1148 else if (samplingRate == 1800.0) {
1149 return 12;
1150 }
1151 else if (samplingRate == 3600.0) {
1152 return 13;
1153 }
1154 else if (samplingRate == 7200.0) {
1155 return 14;
1156 }
1157 else if (samplingRate == 10800.0) {
1158 return 15;
1159 }
1160 return 2; // default
1161}
1162
1163bool bncRtnetUploadCaster::corrIsOutOfRange(struct SsrCorr::ClockOrbit::SatData* sd) {
1164
1165 if (fabs(sd->Clock.DeltaA0) > 209.7151) {return true;}
1166 if (fabs(sd->Clock.DeltaA1) > 1.048575) {return true;}
1167 if (fabs(sd->Clock.DeltaA2) > 1.34217726) {return true;}
1168
1169 if (fabs(sd->Orbit.DeltaRadial) > 209.7151) {return true;}
1170 if (fabs(sd->Orbit.DeltaAlongTrack) > 209.7148) {return true;}
1171 if (fabs(sd->Orbit.DeltaCrossTrack) > 209.7148) {return true;}
1172
1173 if (fabs(sd->Orbit.DotDeltaRadial) > 1.048575) {return true;}
1174 if (fabs(sd->Orbit.DotDeltaAlongTrack) > 1.048572) {return true;}
1175 if (fabs(sd->Orbit.DotDeltaCrossTrack) > 1.048572) {return true;}
1176
1177 return false;
1178}
Note: See TracBrowser for help on using the repository browser.