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

Last change on this file since 9036 was 9036, checked in by stuerze, 4 years ago

some modification to allow encoding and decoding of SSR corrections in RTCM-SSR and IGS-SSR formats

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