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

Last change on this file since 9081 was 9081, checked in by stuerze, 9 months ago

minor changes

File size: 37.1 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") {
60    _ssrCorr = new SsrCorrIgs();
61  }
62  else if (_ssrFormat == "RTCM-SSR") {
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.