source: ntrip/trunk/BNC/src/ephemeris.cpp@ 10539

Last change on this file since 10539 was 10533, checked in by stuerze, 3 days ago

Service and RTCM CRS encoding and decoding as well as Helmert parameter decoding added + some re-organisation

File size: 70.9 KB
RevLine 
[1025]1#include <sstream>
[2234]2#include <iostream>
[1025]3#include <iomanip>
[1239]4#include <cstring>
[1025]5
[2234]6#include <newmatio.h>
7
[1025]8#include "ephemeris.h"
[2221]9#include "bncutils.h"
[2285]10#include "bnctime.h"
[5070]11#include "bnccore.h"
[5839]12#include "bncutils.h"
[6141]13#include "satObs.h"
[6044]14#include "pppInclude.h"
[6400]15#include "pppModel.h"
[10533]16#include "RTCM3/bits.h"
[1025]17
18using namespace std;
19
[5749]20// Constructor
21////////////////////////////////////////////////////////////////////////////
22t_eph::t_eph() {
[6518]23 _checkState = unchecked;
[9765]24 _navType = undefined;
[6518]25 _orbCorr = 0;
26 _clkCorr = 0;
[5749]27}
[7278]28// Destructor
29////////////////////////////////////////////////////////////////////////////
30t_eph::~t_eph() {
31 if (_orbCorr)
32 delete _orbCorr;
33 if (_clkCorr)
34 delete _clkCorr;
35}
[5749]36
[7481]37//
[5749]38////////////////////////////////////////////////////////////////////////////
[6141]39void t_eph::setOrbCorr(const t_orbCorr* orbCorr) {
[7888]40 if (_orbCorr) {
41 delete _orbCorr;
42 _orbCorr = 0;
43 }
[6141]44 _orbCorr = new t_orbCorr(*orbCorr);
[5749]45}
46
[7481]47//
[5749]48////////////////////////////////////////////////////////////////////////////
[6141]49void t_eph::setClkCorr(const t_clkCorr* clkCorr) {
[7888]50 if (_clkCorr) {
51 delete _clkCorr;
52 _clkCorr = 0;
53 }
[6141]54 _clkCorr = new t_clkCorr(*clkCorr);
[5749]55}
56
[7481]57//
[5749]58////////////////////////////////////////////////////////////////////////////
[6109]59t_irc t_eph::getCrd(const bncTime& tt, ColumnVector& xc, ColumnVector& vv, bool useCorr) const {
[6518]60
[8419]61 if (_checkState == bad ||
[8618]62 _checkState == unhealthy ||
63 _checkState == outdated) {
[6518]64 return failure;
65 }
[8903]66
[8542]67 xc.ReSize(6);
[5749]68 vv.ReSize(3);
[6213]69 if (position(tt.gpsw(), tt.gpssec(), xc.data(), vv.data()) != success) {
70 return failure;
71 }
[5789]72 if (useCorr) {
[5839]73 if (_orbCorr && _clkCorr) {
[5849]74 double dtO = tt - _orbCorr->_time;
[6556]75 if (_orbCorr->_updateInt) {
[8903]76 dtO -= (0.5 * ssrUpdateInt[_orbCorr->_updateInt]);
[6556]77 }
[5839]78 ColumnVector dx(3);
[5849]79 dx[0] = _orbCorr->_xr[0] + _orbCorr->_dotXr[0] * dtO;
80 dx[1] = _orbCorr->_xr[1] + _orbCorr->_dotXr[1] * dtO;
81 dx[2] = _orbCorr->_xr[2] + _orbCorr->_dotXr[2] * dtO;
82
[7133]83 RSW_to_XYZ(xc.Rows(1,3), vv.Rows(1,3), dx, dx);
[5849]84
[5839]85 xc[0] -= dx[0];
86 xc[1] -= dx[1];
87 xc[2] -= dx[2];
[5849]88
[7133]89 ColumnVector dv(3);
90 RSW_to_XYZ(xc.Rows(1,3), vv.Rows(1,3), _orbCorr->_dotXr, dv);
91
92 vv[0] -= dv[0];
93 vv[1] -= dv[1];
94 vv[2] -= dv[2];
95
[5849]96 double dtC = tt - _clkCorr->_time;
[6556]97 if (_clkCorr->_updateInt) {
[8903]98 dtC -= (0.5 * ssrUpdateInt[_clkCorr->_updateInt]);
[6556]99 }
[7014]100 xc[3] += _clkCorr->_dClk + _clkCorr->_dotDClk * dtC + _clkCorr->_dotDotDClk * dtC * dtC;
[5839]101 }
102 else {
103 return failure;
104 }
[5749]105 }
106 return success;
107}
108
[9765]109
[6801]110//
111//////////////////////////////////////////////////////////////////////////////
[9765]112t_irc t_eph::setNavType(QString navTypeStr) {
[10317]113 if (navTypeStr == "LNAV") {
114 _navType = t_eph::LNAV;
115 }
116 else if (navTypeStr == "FDMA") {
117 _navType = t_eph::FDMA;
118 }
119 else if (navTypeStr == "FNAV") {
120 _navType = t_eph::FNAV;
121 }
122 else if (navTypeStr == "INAV") {
123 _navType = t_eph::INAF;
124 }
125 else if (navTypeStr == "D1") {
126 _navType = t_eph::D1;
127 }
128 else if (navTypeStr == "D2") {
129 _navType = t_eph::D2;
130 }
131 else if (navTypeStr == "SBAS") {
132 _navType = t_eph::SBASL1;
133 }
134 else if (navTypeStr == "CNAV") {
135 _navType = t_eph::CNAV;
136 }
137 else if (navTypeStr == "CNV1") {
138 _navType = t_eph::CNV1;
139 }
140 else if (navTypeStr == "CNV2") {
141 _navType = t_eph::CNV2;
142 }
143 else if (navTypeStr == "CNV3") {
144 _navType = t_eph::CNV3;
145 }
146 else {
147 _navType = t_eph::undefined;
148 return failure;
149 }
[9765]150
151 return success;
152}
153
154//
155//////////////////////////////////////////////////////////////////////////////
156QString t_eph::navTypeString(e_navType navType, const t_prn& prn, double version) {
157 QString navTypeString = "";
158 QString epochStart;
159 QString eolStr;
160
161 if (version < 4.0) {
162 return navTypeString;
163 }
164
165 if (version == 99.0) {
166 epochStart = "";
167 eolStr = "";
168 }
169 else {
170 epochStart = "> ";
171 eolStr = "\n";
172 }
173
174 QString ephStr = QString("EPH %1 ").arg(prn.toString().c_str());
175 switch (navType) {
176 case undefined:
177 navTypeString = epochStart + ephStr + "unknown" + eolStr;
178 break;
179 case LNAV:
180 navTypeString = epochStart + ephStr + "LNAV" + eolStr;
181 break;
182 case FDMA:
183 navTypeString = epochStart + ephStr + "FDMA" + eolStr;
184 break;
185 case FNAV:
186 navTypeString = epochStart + ephStr + "FNAV" + eolStr;
187 break;
188 case INAF:
189 navTypeString = epochStart + ephStr + "INAV" + eolStr;
190 break;
191 case D1:
[9774]192 navTypeString = epochStart + ephStr + "D1 " + eolStr;
[9765]193 break;
194 case D2:
[9774]195 navTypeString = epochStart + ephStr + "D2 " + eolStr;
[9765]196 break;
197 case SBASL1:
198 navTypeString = epochStart + ephStr + "SBAS" + eolStr;
199 break;
200 case CNAV:
201 navTypeString = epochStart + ephStr + "CNAV" + eolStr;
202 break;
203 case CNV1:
204 navTypeString = epochStart + ephStr + "CNV1" + eolStr;
205 break;
206 case CNV2:
207 navTypeString = epochStart + ephStr + "CNV2" + eolStr;
208 break;
209 case CNV3:
210 navTypeString = epochStart + ephStr + "CNV3" + eolStr;
211 break;
212 }
213 return navTypeString;
214 }
215
216//
217//////////////////////////////////////////////////////////////////////////////
[6801]218QString t_eph::rinexDateStr(const bncTime& tt, const t_prn& prn, double version) {
219 QString prnStr(prn.toString().c_str());
220 return rinexDateStr(tt, prnStr, version);
221}
222
223//
224//////////////////////////////////////////////////////////////////////////////
225QString t_eph::rinexDateStr(const bncTime& tt, const QString& prnStr, double version) {
226
227 QString datStr;
228
229 unsigned year, month, day, hour, min;
230 double sec;
231 tt.civil_date(year, month, day);
232 tt.civil_time(hour, min, sec);
233
234 QTextStream out(&datStr);
235
236 if (version < 3.0) {
237 QString prnHlp = prnStr.mid(1,2); if (prnHlp[0] == '0') prnHlp[0] = ' ';
238 out << prnHlp << QString(" %1 %2 %3 %4 %5%6")
239 .arg(year % 100, 2, 10, QChar('0'))
240 .arg(month, 2)
241 .arg(day, 2)
242 .arg(hour, 2)
243 .arg(min, 2)
244 .arg(sec, 5, 'f',1);
245 }
[9765]246 else if (version == 99) {
247 out << QString(" %1 %2 %3 %4 %5 %6")
248 .arg(year, 4)
249 .arg(month, 2, 10, QChar('0'))
250 .arg(day, 2, 10, QChar('0'))
251 .arg(hour, 2, 10, QChar('0'))
252 .arg(min, 2, 10, QChar('0'))
253 .arg(int(sec), 2, 10, QChar('0'));
254 }
[6801]255 else {
256 out << prnStr << QString(" %1 %2 %3 %4 %5 %6")
257 .arg(year, 4)
258 .arg(month, 2, 10, QChar('0'))
259 .arg(day, 2, 10, QChar('0'))
260 .arg(hour, 2, 10, QChar('0'))
261 .arg(min, 2, 10, QChar('0'))
262 .arg(int(sec), 2, 10, QChar('0'));
263 }
264
265 return datStr;
266}
267
268// Constructor
269//////////////////////////////////////////////////////////////////////////////
[9367]270t_ephGPS::t_ephGPS(double rnxVersion, const QStringList& lines) {
[6801]271
[9786]272 int nLines = 8;
[6801]273
[9786]274 if (navType() == t_eph::CNAV) {
275 nLines += 1;
276 }
[9788]277 if (navType() == t_eph::CNV2) {
[9786]278 nLines += 2;
279 }
280
[6801]281 if (lines.size() != nLines) {
282 _checkState = bad;
283 return;
284 }
285
286 // RINEX Format
287 // ------------
288 int fieldLen = 19;
289
290 int pos[4];
291 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
292 pos[1] = pos[0] + fieldLen;
293 pos[2] = pos[1] + fieldLen;
294 pos[3] = pos[2] + fieldLen;
295
296 // Read eight lines
297 // ----------------
298 for (int iLine = 0; iLine < nLines; iLine++) {
299 QString line = lines[iLine];
300
301 if ( iLine == 0 ) {
[8204]302 QTextStream in(line.left(pos[1]).toLatin1());
[6801]303 int year, month, day, hour, min;
304 double sec;
305
[7139]306 QString prnStr, n;
[6880]307 in >> prnStr;
[7639]308
309 if (prnStr.size() == 1 &&
[8168]310 (prnStr[0] == 'G' ||
311 prnStr[0] == 'J' ||
312 prnStr[0] == 'I')) {
[7139]313 in >> n;
314 prnStr.append(n);
[6880]315 }
[7639]316
[6880]317 in >> year >> month >> day >> hour >> min >> sec;
[6801]318 if (prnStr.at(0) == 'G') {
319 _prn.set('G', prnStr.mid(1).toInt());
320 }
321 else if (prnStr.at(0) == 'J') {
322 _prn.set('J', prnStr.mid(1).toInt());
323 }
[8168]324 else if (prnStr.at(0) == 'I') {
325 _prn.set('I', prnStr.mid(1).toInt());
326 }
[6801]327 else {
328 _prn.set('G', prnStr.toInt());
329 }
330
331 if (year < 80) {
332 year += 2000;
333 }
334 else if (year < 100) {
335 year += 1900;
336 }
337
338 _TOC.set(year, month, day, hour, min, sec);
339
[9786]340 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
[6801]341 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
342 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
343 _checkState = bad;
344 return;
345 }
346 }
[9786]347 // =====================
348 // BROADCAST ORBIT - 1
349 // =====================
350 else if ( iLine == 1) {
[6801]351
[9786]352 if (navType() == t_eph::CNAV ||
353 navType() == t_eph::CNV2) {
354 if ( readDbl(line, pos[0], fieldLen, _ADOT ) ||
355 readDbl(line, pos[1], fieldLen, _Crs ) ||
356 readDbl(line, pos[2], fieldLen, _Delta_n) ||
357 readDbl(line, pos[3], fieldLen, _M0 ) ) {
358 _checkState = bad;
359 return;
360 }
[6801]361 }
[9786]362 else { // LNAV, undefined
363 if ( readDbl(line, pos[0], fieldLen, _IODE ) ||
364 readDbl(line, pos[1], fieldLen, _Crs ) ||
365 readDbl(line, pos[2], fieldLen, _Delta_n) ||
366 readDbl(line, pos[3], fieldLen, _M0 ) ) {
367 _checkState = bad;
368 return;
369 }
370 }
[6801]371 }
[9786]372 // =====================
373 // BROADCAST ORBIT - 2
374 // =====================
[6801]375 else if ( iLine == 2 ) {
376 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
377 readDbl(line, pos[1], fieldLen, _e ) ||
378 readDbl(line, pos[2], fieldLen, _Cus ) ||
379 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
380 _checkState = bad;
381 return;
382 }
383 }
[9786]384 // =====================
385 // BROADCAST ORBIT - 3
386 // =====================
387 else if ( iLine == 3 ) {
[6801]388
[9786]389 if (navType() == t_eph::CNAV ||
390 navType() == t_eph::CNV2) {
391 if ( readDbl(line, pos[0], fieldLen, _top) ||
392 readDbl(line, pos[1], fieldLen, _Cic ) ||
393 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
394 readDbl(line, pos[3], fieldLen, _Cis ) ) {
395 _checkState = bad;
396 return;
397 }
[6801]398 }
[9786]399 else { // LNAV, undefined
400 if ( readDbl(line, pos[0], fieldLen, _TOEsec) ||
401 readDbl(line, pos[1], fieldLen, _Cic ) ||
402 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
403 readDbl(line, pos[3], fieldLen, _Cis ) ) {
404 _checkState = bad;
405 return;
406 }
407 }
[6801]408 }
[9786]409 // =====================
410 // BROADCAST ORBIT - 4
411 // =====================
[6801]412 else if ( iLine == 4 ) {
413 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
414 readDbl(line, pos[1], fieldLen, _Crc ) ||
415 readDbl(line, pos[2], fieldLen, _omega ) ||
416 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
417 _checkState = bad;
418 return;
419 }
420 }
[9786]421 // =====================
422 // BROADCAST ORBIT - 5
423 // =====================
424 else if ( iLine == 5 && type() != t_eph::IRNSS) {
[6801]425
[9786]426 if (navType() == t_eph::CNAV ||
427 navType() == t_eph::CNV2) {
[9788]428 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
429 readDbl(line, pos[1], fieldLen, _Delta_n_dot) ||
430 readDbl(line, pos[2], fieldLen, _URAI_NED0 ) ||
[9786]431 readDbl(line, pos[3], fieldLen, _URAI_NED1) ) {
432 _checkState = bad;
433 return;
434 }
[6801]435 }
[9786]436 else { // LNAV, undefined
437 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
438 readDbl(line, pos[1], fieldLen, _L2Codes) ||
[9788]439 readDbl(line, pos[2], fieldLen, _TOEweek) ||
[9786]440 readDbl(line, pos[3], fieldLen, _L2PFlag) ) {
441 _checkState = bad;
442 return;
443 }
444 }
[6801]445 }
[8168]446 else if ( iLine == 5 && type() == t_eph::IRNSS) {
447 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
448 readDbl(line, pos[2], fieldLen, _TOEweek) ) {
449 _checkState = bad;
450 return;
451 }
452 }
[9786]453 // =====================
454 // BROADCAST ORBIT - 6
455 // =====================
456 else if ( iLine == 6 && type() != t_eph::IRNSS) {
[6801]457
[9786]458 if (navType() == t_eph::CNAV ||
459 navType() == t_eph::CNV2 ) {
460 if ( readDbl(line, pos[0], fieldLen, _URAI_ED) ||
461 readDbl(line, pos[1], fieldLen, _health ) ||
462 readDbl(line, pos[2], fieldLen, _TGD ) ||
463 readDbl(line, pos[3], fieldLen, _URAI_NED2) ) {
464 _checkState = bad;
465 return;
466 }
[6801]467 }
[9786]468 else { // LNAV, undefined
469 if ( readDbl(line, pos[0], fieldLen, _ura ) ||
470 readDbl(line, pos[1], fieldLen, _health) ||
471 readDbl(line, pos[2], fieldLen, _TGD ) ||
472 readDbl(line, pos[3], fieldLen, _IODC ) ) {
473 _checkState = bad;
474 return;
475 }
476 }
[6801]477 }
[8168]478 else if ( iLine == 6 && type() == t_eph::IRNSS) {
479 if ( readDbl(line, pos[0], fieldLen, _ura ) ||
480 readDbl(line, pos[1], fieldLen, _health) ||
481 readDbl(line, pos[2], fieldLen, _TGD ) ) {
482 _checkState = bad;
483 return;
484 }
485 }
[9786]486 // =====================
487 // BROADCAST ORBIT - 7
488 // =====================
[6801]489 else if ( iLine == 7 ) {
[9786]490 if (navType() == t_eph::LNAV ||
491 navType() == t_eph::undefined) {
492
493 if ( readDbl(line, pos[0], fieldLen, _TOT) ) {
494 _checkState = bad;
495 return;
496 }
497
498 if (type() != t_eph::IRNSS) {
499 double fitIntervalRnx;
500 if ( readDbl(line, pos[1], fieldLen, fitIntervalRnx) ) {
501 _checkState = bad;
502 return;
[8931]503 }
[9786]504 if (type() == t_eph::GPS) { // in RINEX specified always as time period for GPS
505 _fitInterval = fitIntervalRnx;
506 } else if (type() == t_eph::QZSS) { // specified as flag for QZSS
507 if (rnxVersion == 3.02) {
508 _fitInterval = fitIntervalRnx; // specified as time period
509 }
510 else {
511 _fitInterval = fitIntervalFromFlag(fitIntervalRnx, _IODC, t_eph::QZSS);
512 }
[8934]513 }
[8927]514 }
[8925]515 }
[9786]516
517 else if (navType() == t_eph::CNAV ||
518 navType() == t_eph::CNV2) {
519 if ( readDbl(line, pos[0], fieldLen, _ISC_L1CA) ||
520 readDbl(line, pos[1], fieldLen, _ISC_L2C ) ||
521 readDbl(line, pos[2], fieldLen, _ISC_L5I5) ||
522 readDbl(line, pos[3], fieldLen, _ISC_L5Q5) ) {
523 _checkState = bad;
524 return;
525 }
526 }
527
[6801]528 }
[9786]529 // =====================
530 // BROADCAST ORBIT - 8
531 // =====================
532 else if ( iLine == 8 ) {
533 if (navType() == t_eph::CNAV) {
534 if ( readDbl(line, pos[0], fieldLen, _TOT) ||
535 readDbl(line, pos[1], fieldLen, _wnop) ) {
536 _checkState = bad;
537 return;
538 }
539 }
540 else if (navType() == t_eph::CNV2) {
541 if ( readDbl(line, pos[0], fieldLen, _ISC_L1Cd) ||
542 readDbl(line, pos[1], fieldLen, _ISC_L1Cp)) {
543 _checkState = bad;
544 return;
545 }
546 }
547 }
548 // =====================
549 // BROADCAST ORBIT - 9
550 // =====================
551 else if ( iLine == 9 ) {
552 if (navType() == t_eph::CNV2) {
553 if ( readDbl(line, pos[0], fieldLen, _TOT) ||
554 readDbl(line, pos[1], fieldLen, _wnop) ) {
555 _checkState = bad;
556 return;
557 }
558 }
559 }
[6801]560 }
561}
562
[2222]563// Compute GPS Satellite Position (virtual)
[1025]564////////////////////////////////////////////////////////////////////////////
[6213]565t_irc t_ephGPS::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
[1025]566
[1098]567 static const double omegaEarth = 7292115.1467e-11;
[5277]568 static const double gmGRS = 398.6005e12;
[1025]569
[8542]570 memset(xc, 0, 6*sizeof(double));
[1025]571 memset(vv, 0, 3*sizeof(double));
572
573 double a0 = _sqrt_A * _sqrt_A;
574 if (a0 == 0) {
[6213]575 return failure;
[1025]576 }
577
[5277]578 double n0 = sqrt(gmGRS/(a0*a0*a0));
[4018]579
580 bncTime tt(GPSweek, GPSweeks);
[4543]581 double tk = tt - bncTime(int(_TOEweek), _TOEsec);
[4018]582
[1025]583 double n = n0 + _Delta_n;
584 double M = _M0 + n*tk;
585 double E = M;
586 double E_last;
[8368]587 int nLoop = 0;
[1025]588 do {
589 E_last = E;
590 E = M + _e*sin(E);
[8368]591
592 if (++nLoop == 100) {
593 return failure;
594 }
595 } while ( fabs(E-E_last)*a0 > 0.001);
[1025]596 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
597 double u0 = v + _omega;
598 double sin2u0 = sin(2*u0);
599 double cos2u0 = cos(2*u0);
600 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
601 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
602 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
603 double xp = r*cos(u);
604 double yp = r*sin(u);
[7481]605 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
[4018]606 omegaEarth*_TOEsec;
[7278]607
[1025]608 double sinom = sin(OM);
609 double cosom = cos(OM);
610 double sini = sin(i);
611 double cosi = cos(i);
612 xc[0] = xp*cosom - yp*cosi*sinom;
613 xc[1] = xp*sinom + yp*cosi*cosom;
[7481]614 xc[2] = yp*sini;
615
[4018]616 double tc = tt - _TOC;
[2429]617 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
[1025]618
619 // Velocity
620 // --------
621 double tanv2 = tan(v/2);
622 double dEdM = 1 / (1 - _e*cos(E));
[7278]623 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
[1025]624 * dEdM * n;
625 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
626 double dotom = _OMEGADOT - omegaEarth;
627 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
[7278]628 double dotr = a0 * _e*sin(E) * dEdM * n
[1025]629 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
630 double dotx = dotr*cos(u) - r*sin(u)*dotu;
631 double doty = dotr*sin(u) + r*cos(u)*dotu;
632
633 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
634 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
635 + yp*sini*sinom*doti; // dX / di
636
637 vv[1] = sinom *dotx + cosi*cosom *doty
638 + xp*cosom*dotom - yp*cosi*sinom*dotom
639 - yp*sini*cosom*doti;
640
641 vv[2] = sini *doty + yp*cosi *doti;
[2429]642
643 // Relativistic Correction
644 // -----------------------
[9124]645 xc[3] -= 4.442807633e-10 * _e * sqrt(a0) *sin(E);
[9132]646
[8542]647 xc[4] = _clock_drift + _clock_driftrate*tc;
648 xc[5] = _clock_driftrate;
[8581]649
[6213]650 return success;
[1025]651}
652
[6801]653// RINEX Format String
654//////////////////////////////////////////////////////////////////////////////
655QString t_ephGPS::toString(double version) const {
[2221]656
[9765]657 QString navStr = navTypeString(_navType, _prn, version);
658 QString rnxStr = navStr + rinexDateStr(_TOC, _prn, version);
[2221]659
[6801]660 QTextStream out(&rnxStr);
[2221]661
[6801]662 out << QString("%1%2%3\n")
663 .arg(_clock_bias, 19, 'e', 12)
664 .arg(_clock_drift, 19, 'e', 12)
665 .arg(_clock_driftrate, 19, 'e', 12);
[2221]666
[6801]667 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
[2221]668
[6801]669
[9786]670 // =====================
671 // BROADCAST ORBIT - 1
672 // =====================
673 if (navType() == t_eph::CNAV ||
674 navType() == t_eph::CNV2) {
675 out << QString(fmt)
676 .arg(_ADOT, 19, 'e', 12)
677 .arg(_Crs, 19, 'e', 12)
678 .arg(_Delta_n, 19, 'e', 12)
679 .arg(_M0, 19, 'e', 12);
680 }
681 else { // LNAV, undefinded
682 out << QString(fmt)
683 .arg(_IODE, 19, 'e', 12)
684 .arg(_Crs, 19, 'e', 12)
685 .arg(_Delta_n, 19, 'e', 12)
686 .arg(_M0, 19, 'e', 12);
687 }
688 // =====================
689 // BROADCAST ORBIT - 2
690 // =====================
[6801]691 out << QString(fmt)
692 .arg(_Cuc, 19, 'e', 12)
693 .arg(_e, 19, 'e', 12)
694 .arg(_Cus, 19, 'e', 12)
695 .arg(_sqrt_A, 19, 'e', 12);
[9786]696 // =====================
697 // BROADCAST ORBIT - 3
698 // =====================
699 if (navType() == t_eph::CNAV ||
700 navType() == t_eph::CNV2) {
701 out << QString(fmt)
702 .arg(_top, 19, 'e', 12)
703 .arg(_Cic, 19, 'e', 12)
704 .arg(_OMEGA0, 19, 'e', 12)
705 .arg(_Cis, 19, 'e', 12);
706 }
707 else {
708 out << QString(fmt)
709 .arg(_TOEsec, 19, 'e', 12)
710 .arg(_Cic, 19, 'e', 12)
711 .arg(_OMEGA0, 19, 'e', 12)
712 .arg(_Cis, 19, 'e', 12);
713 }
714 // =====================
715 // BROADCAST ORBIT - 4
716 // =====================
[6801]717 out << QString(fmt)
718 .arg(_i0, 19, 'e', 12)
719 .arg(_Crc, 19, 'e', 12)
720 .arg(_omega, 19, 'e', 12)
721 .arg(_OMEGADOT, 19, 'e', 12);
[9786]722 // =====================
723 // BROADCAST ORBIT - 5
724 // =====================
[8800]725 if (type() == t_eph::IRNSS) {
[8168]726 out << QString(fmt)
727 .arg(_IDOT, 19, 'e', 12)
[8800]728 .arg(0.0, 19, 'e', 12)
729 .arg(_TOEweek, 19, 'e', 12)
730 .arg(0.0, 19, 'e', 12);
731 }
732 else {
[9786]733 if (navType() == t_eph::CNAV ||
734 navType() == t_eph::CNV2) {
735 out << QString(fmt)
[9788]736 .arg(_IDOT, 19, 'e', 12)
737 .arg(_Delta_n_dot, 19, 'e', 12)
738 .arg(_URAI_NED0, 19, 'e', 12)
739 .arg(_URAI_NED1, 19, 'e', 12);
[9786]740
741 }
742 else { // LNAV, undefined
743 out << QString(fmt)
744 .arg(_IDOT, 19, 'e', 12)
745 .arg(_L2Codes, 19, 'e', 12)
746 .arg(_TOEweek, 19, 'e', 12)
747 .arg(_L2PFlag, 19, 'e', 12);
748
749 }
[8800]750 }
[9786]751 // =====================
752 // BROADCAST ORBIT - 6
753 // =====================
[8168]754 if (type() == t_eph::IRNSS) {
755 out << QString(fmt)
756 .arg(_ura, 19, 'e', 12)
757 .arg(_health, 19, 'e', 12)
758 .arg(_TGD, 19, 'e', 12)
[8790]759 .arg(0.0, 19, 'e', 12);
[8168]760 }
761 else {
[9786]762 if (navType() == t_eph::CNAV ||
763 navType() == t_eph::CNV2) {
764 out << QString(fmt)
765 .arg(_URAI_ED, 19, 'e', 12)
766 .arg(_health, 19, 'e', 12)
767 .arg(_TGD, 19, 'e', 12)
768 .arg(_URAI_NED2,19, 'e', 12);
769
770 }
771 else { // LNAV, undefined
772 out << QString(fmt)
773 .arg(_ura, 19, 'e', 12)
774 .arg(_health, 19, 'e', 12)
775 .arg(_TGD, 19, 'e', 12)
776 .arg(_IODC, 19, 'e', 12);
777 }
[8168]778 }
[9786]779 // =====================
780 // BROADCAST ORBIT - 7
781 // =====================
782 if (navType() == t_eph::LNAV ||
783 navType() == t_eph::undefined) {
[6801]784
[9786]785 double tot = _TOT;
786 if (tot == 0.9999e9 && version < 3.0) {
787 tot = 0.0;
788 }
789 // fitInterval
790 if (type() == t_eph::IRNSS) {// not valid for IRNSS
791 out << QString(fmt)
792 .arg(tot, 19, 'e', 12)
793 .arg(0.0, 19, 'e', 12)
794 .arg("", 19, QChar(' '))
795 .arg("", 19, QChar(' '));
796 }
797 else {
798 // for GPS and QZSS in version 3.02 specified in hours
799 double fitIntervalRnx = _fitInterval;
800 // otherwise specified as flag
801 if (type() == t_eph::QZSS && version != 3.02) {
802 (_fitInterval == 2.0) ? fitIntervalRnx = 0.0 : fitIntervalRnx = 1.0;
803 }
804 out << QString(fmt)
805 .arg(tot, 19, 'e', 12)
806 .arg(fitIntervalRnx, 19, 'e', 12)
807 .arg("", 19, QChar(' '))
808 .arg("", 19, QChar(' '));
809 }
[7922]810 }
[9786]811 else if (navType() == t_eph::CNAV ||
812 navType() == t_eph::CNV2) {
[8800]813 out << QString(fmt)
[9786]814 .arg(_ISC_L1CA, 19, 'e', 12)
815 .arg(_ISC_L2C, 19, 'e', 12)
816 .arg(_ISC_L5I5, 19, 'e', 12)
817 .arg(_ISC_L5Q5, 19, 'e', 12);
[8800]818 }
[9786]819 // =====================
820 // BROADCAST ORBIT - 8
821 // =====================
822 if (navType() == t_eph::CNAV) {
[8800]823 out << QString(fmt)
[9786]824 .arg(_TOT, 19, 'e', 12)
825 .arg(_wnop, 19, 'e', 12)
826 .arg("", 19, QChar(' '))
827 .arg("", 19, QChar(' '));
[8800]828 }
[9786]829 else if (navType() == t_eph::CNV2) {
830 out << QString(fmt)
831 .arg(_ISC_L1Cd, 19, 'e', 12)
832 .arg(_ISC_L1Cp, 19, 'e', 12)
833 .arg("", 19, QChar(' '))
834 .arg("", 19, QChar(' '));
835 }
836
837 // =====================
838 // BROADCAST ORBIT - 9
839 // =====================
840 if (navType() == t_eph::CNV2) {
841 out << QString(fmt)
842 .arg(_TOT, 19, 'e', 12)
843 .arg(_wnop, 19, 'e', 12)
844 .arg("", 19, QChar(' '))
845 .arg("", 19, QChar(' '));
846 }
847
[6801]848 return rnxStr;
[2221]849}
850
[6801]851// Constructor
852//////////////////////////////////////////////////////////////////////////////
[9367]853t_ephGlo::t_ephGlo(double rnxVersion, const QStringList& lines) {
[2221]854
[9367]855 int nLines = 4;
856 if (rnxVersion >= 3.05) {
857 nLines += 1;
858 }
859 else {
860 _M_delta_tau = 0.9999e9; // unknown
861 _M_FT = 1.5e1; // unknown
862 }
[6801]863
864 if (lines.size() != nLines) {
865 _checkState = bad;
866 return;
[6518]867 }
868
[6801]869 // RINEX Format
870 // ------------
871 int fieldLen = 19;
[9367]872 double statusflags = 0.0;
873 double healthflags = 0.0;
[2221]874
[6801]875 int pos[4];
876 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
877 pos[1] = pos[0] + fieldLen;
878 pos[2] = pos[1] + fieldLen;
879 pos[3] = pos[2] + fieldLen;
[2221]880
[6801]881 // Read four lines
882 // ---------------
883 for (int iLine = 0; iLine < nLines; iLine++) {
884 QString line = lines[iLine];
[2221]885
[6801]886 if ( iLine == 0 ) {
[8204]887 QTextStream in(line.left(pos[1]).toLatin1());
[6213]888
[6801]889 int year, month, day, hour, min;
890 double sec;
[2221]891
[7139]892 QString prnStr, n;
[6880]893 in >> prnStr;
[7639]894 if (prnStr.size() == 1 && prnStr[0] == 'R') {
[7139]895 in >> n;
896 prnStr.append(n);
[6880]897 }
898 in >> year >> month >> day >> hour >> min >> sec;
[6801]899 if (prnStr.at(0) == 'R') {
900 _prn.set('R', prnStr.mid(1).toInt());
901 }
902 else {
903 _prn.set('R', prnStr.toInt());
904 }
[2221]905
[6801]906 if (year < 80) {
907 year += 2000;
908 }
909 else if (year < 100) {
910 year += 1900;
911 }
[2221]912
[6801]913 _gps_utc = gnumleap(year, month, day);
[2221]914
[6801]915 _TOC.set(year, month, day, hour, min, sec);
916 _TOC = _TOC + _gps_utc;
[8800]917 int nd = int((_TOC.gpssec())) / (24.0*60.0*60.0);
[6801]918 if ( readDbl(line, pos[1], fieldLen, _tau ) ||
919 readDbl(line, pos[2], fieldLen, _gamma) ||
920 readDbl(line, pos[3], fieldLen, _tki ) ) {
921 _checkState = bad;
922 return;
923 }
[8800]924 _tki -= nd * 86400.0;
925 _tau = -_tau;
[6801]926 }
[9788]927 // =====================
928 // BROADCAST ORBIT - 1
929 // =====================
[6801]930 else if ( iLine == 1 ) {
931 if ( readDbl(line, pos[0], fieldLen, _x_pos ) ||
932 readDbl(line, pos[1], fieldLen, _x_velocity ) ||
933 readDbl(line, pos[2], fieldLen, _x_acceleration) ||
934 readDbl(line, pos[3], fieldLen, _health ) ) {
935 _checkState = bad;
936 return;
937 }
938 }
[9788]939 // =====================
940 // BROADCAST ORBIT - 2
941 // =====================
[6801]942 else if ( iLine == 2 ) {
943 if ( readDbl(line, pos[0], fieldLen, _y_pos ) ||
944 readDbl(line, pos[1], fieldLen, _y_velocity ) ||
945 readDbl(line, pos[2], fieldLen, _y_acceleration ) ||
946 readDbl(line, pos[3], fieldLen, _frequency_number) ) {
947 _checkState = bad;
948 return;
949 }
950 }
[9788]951 // =====================
952 // BROADCAST ORBIT - 3
953 // =====================
[6801]954 else if ( iLine == 3 ) {
955 if ( readDbl(line, pos[0], fieldLen, _z_pos ) ||
956 readDbl(line, pos[1], fieldLen, _z_velocity ) ||
957 readDbl(line, pos[2], fieldLen, _z_acceleration) ||
958 readDbl(line, pos[3], fieldLen, _E ) ) {
959 _checkState = bad;
960 return;
961 }
962 }
[9788]963 // =====================
964 // BROADCAST ORBIT - 4
965 // =====================
[9367]966 else if ( iLine == 4 ) {
[9892]967 if (readDbl(line, pos[0], fieldLen, statusflags ) ) {
968 //statusflags BLK, do nothing
969 _flags_unknown = true;
[9367]970 }
971 else {
[9892]972 _flags_unknown = false;
[9367]973 // status flags
974 // ============
975 // bit 0-1
976 _M_P = double(bitExtracted(statusflags, 2, 0));
977 // bit 2-3
978 _P1 = double(bitExtracted(statusflags, 2, 2));
979 // bit 4
980 _P2 = double(bitExtracted(statusflags, 1, 4));
981 // bit 5
982 _P3 = double(bitExtracted(statusflags, 1, 5));
983 // bit 6
984 _M_P4 = double(bitExtracted(statusflags, 1, 6));
985 // bit 7-8
986 _M_M = double(bitExtracted(statusflags, 2, 7));
987 /// GLO M/K exclusive flags/values only valid if flag M is set to '01'
988 if (!_M_M) {
989 _M_P4 = 0.0;
990 _M_P = 0.0;
991 }
[9892]992 }
993 if ( readDbl(line, pos[1], fieldLen, _M_delta_tau ) ||
994 readDbl(line, pos[2], fieldLen, _M_FT ) ) {
995 _checkState = bad;
996 return;
997 }
998 if (readDbl(line, pos[3], fieldLen, healthflags ) ) {
999 // healthflags BLK
1000 _flags_unknown = true;
1001 }
1002 else {
1003 _flags_unknown = false;
[9367]1004 // health flags
1005 // ============
1006 // bit 0 (is to be ignored, if bit 1 is zero)
1007 _almanac_health = double(bitExtracted(healthflags, 1, 0));
1008 // bit 1
1009 _almanac_health_availablility_indicator = double(bitExtracted(healthflags, 1, 1));
1010 // bit 2
1011 _M_l3 = double(bitExtracted(healthflags, 1, 2));
1012 }
1013 }
[6801]1014 }
1015
1016 // Initialize status vector
1017 // ------------------------
1018 _tt = _TOC;
[8698]1019 _xv.ReSize(6); _xv = 0.0;
[6801]1020 _xv(1) = _x_pos * 1.e3;
1021 _xv(2) = _y_pos * 1.e3;
1022 _xv(3) = _z_pos * 1.e3;
1023 _xv(4) = _x_velocity * 1.e3;
1024 _xv(5) = _y_velocity * 1.e3;
1025 _xv(6) = _z_velocity * 1.e3;
[2221]1026}
1027
[6801]1028// Compute Glonass Satellite Position (virtual)
[2771]1029////////////////////////////////////////////////////////////////////////////
[6801]1030t_irc t_ephGlo::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
[2771]1031
[6801]1032 static const double nominalStep = 10.0;
[2771]1033
[8542]1034 memset(xc, 0, 6*sizeof(double));
[2771]1035 memset(vv, 0, 3*sizeof(double));
1036
[6801]1037 double dtPos = bncTime(GPSweek, GPSweeks) - _tt;
1038
[8698]1039 if (fabs(dtPos) > 24 * 3600.0) {
[6213]1040 return failure;
[2771]1041 }
1042
[6801]1043 int nSteps = int(fabs(dtPos) / nominalStep) + 1;
1044 double step = dtPos / nSteps;
[4018]1045
[6801]1046 double acc[3];
1047 acc[0] = _x_acceleration * 1.e3;
1048 acc[1] = _y_acceleration * 1.e3;
1049 acc[2] = _z_acceleration * 1.e3;
[9132]1050
[6801]1051 for (int ii = 1; ii <= nSteps; ii++) {
1052 _xv = rungeKutta4(_tt.gpssec(), _xv, step, acc, glo_deriv);
1053 _tt = _tt + step;
1054 }
[4018]1055
[6801]1056 // Position and Velocity
1057 // ---------------------
1058 xc[0] = _xv(1);
1059 xc[1] = _xv(2);
1060 xc[2] = _xv(3);
[2771]1061
[6801]1062 vv[0] = _xv(4);
1063 vv[1] = _xv(5);
1064 vv[2] = _xv(6);
[2771]1065
[6801]1066 // Clock Correction
1067 // ----------------
1068 double dtClk = bncTime(GPSweek, GPSweeks) - _TOC;
1069 xc[3] = -_tau + _gamma * dtClk;
[2771]1070
[8542]1071 xc[4] = _gamma;
1072 xc[5] = 0.0;
[8483]1073
[6213]1074 return success;
[2771]1075}
1076
[6801]1077// RINEX Format String
[3659]1078//////////////////////////////////////////////////////////////////////////////
[6801]1079QString t_ephGlo::toString(double version) const {
[3664]1080
[9765]1081 QString navStr = navTypeString(_navType, _prn, version);
1082 QString rnxStr = navStr + rinexDateStr(_TOC -_gps_utc, _prn, version);
[8800]1083 int nd = int((_TOC - _gps_utc).gpssec()) / (24.0*60.0*60.0);
[6801]1084 QTextStream out(&rnxStr);
[3664]1085
[6801]1086 out << QString("%1%2%3\n")
[8800]1087 .arg(-_tau, 19, 'e', 12)
1088 .arg(_gamma, 19, 'e', 12)
1089 .arg(_tki+nd*86400.0, 19, 'e', 12);
[3668]1090
[6801]1091 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
[9788]1092 // =====================
1093 // BROADCAST ORBIT - 1
1094 // =====================
[6801]1095 out << QString(fmt)
1096 .arg(_x_pos, 19, 'e', 12)
1097 .arg(_x_velocity, 19, 'e', 12)
1098 .arg(_x_acceleration, 19, 'e', 12)
1099 .arg(_health, 19, 'e', 12);
[9788]1100 // =====================
1101 // BROADCAST ORBIT - 2
1102 // =====================
[6801]1103 out << QString(fmt)
1104 .arg(_y_pos, 19, 'e', 12)
1105 .arg(_y_velocity, 19, 'e', 12)
1106 .arg(_y_acceleration, 19, 'e', 12)
1107 .arg(_frequency_number, 19, 'e', 12);
[9788]1108 // =====================
1109 // BROADCAST ORBIT - 3
1110 // =====================
[6801]1111 out << QString(fmt)
1112 .arg(_z_pos, 19, 'e', 12)
1113 .arg(_z_velocity, 19, 'e', 12)
1114 .arg(_z_acceleration, 19, 'e', 12)
1115 .arg(_E, 19, 'e', 12);
[9788]1116 // =====================
1117 // BROADCAST ORBIT - 4
1118 // =====================
[9367]1119 if (version >= 3.05) {
1120 // unknown (RINEX version < 3.05)
1121 if (_flags_unknown) {
1122 out << QString(fmt)
1123 .arg("", 19, QChar(' ')) // statusflags blank if unknown
1124 .arg(_M_delta_tau, 19, 'e', 12)
1125 .arg(_M_FT, 19, 'e', 12)
1126 .arg("", 19, QChar(' ')); // healthflags blank if unknown
1127 }
1128 else {
1129 int statusflags = 0;
1130 // bit 7-8
1131 if (_M_M == 2.0) {
1132 statusflags |= (1<<7);
1133 }
1134 // bit 6
1135 if (_M_P4) {
1136 statusflags |= (1<<6);
1137 }
1138 // bit 5
1139 if (_P3) {
1140 statusflags |= (1<<5);
1141 }
1142 // bit 4
1143 if (_P2) {
1144 statusflags |= (1<<4);
1145 }
1146 // bit 2-3
1147 if (_P1 == 2.0) {
1148 statusflags |= (1<<2);
1149 }
1150 else if (_P1 == 1.0) {
1151 statusflags |= (1<<3);
1152 }
1153 else if (_P1 == 3.0) {
1154 statusflags |= (1<<2);
1155 statusflags |= (1<<3);
1156 }
1157 // bit 0-1
1158 if (_M_P == 2.0) {
1159 statusflags |= (1<<0);
1160 }
1161 else if (_M_P == 1.0) {
1162 statusflags |= (1<<1);
1163 }
1164 else if (_M_P == 3.0) {
1165 statusflags |= (1<<0);
1166 statusflags |= (1<<1);
1167 }
1168 // health flags
1169 // ============
1170 int healthflags = 0;
1171 // bit 0 (is to be ignored, if bit 1 is zero)
1172 if (_almanac_health) {
1173 healthflags |= (1<<0);
1174 }
1175 // bit 1
1176 if (_almanac_health_availablility_indicator) {
1177 healthflags |= (1<<1);
1178 }
1179 // bit 2
1180 if (_M_l3) {
1181 healthflags |= (1<<2);
1182 }
1183 out << QString(fmt)
1184 .arg(double(statusflags), 19, 'e', 12)
1185 .arg(_M_delta_tau, 19, 'e', 12)
1186 .arg(_M_FT, 19, 'e', 12)
1187 .arg(double(healthflags), 19, 'e', 12);
1188 }
1189 }
1190
[6801]1191 return rnxStr;
[3659]1192}
1193
[6801]1194// Derivative of the state vector using a simple force model (static)
1195////////////////////////////////////////////////////////////////////////////
1196ColumnVector t_ephGlo::glo_deriv(double /* tt */, const ColumnVector& xv,
1197 double* acc) {
[3659]1198
[6801]1199 // State vector components
1200 // -----------------------
1201 ColumnVector rr = xv.rows(1,3);
1202 ColumnVector vv = xv.rows(4,6);
[3699]1203
[6801]1204 // Acceleration
[3699]1205 // ------------
[6801]1206 static const double gmWGS = 398.60044e12;
1207 static const double AE = 6378136.0;
1208 static const double OMEGA = 7292115.e-11;
1209 static const double C20 = -1082.6257e-6;
[3699]1210
[8903]1211 double rho = rr.NormFrobenius();
[6801]1212 double t1 = -gmWGS/(rho*rho*rho);
1213 double t2 = 3.0/2.0 * C20 * (gmWGS*AE*AE) / (rho*rho*rho*rho*rho);
1214 double t3 = OMEGA * OMEGA;
1215 double t4 = 2.0 * OMEGA;
1216 double z2 = rr(3) * rr(3);
[3699]1217
[6801]1218 // Vector of derivatives
1219 // ---------------------
1220 ColumnVector va(6);
1221 va(1) = vv(1);
1222 va(2) = vv(2);
1223 va(3) = vv(3);
1224 va(4) = (t1 + t2*(1.0-5.0*z2/(rho*rho)) + t3) * rr(1) + t4*vv(2) + acc[0];
1225 va(5) = (t1 + t2*(1.0-5.0*z2/(rho*rho)) + t3) * rr(2) - t4*vv(1) + acc[1];
1226 va(6) = (t1 + t2*(3.0-5.0*z2/(rho*rho)) ) * rr(3) + acc[2];
[3699]1227
[6801]1228 return va;
1229}
[3699]1230
[6801]1231// IOD of Glonass Ephemeris (virtual)
1232////////////////////////////////////////////////////////////////////////////
[7169]1233unsigned int t_ephGlo::IOD() const {
[6801]1234 bncTime tMoscow = _TOC - _gps_utc + 3 * 3600.0;
[7054]1235 return (unsigned long)tMoscow.daysec() / 900;
[3659]1236}
1237
[8187]1238// Health status of Glonass Ephemeris (virtual)
1239////////////////////////////////////////////////////////////////////////////
1240unsigned int t_ephGlo::isUnhealthy() const {
[8215]1241
[8217]1242 if (_almanac_health_availablility_indicator) {
[8215]1243 if ((_health == 0 && _almanac_health == 0) ||
1244 (_health == 1 && _almanac_health == 0) ||
1245 (_health == 1 && _almanac_health == 1)) {
1246 return 1;
1247 }
[8187]1248 }
[8217]1249 else if (!_almanac_health_availablility_indicator) {
1250 if (_health) {
1251 return 1;
1252 }
1253 }
[8215]1254 return 0; /* (_health == 0 && _almanac_health == 1) or (_health == 0) */
[8187]1255}
1256
[3659]1257// Constructor
1258//////////////////////////////////////////////////////////////////////////////
[9367]1259t_ephGal::t_ephGal(double rnxVersion, const QStringList& lines) {
[6809]1260 int year, month, day, hour, min;
1261 double sec;
1262 QString prnStr;
[4891]1263 const int nLines = 8;
1264 if (lines.size() != nLines) {
[6518]1265 _checkState = bad;
[4891]1266 return;
1267 }
1268
1269 // RINEX Format
1270 // ------------
1271 int fieldLen = 19;
[6792]1272 double SVhealth = 0.0;
1273 double datasource = 0.0;
[6798]1274
[4891]1275 int pos[4];
1276 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
1277 pos[1] = pos[0] + fieldLen;
1278 pos[2] = pos[1] + fieldLen;
1279 pos[3] = pos[2] + fieldLen;
1280
1281 // Read eight lines
1282 // ----------------
1283 for (int iLine = 0; iLine < nLines; iLine++) {
1284 QString line = lines[iLine];
1285
1286 if ( iLine == 0 ) {
[8204]1287 QTextStream in(line.left(pos[1]).toLatin1());
[7140]1288 QString n;
[6880]1289 in >> prnStr;
[7639]1290 if (prnStr.size() == 1 && prnStr[0] == 'E') {
[7139]1291 in >> n;
1292 prnStr.append(n);
[6880]1293 }
1294 in >> year >> month >> day >> hour >> min >> sec;
[4891]1295 if (year < 80) {
1296 year += 2000;
1297 }
1298 else if (year < 100) {
1299 year += 1900;
1300 }
1301
1302 _TOC.set(year, month, day, hour, min, sec);
1303
1304 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
1305 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
1306 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
[6518]1307 _checkState = bad;
[4891]1308 return;
1309 }
1310 }
[9788]1311 // =====================
1312 // BROADCAST ORBIT - 1
1313 // =====================
[4891]1314 else if ( iLine == 1 ) {
1315 if ( readDbl(line, pos[0], fieldLen, _IODnav ) ||
1316 readDbl(line, pos[1], fieldLen, _Crs ) ||
1317 readDbl(line, pos[2], fieldLen, _Delta_n) ||
1318 readDbl(line, pos[3], fieldLen, _M0 ) ) {
[6518]1319 _checkState = bad;
[4891]1320 return;
1321 }
1322 }
[9788]1323 // =====================
1324 // BROADCAST ORBIT - 2
1325 // =====================
[4891]1326 else if ( iLine == 2 ) {
1327 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
1328 readDbl(line, pos[1], fieldLen, _e ) ||
1329 readDbl(line, pos[2], fieldLen, _Cus ) ||
1330 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
[6518]1331 _checkState = bad;
[4891]1332 return;
1333 }
1334 }
[9788]1335 // =====================
1336 // BROADCAST ORBIT - 3
1337 // =====================
[4891]1338 else if ( iLine == 3 ) {
1339 if ( readDbl(line, pos[0], fieldLen, _TOEsec) ||
1340 readDbl(line, pos[1], fieldLen, _Cic ) ||
1341 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
1342 readDbl(line, pos[3], fieldLen, _Cis ) ) {
[6518]1343 _checkState = bad;
[4891]1344 return;
1345 }
1346 }
[9788]1347 // =====================
1348 // BROADCAST ORBIT - 4
1349 // =====================
[4891]1350 else if ( iLine == 4 ) {
1351 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
1352 readDbl(line, pos[1], fieldLen, _Crc ) ||
1353 readDbl(line, pos[2], fieldLen, _omega ) ||
1354 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
[6518]1355 _checkState = bad;
[4891]1356 return;
1357 }
1358 }
[9788]1359 // =====================
1360 // BROADCAST ORBIT - 5
1361 // =====================
[4891]1362 else if ( iLine == 5 ) {
[6792]1363 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
1364 readDbl(line, pos[1], fieldLen, datasource) ||
1365 readDbl(line, pos[2], fieldLen, _TOEweek ) ) {
[6518]1366 _checkState = bad;
[4891]1367 return;
[6792]1368 } else {
1369 if (int(datasource) & (1<<8)) {
[6812]1370 _fnav = true;
1371 _inav = false;
[6792]1372 } else if (int(datasource) & (1<<9)) {
[6812]1373 _fnav = false;
1374 _inav = true;
[6792]1375 }
[6892]1376 _TOEweek -= 1024.0;
[4891]1377 }
1378 }
[9788]1379 // =====================
1380 // BROADCAST ORBIT - 6
1381 // =====================
[4891]1382 else if ( iLine == 6 ) {
1383 if ( readDbl(line, pos[0], fieldLen, _SISA ) ||
[6792]1384 readDbl(line, pos[1], fieldLen, SVhealth) ||
[4891]1385 readDbl(line, pos[2], fieldLen, _BGD_1_5A) ||
1386 readDbl(line, pos[3], fieldLen, _BGD_1_5B) ) {
[6518]1387 _checkState = bad;
[4891]1388 return;
[6792]1389 } else {
1390 // Bit 0
[9367]1391 _e1DataInValid = (int(SVhealth) & (1<<0));
[6792]1392 // Bit 1-2
[9367]1393 _E1_bHS = double((int(SVhealth) >> 1) & 0x3);
[6792]1394 // Bit 3
[6812]1395 _e5aDataInValid = (int(SVhealth) & (1<<3));
[6792]1396 // Bit 4-5
[9367]1397 _E5aHS = double((int(SVhealth) >> 4) & 0x3);
[6792]1398 // Bit 6
[6812]1399 _e5bDataInValid = (int(SVhealth) & (1<<6));
[6792]1400 // Bit 7-8
[9367]1401 _E5bHS = double((int(SVhealth) >> 7) & 0x3);
[6809]1402
1403 if (prnStr.at(0) == 'E') {
[7140]1404 _prn.set('E', prnStr.mid(1).toInt(), _inav ? 1 : 0);
[6809]1405 }
[4891]1406 }
1407 }
[9788]1408 // =====================
1409 // BROADCAST ORBIT - 7
1410 // =====================
[4891]1411 else if ( iLine == 7 ) {
1412 if ( readDbl(line, pos[0], fieldLen, _TOT) ) {
[6518]1413 _checkState = bad;
[4891]1414 return;
1415 }
1416 }
1417 }
[3659]1418}
[4013]1419
[6801]1420// Compute Galileo Satellite Position (virtual)
1421////////////////////////////////////////////////////////////////////////////
1422t_irc t_ephGal::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
[4013]1423
[6801]1424 static const double omegaEarth = 7292115.1467e-11;
[8212]1425 static const double gmWGS = 398.6004418e12;
[4023]1426
[8542]1427 memset(xc, 0, 6*sizeof(double));
[6801]1428 memset(vv, 0, 3*sizeof(double));
[4023]1429
[6801]1430 double a0 = _sqrt_A * _sqrt_A;
1431 if (a0 == 0) {
1432 return failure;
1433 }
[4023]1434
[6801]1435 double n0 = sqrt(gmWGS/(a0*a0*a0));
[4023]1436
[6801]1437 bncTime tt(GPSweek, GPSweeks);
1438 double tk = tt - bncTime(_TOC.gpsw(), _TOEsec);
[4023]1439
[6801]1440 double n = n0 + _Delta_n;
1441 double M = _M0 + n*tk;
1442 double E = M;
1443 double E_last;
[8368]1444 int nLoop = 0;
[6801]1445 do {
1446 E_last = E;
1447 E = M + _e*sin(E);
[8368]1448
1449 if (++nLoop == 100) {
1450 return failure;
1451 }
[6801]1452 } while ( fabs(E-E_last)*a0 > 0.001 );
1453 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
1454 double u0 = v + _omega;
1455 double sin2u0 = sin(2*u0);
1456 double cos2u0 = cos(2*u0);
1457 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
1458 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
1459 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
1460 double xp = r*cos(u);
1461 double yp = r*sin(u);
1462 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
1463 omegaEarth*_TOEsec;
[4023]1464
[6801]1465 double sinom = sin(OM);
1466 double cosom = cos(OM);
1467 double sini = sin(i);
1468 double cosi = cos(i);
1469 xc[0] = xp*cosom - yp*cosi*sinom;
1470 xc[1] = xp*sinom + yp*cosi*cosom;
1471 xc[2] = yp*sini;
[4023]1472
[6801]1473 double tc = tt - _TOC;
1474 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
[4023]1475
[6801]1476 // Velocity
1477 // --------
1478 double tanv2 = tan(v/2);
1479 double dEdM = 1 / (1 - _e*cos(E));
1480 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
1481 * dEdM * n;
1482 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
1483 double dotom = _OMEGADOT - omegaEarth;
1484 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
1485 double dotr = a0 * _e*sin(E) * dEdM * n
1486 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
1487 double dotx = dotr*cos(u) - r*sin(u)*dotu;
1488 double doty = dotr*sin(u) + r*cos(u)*dotu;
[4023]1489
[6801]1490 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
1491 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
1492 + yp*sini*sinom*doti; // dX / di
1493
1494 vv[1] = sinom *dotx + cosi*cosom *doty
1495 + xp*cosom*dotom - yp*cosi*sinom*dotom
1496 - yp*sini*cosom*doti;
1497
1498 vv[2] = sini *doty + yp*cosi *doti;
1499
1500 // Relativistic Correction
1501 // -----------------------
[9290]1502 xc[3] -= 4.442807309e-10 * _e * sqrt(a0) *sin(E);
[6801]1503
[8542]1504 xc[4] = _clock_drift + _clock_driftrate*tc;
1505 xc[5] = _clock_driftrate;
[8581]1506
[6801]1507 return success;
[4023]1508}
1509
[8187]1510// Health status of Galileo Ephemeris (virtual)
1511////////////////////////////////////////////////////////////////////////////
1512unsigned int t_ephGal::isUnhealthy() const {
[10315]1513 if (_E5aHS || _E5bHS || _E1_bHS) {
[8187]1514 return 1;
1515 }
[10315]1516 if (_SISA == 255.0) {
1517 return 1;
1518 }
1519 if (_e5aDataInValid || _e5bDataInValid || _e1DataInValid) {
1520 return 1;
1521 }
[8187]1522 return 0;
1523}
1524
[4023]1525// RINEX Format String
1526//////////////////////////////////////////////////////////////////////////////
1527QString t_ephGal::toString(double version) const {
1528
[9765]1529 QString navStr = navTypeString(_navType, _prn, version);
1530 QString rnxStr = navStr + rinexDateStr(_TOC, _prn, version);
[4023]1531
1532 QTextStream out(&rnxStr);
1533
1534 out << QString("%1%2%3\n")
1535 .arg(_clock_bias, 19, 'e', 12)
1536 .arg(_clock_drift, 19, 'e', 12)
1537 .arg(_clock_driftrate, 19, 'e', 12);
1538
1539 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
[9788]1540 // =====================
1541 // BROADCAST ORBIT - 1
1542 // =====================
[4023]1543 out << QString(fmt)
1544 .arg(_IODnav, 19, 'e', 12)
1545 .arg(_Crs, 19, 'e', 12)
1546 .arg(_Delta_n, 19, 'e', 12)
1547 .arg(_M0, 19, 'e', 12);
[9788]1548 // =====================
1549 // BROADCAST ORBIT - 2
1550 // =====================
[4023]1551 out << QString(fmt)
1552 .arg(_Cuc, 19, 'e', 12)
1553 .arg(_e, 19, 'e', 12)
1554 .arg(_Cus, 19, 'e', 12)
1555 .arg(_sqrt_A, 19, 'e', 12);
[9788]1556 // =====================
1557 // BROADCAST ORBIT - 3
1558 // =====================
[4023]1559 out << QString(fmt)
1560 .arg(_TOEsec, 19, 'e', 12)
1561 .arg(_Cic, 19, 'e', 12)
1562 .arg(_OMEGA0, 19, 'e', 12)
1563 .arg(_Cis, 19, 'e', 12);
[9788]1564 // =====================
1565 // BROADCAST ORBIT - 4
1566 // =====================
[4023]1567 out << QString(fmt)
1568 .arg(_i0, 19, 'e', 12)
1569 .arg(_Crc, 19, 'e', 12)
1570 .arg(_omega, 19, 'e', 12)
1571 .arg(_OMEGADOT, 19, 'e', 12);
[9788]1572 // =====================
1573 // BROADCAST ORBIT - 5
1574 // =====================
[6792]1575 int dataSource = 0;
1576 int SVhealth = 0;
1577 double BGD_1_5A = _BGD_1_5A;
1578 double BGD_1_5B = _BGD_1_5B;
[6812]1579 if (_fnav) {
[6792]1580 dataSource |= (1<<1);
1581 dataSource |= (1<<8);
1582 BGD_1_5B = 0.0;
1583 // SVhealth
1584 // Bit 3 : E5a DVS
[6812]1585 if (_e5aDataInValid) {
[6792]1586 SVhealth |= (1<<3);
1587 }
1588 // Bit 4-5: E5a HS
1589 if (_E5aHS == 1.0) {
1590 SVhealth |= (1<<4);
1591 }
1592 else if (_E5aHS == 2.0) {
1593 SVhealth |= (1<<5);
1594 }
1595 else if (_E5aHS == 3.0) {
1596 SVhealth |= (1<<4);
1597 SVhealth |= (1<<5);
1598 }
1599 }
[6812]1600 else if(_inav) {
[6803]1601 // Bit 2 and 0 are set because from MT1046 the data source cannot be determined
1602 // and RNXv3.03 says both can be set if the navigation messages were merged
[5539]1603 dataSource |= (1<<0);
[6792]1604 dataSource |= (1<<2);
[5540]1605 dataSource |= (1<<9);
[6792]1606 // SVhealth
1607 // Bit 0 : E1-B DVS
[6812]1608 if (_e1DataInValid) {
[6792]1609 SVhealth |= (1<<0);
1610 }
1611 // Bit 1-2: E1-B HS
1612 if (_E1_bHS == 1.0) {
1613 SVhealth |= (1<<1);
1614 }
1615 else if (_E1_bHS == 2.0) {
1616 SVhealth |= (1<<2);
1617 }
[6803]1618 else if (_E1_bHS == 3.0) {
[6792]1619 SVhealth |= (1<<1);
1620 SVhealth |= (1<<2);
1621 }
[6802]1622 // Bit 3 : E5a DVS
[6812]1623 if (_e5aDataInValid) {
[6802]1624 SVhealth |= (1<<3);
1625 }
1626 // Bit 4-5: E5a HS
1627 if (_E5aHS == 1.0) {
1628 SVhealth |= (1<<4);
1629 }
1630 else if (_E5aHS == 2.0) {
1631 SVhealth |= (1<<5);
1632 }
[6803]1633 else if (_E5aHS == 3.0) {
[6802]1634 SVhealth |= (1<<4);
1635 SVhealth |= (1<<5);
1636 }
[6792]1637 // Bit 6 : E5b DVS
[6812]1638 if (_e5bDataInValid) {
[6792]1639 SVhealth |= (1<<6);
1640 }
1641 // Bit 7-8: E5b HS
1642 if (_E5bHS == 1.0) {
1643 SVhealth |= (1<<7);
1644 }
1645 else if (_E5bHS == 2.0) {
1646 SVhealth |= (1<<8);
1647 }
[6803]1648 else if (_E5bHS == 3.0) {
[6792]1649 SVhealth |= (1<<7);
1650 SVhealth |= (1<<8);
1651 }
[5539]1652 }
[6792]1653
[4023]1654 out << QString(fmt)
[5532]1655 .arg(_IDOT, 19, 'e', 12)
1656 .arg(double(dataSource), 19, 'e', 12)
[6892]1657 .arg(_TOEweek + 1024.0, 19, 'e', 12)
[5532]1658 .arg(0.0, 19, 'e', 12);
[9788]1659 // =====================
1660 // BROADCAST ORBIT - 6
1661 // =====================
[4023]1662 out << QString(fmt)
[6798]1663 .arg(_SISA, 19, 'e', 12)
[6792]1664 .arg(double(SVhealth), 19, 'e', 12)
1665 .arg(BGD_1_5A, 19, 'e', 12)
1666 .arg(BGD_1_5B, 19, 'e', 12);
[9788]1667 // =====================
1668 // BROADCAST ORBIT - 7
1669 // =====================
[7922]1670 double tot = _TOT;
1671 if (tot == 0.9999e9 && version < 3.0) {
1672 tot = 0.0;
1673 }
[4023]1674 out << QString(fmt)
[7922]1675 .arg(tot, 19, 'e', 12)
[4024]1676 .arg("", 19, QChar(' '))
1677 .arg("", 19, QChar(' '))
1678 .arg("", 19, QChar(' '));
[4023]1679
1680 return rnxStr;
1681}
1682
[6385]1683// Constructor
1684//////////////////////////////////////////////////////////////////////////////
[9367]1685t_ephSBAS::t_ephSBAS(double rnxVersion, const QStringList& lines) {
[6390]1686
1687 const int nLines = 4;
1688
1689 if (lines.size() != nLines) {
[6518]1690 _checkState = bad;
[6390]1691 return;
1692 }
1693
1694 // RINEX Format
1695 // ------------
1696 int fieldLen = 19;
1697
1698 int pos[4];
1699 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
1700 pos[1] = pos[0] + fieldLen;
1701 pos[2] = pos[1] + fieldLen;
1702 pos[3] = pos[2] + fieldLen;
1703
1704 // Read four lines
1705 // ---------------
1706 for (int iLine = 0; iLine < nLines; iLine++) {
1707 QString line = lines[iLine];
1708
1709 if ( iLine == 0 ) {
[8204]1710 QTextStream in(line.left(pos[1]).toLatin1());
[6390]1711
1712 int year, month, day, hour, min;
1713 double sec;
[6880]1714
[7139]1715 QString prnStr, n;
[6880]1716 in >> prnStr;
[7639]1717 if (prnStr.size() == 1 && prnStr[0] == 'S') {
[7139]1718 in >> n;
1719 prnStr.append(n);
[6880]1720 }
1721 in >> year >> month >> day >> hour >> min >> sec;
[6390]1722 if (prnStr.at(0) == 'S') {
1723 _prn.set('S', prnStr.mid(1).toInt());
1724 }
1725 else {
1726 _prn.set('S', prnStr.toInt());
1727 }
1728
1729 if (year < 80) {
1730 year += 2000;
1731 }
1732 else if (year < 100) {
1733 year += 1900;
1734 }
1735
1736 _TOC.set(year, month, day, hour, min, sec);
1737
1738 if ( readDbl(line, pos[1], fieldLen, _agf0 ) ||
1739 readDbl(line, pos[2], fieldLen, _agf1 ) ||
[8456]1740 readDbl(line, pos[3], fieldLen, _TOT ) ) {
[6518]1741 _checkState = bad;
[6390]1742 return;
1743 }
1744 }
[9788]1745 // =====================
1746 // BROADCAST ORBIT - 1
1747 // =====================
[6390]1748 else if ( iLine == 1 ) {
1749 if ( readDbl(line, pos[0], fieldLen, _x_pos ) ||
1750 readDbl(line, pos[1], fieldLen, _x_velocity ) ||
1751 readDbl(line, pos[2], fieldLen, _x_acceleration) ||
1752 readDbl(line, pos[3], fieldLen, _health ) ) {
[6518]1753 _checkState = bad;
[6390]1754 return;
1755 }
1756 }
[9788]1757 // =====================
1758 // BROADCAST ORBIT - 2
1759 // =====================
[6390]1760 else if ( iLine == 2 ) {
1761 if ( readDbl(line, pos[0], fieldLen, _y_pos ) ||
1762 readDbl(line, pos[1], fieldLen, _y_velocity ) ||
1763 readDbl(line, pos[2], fieldLen, _y_acceleration ) ||
1764 readDbl(line, pos[3], fieldLen, _ura ) ) {
[6518]1765 _checkState = bad;
[6390]1766 return;
1767 }
1768 }
[9788]1769 // =====================
1770 // BROADCAST ORBIT - 3
1771 // =====================
[6390]1772 else if ( iLine == 3 ) {
[6536]1773 double iodn;
[6390]1774 if ( readDbl(line, pos[0], fieldLen, _z_pos ) ||
1775 readDbl(line, pos[1], fieldLen, _z_velocity ) ||
1776 readDbl(line, pos[2], fieldLen, _z_acceleration) ||
[6536]1777 readDbl(line, pos[3], fieldLen, iodn ) ) {
[6518]1778 _checkState = bad;
[6390]1779 return;
[6891]1780 } else {
[6536]1781 _IODN = int(iodn);
[6390]1782 }
1783 }
1784 }
1785
[7278]1786 _x_pos *= 1.e3;
1787 _y_pos *= 1.e3;
1788 _z_pos *= 1.e3;
1789 _x_velocity *= 1.e3;
1790 _y_velocity *= 1.e3;
1791 _z_velocity *= 1.e3;
1792 _x_acceleration *= 1.e3;
1793 _y_acceleration *= 1.e3;
1794 _z_acceleration *= 1.e3;
[6385]1795}
1796
[7054]1797// IOD of SBAS Ephemeris (virtual)
1798////////////////////////////////////////////////////////////////////////////
1799
[7169]1800unsigned int t_ephSBAS::IOD() const {
[7054]1801 unsigned char buffer[80];
1802 int size = 0;
1803 int numbits = 0;
1804 long long bitbuffer = 0;
1805 unsigned char *startbuffer = buffer;
1806
1807 SBASADDBITSFLOAT(30, this->_x_pos, 0.08)
1808 SBASADDBITSFLOAT(30, this->_y_pos, 0.08)
1809 SBASADDBITSFLOAT(25, this->_z_pos, 0.4)
1810 SBASADDBITSFLOAT(17, this->_x_velocity, 0.000625)
1811 SBASADDBITSFLOAT(17, this->_y_velocity, 0.000625)
1812 SBASADDBITSFLOAT(18, this->_z_velocity, 0.004)
1813 SBASADDBITSFLOAT(10, this->_x_acceleration, 0.0000125)
1814 SBASADDBITSFLOAT(10, this->_y_acceleration, 0.0000125)
1815 SBASADDBITSFLOAT(10, this->_z_acceleration, 0.0000625)
1816 SBASADDBITSFLOAT(12, this->_agf0, 1.0/static_cast<double>(1<<30)/static_cast<double>(1<<1))
1817 SBASADDBITSFLOAT(8, this->_agf1, 1.0/static_cast<double>(1<<30)/static_cast<double>(1<<10))
1818 SBASADDBITS(5,0); // the last byte is filled by 0-bits to obtain a length of an integer multiple of 8
1819
1820 return CRC24(size, startbuffer);
1821}
1822
[6385]1823// Compute SBAS Satellite Position (virtual)
1824////////////////////////////////////////////////////////////////////////////
1825t_irc t_ephSBAS::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
[6386]1826
1827 bncTime tt(GPSweek, GPSweeks);
1828 double dt = tt - _TOC;
1829
[7278]1830 xc[0] = _x_pos + _x_velocity * dt + _x_acceleration * dt * dt / 2.0;
1831 xc[1] = _y_pos + _y_velocity * dt + _y_acceleration * dt * dt / 2.0;
1832 xc[2] = _z_pos + _z_velocity * dt + _z_acceleration * dt * dt / 2.0;
[6386]1833
1834 vv[0] = _x_velocity + _x_acceleration * dt;
1835 vv[1] = _y_velocity + _y_acceleration * dt;
1836 vv[2] = _z_velocity + _z_acceleration * dt;
1837
1838 xc[3] = _agf0 + _agf1 * dt;
1839
[8542]1840 xc[4] = _agf1;
1841 xc[5] = 0.0;
[8483]1842
[6386]1843 return success;
[6385]1844}
1845
[9774]1846// Health status of SBAS Ephemeris (virtual)
1847////////////////////////////////////////////////////////////////////////////
1848unsigned int t_ephSBAS::isUnhealthy() const {
1849
1850 // Bit 5
1851 bool URAindexIs15 = (int(_health) & (1<<5));
1852 if (URAindexIs15) {
1853 // in this case it is recommended
1854 // to set the bits 0,1,2,3 to 1 (MT17health = 15)
1855 return 1;
1856 }
1857
1858 // Bit 0-3
1859 int MT17health = (int(_health)) & (0x0f);
1860 if (MT17health) {
1861 return 1;
1862 }
1863
1864 // Bit 4
1865 // bool MT17HealthIsUnavailable = (int(_health) & (1<<4));
1866 // is not used because the MT17health bits can be independently set if URA index is 15
1867
1868 return 0;
1869}
1870
1871
[6385]1872// RINEX Format String
1873//////////////////////////////////////////////////////////////////////////////
[6388]1874QString t_ephSBAS::toString(double version) const {
1875
[9765]1876 QString navStr = navTypeString(_navType, _prn, version);
1877 QString rnxStr = navStr + rinexDateStr(_TOC, _prn, version);
[6388]1878
1879 QTextStream out(&rnxStr);
1880
1881 out << QString("%1%2%3\n")
[6390]1882 .arg(_agf0, 19, 'e', 12)
1883 .arg(_agf1, 19, 'e', 12)
[8456]1884 .arg(_TOT, 19, 'e', 12);
[6388]1885
1886 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
[9788]1887 // =====================
1888 // BROADCAST ORBIT - 1
1889 // =====================
[6388]1890 out << QString(fmt)
1891 .arg(1.e-3*_x_pos, 19, 'e', 12)
1892 .arg(1.e-3*_x_velocity, 19, 'e', 12)
1893 .arg(1.e-3*_x_acceleration, 19, 'e', 12)
[6390]1894 .arg(_health, 19, 'e', 12);
[9788]1895 // =====================
1896 // BROADCAST ORBIT - 2
1897 // =====================
[6388]1898 out << QString(fmt)
1899 .arg(1.e-3*_y_pos, 19, 'e', 12)
1900 .arg(1.e-3*_y_velocity, 19, 'e', 12)
1901 .arg(1.e-3*_y_acceleration, 19, 'e', 12)
[6390]1902 .arg(_ura, 19, 'e', 12);
[9788]1903 // =====================
1904 // BROADCAST ORBIT - 3
1905 // =====================
[6388]1906 out << QString(fmt)
1907 .arg(1.e-3*_z_pos, 19, 'e', 12)
1908 .arg(1.e-3*_z_velocity, 19, 'e', 12)
1909 .arg(1.e-3*_z_acceleration, 19, 'e', 12)
[6536]1910 .arg(double(_IODN), 19, 'e', 12);
[6388]1911
1912 return rnxStr;
[6385]1913}
[6400]1914
1915// Constructor
1916//////////////////////////////////////////////////////////////////////////////
[9367]1917t_ephBDS::t_ephBDS(double rnxVersion, const QStringList& lines) {
[6400]1918
[9788]1919 int nLines = 8;
[6400]1920
[9788]1921 if (navType() == t_eph::CNV1 ||
1922 navType() == t_eph::CNV2) {
1923 nLines += 2;
1924 }
1925 if (navType() == t_eph::CNV3) {
1926 nLines += 1;
1927 }
1928
[6400]1929 if (lines.size() != nLines) {
[6518]1930 _checkState = bad;
[6400]1931 return;
1932 }
1933
1934 // RINEX Format
1935 // ------------
1936 int fieldLen = 19;
1937
1938 int pos[4];
1939 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
1940 pos[1] = pos[0] + fieldLen;
1941 pos[2] = pos[1] + fieldLen;
1942 pos[3] = pos[2] + fieldLen;
1943
1944 // Read eight lines
1945 // ----------------
1946 for (int iLine = 0; iLine < nLines; iLine++) {
1947 QString line = lines[iLine];
1948
1949 if ( iLine == 0 ) {
[8204]1950 QTextStream in(line.left(pos[1]).toLatin1());
[6400]1951
1952 int year, month, day, hour, min;
1953 double sec;
[6880]1954
[7139]1955 QString prnStr, n;
[6880]1956 in >> prnStr;
[7639]1957 if (prnStr.size() == 1 && prnStr[0] == 'C') {
[7139]1958 in >> n;
1959 prnStr.append(n);
[6880]1960 }
1961 in >> year >> month >> day >> hour >> min >> sec;
[6400]1962 if (prnStr.at(0) == 'C') {
1963 _prn.set('C', prnStr.mid(1).toInt());
1964 }
1965 else {
1966 _prn.set('C', prnStr.toInt());
1967 }
1968
1969 if (year < 80) {
1970 year += 2000;
1971 }
1972 else if (year < 100) {
1973 year += 1900;
1974 }
1975
[6812]1976 _TOC.setBDS(year, month, day, hour, min, sec);
[6400]1977
1978 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
1979 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
1980 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
[6518]1981 _checkState = bad;
[6400]1982 return;
1983 }
1984 }
[9788]1985 // =====================
1986 // BROADCAST ORBIT - 1
1987 // =====================
[6400]1988 else if ( iLine == 1 ) {
1989 double aode;
1990 if ( readDbl(line, pos[0], fieldLen, aode ) ||
1991 readDbl(line, pos[1], fieldLen, _Crs ) ||
1992 readDbl(line, pos[2], fieldLen, _Delta_n) ||
1993 readDbl(line, pos[3], fieldLen, _M0 ) ) {
[6518]1994 _checkState = bad;
[6400]1995 return;
1996 }
1997 _AODE = int(aode);
1998 }
[9788]1999 // =====================
2000 // BROADCAST ORBIT - 2
2001 // =====================
[6400]2002 else if ( iLine == 2 ) {
2003 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
2004 readDbl(line, pos[1], fieldLen, _e ) ||
2005 readDbl(line, pos[2], fieldLen, _Cus ) ||
2006 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
[6518]2007 _checkState = bad;
[6400]2008 return;
2009 }
2010 }
[9788]2011 // =====================
2012 // BROADCAST ORBIT - 3
2013 // =====================
[6400]2014 else if ( iLine == 3 ) {
[6812]2015 if ( readDbl(line, pos[0], fieldLen, _TOEsec ) ||
[6400]2016 readDbl(line, pos[1], fieldLen, _Cic ) ||
2017 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
2018 readDbl(line, pos[3], fieldLen, _Cis ) ) {
[6518]2019 _checkState = bad;
[6400]2020 return;
2021 }
2022 }
[9788]2023 // =====================
2024 // BROADCAST ORBIT - 4
2025 // =====================
[6400]2026 else if ( iLine == 4 ) {
2027 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
2028 readDbl(line, pos[1], fieldLen, _Crc ) ||
2029 readDbl(line, pos[2], fieldLen, _omega ) ||
2030 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
[6518]2031 _checkState = bad;
[6400]2032 return;
2033 }
2034 }
[9788]2035 // =====================
2036 // BROADCAST ORBIT - 5
2037 // =====================
2038 else if ( iLine == 5 ) {
[6400]2039
[9788]2040 if (navType() == t_eph::CNV1 ||
2041 navType() == t_eph::CNV2 ||
2042 navType() == t_eph::CNV3 ) {
2043 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
2044 readDbl(line, pos[1], fieldLen, _Delta_n_dot) ||
2045 readDbl(line, pos[2], fieldLen, _satType ) ||
2046 readDbl(line, pos[3], fieldLen, _top ) ) {
2047 _checkState = bad;
2048 return;
2049 }
[6400]2050 }
[9788]2051 else { // D1, D2, undefined
2052 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
2053 readDbl(line, pos[2], fieldLen, _BDTweek)) {
2054 _checkState = bad;
2055 return;
2056 }
2057 }
[6400]2058 }
[9788]2059 // =====================
2060 // BROADCAST ORBIT - 6
2061 // =====================
[6400]2062 else if ( iLine == 6 ) {
[9788]2063 if (navType() == t_eph::CNV1 ||
2064 navType() == t_eph::CNV2 ||
2065 navType() == t_eph::CNV3 ) {
2066 if ( readDbl(line, pos[0], fieldLen, _SISAI_oe ) ||
2067 readDbl(line, pos[1], fieldLen, _SISAI_ocb ) ||
2068 readDbl(line, pos[2], fieldLen, _SISAI_oc1 ) ||
2069 readDbl(line, pos[3], fieldLen, _SISAI_oc2 ) ) {
2070 _checkState = bad;
2071 return;
2072 }
[6400]2073 }
[9788]2074 else { // D1, D2, undefined
2075 double SatH1;
2076 if ( readDbl(line, pos[0], fieldLen, _URA ) ||
2077 readDbl(line, pos[1], fieldLen, SatH1) ||
2078 readDbl(line, pos[2], fieldLen, _TGD1) ||
2079 readDbl(line, pos[3], fieldLen, _TGD2) ) {
2080 _checkState = bad;
2081 return;
2082 }
2083 _SatH1 = int(SatH1);
2084 }
[6400]2085 }
[9788]2086 // =====================
2087 // BROADCAST ORBIT - 7
2088 // =====================
[6400]2089 else if ( iLine == 7 ) {
[9788]2090 if (navType() == t_eph::CNV1) {
2091 if ( readDbl(line, pos[0], fieldLen, _ISC_B1Cd) ||
2092 readDbl(line, pos[2], fieldLen, _TGD_B1Cp) ||
2093 readDbl(line, pos[3], fieldLen, _TGD_B2ap) ) {
2094 _checkState = bad;
2095 return;
2096 }
[6400]2097 }
[9788]2098 else if (navType() == t_eph::CNV2) {
2099 if ( readDbl(line, pos[1], fieldLen, _ISC_B2ad) ||
2100 readDbl(line, pos[2], fieldLen, _TGD_B1Cp) ||
2101 readDbl(line, pos[3], fieldLen, _TGD_B2ap) ) {
2102 _checkState = bad;
2103 return;
2104 }
[6400]2105 }
[9788]2106 else if (navType() == t_eph::CNV3) {
[9789]2107 double health;
[9788]2108 if ( readDbl(line, pos[0], fieldLen, _SISMAI ) ||
[9789]2109 readDbl(line, pos[1], fieldLen, health ) ||
[9788]2110 readDbl(line, pos[2], fieldLen, _INTEGRITYF_B2b) ||
2111 readDbl(line, pos[3], fieldLen, _TGD_B2bI) ) {
2112 _checkState = bad;
2113 return;
2114 }
[9789]2115 _health = int(health);
[9788]2116 }
2117 else { // D1, D2 or undefined
2118 double aodc;
2119 if ( readDbl(line, pos[0], fieldLen, _TOT) ||
2120 readDbl(line, pos[1], fieldLen, aodc) ) {
2121 _checkState = bad;
2122 return;
2123 }
2124 if (_TOT == 0.9999e9) { // 0.9999e9 means not known (RINEX standard)
2125 _TOT = _TOEsec;
2126 }
2127 _AODC = int(aodc);
2128 }
[6400]2129 }
[9788]2130 // =====================
2131 // BROADCAST ORBIT - 8
2132 // =====================
2133 else if ( iLine == 8 ) {
[9789]2134 double health;
[9788]2135 if (navType() == t_eph::CNV1) {
2136 if ( readDbl(line, pos[0], fieldLen, _SISMAI ) ||
[9789]2137 readDbl(line, pos[1], fieldLen, health ) ||
[9788]2138 readDbl(line, pos[2], fieldLen, _INTEGRITYF_B1C) ||
2139 readDbl(line, pos[3], fieldLen, _IODC) ) {
2140 _checkState = bad;
2141 return;
2142 }
[9789]2143 _health = int(health);
[9788]2144 }
2145 else if (navType() == t_eph::CNV2) {
2146 if ( readDbl(line, pos[0], fieldLen, _SISMAI ) ||
[9789]2147 readDbl(line, pos[1], fieldLen, health ) ||
[9788]2148 readDbl(line, pos[2], fieldLen, _INTEGRITYF_B2aB1C) ||
2149 readDbl(line, pos[3], fieldLen, _IODC) ) {
2150 _checkState = bad;
2151 return;
2152 }
[9789]2153 _health = int(health);
[9788]2154 }
2155 else if (navType() == t_eph::CNV3) {
2156 if ( readDbl(line, pos[0], fieldLen, _TOT)) {
2157 _checkState = bad;
2158 return;
2159 }
2160 }
2161
2162 }
2163 // =====================
2164 // BROADCAST ORBIT - 9
2165 // =====================
2166 else if ( iLine == 9 ) {
2167
2168 if (navType() == t_eph::CNV1 ||
2169 navType() == t_eph::CNV2) {
2170 if ( readDbl(line, pos[0], fieldLen, _TOT) ||
2171 readDbl(line, pos[3], fieldLen, _IODE) ) {
2172 _checkState = bad;
2173 return;
2174 }
2175 }
2176
2177 }
[6400]2178 }
2179
[9788]2180 _TOE.setBDS(int(_BDTweek), _TOEsec);
[6400]2181 // remark: actually should be computed from second_tot
2182 // but it seems to be unreliable in RINEX files
[6843]2183 //_TOT = _TOC.bdssec();
[6400]2184}
2185
[7054]2186// IOD of BDS Ephemeris (virtual)
2187////////////////////////////////////////////////////////////////////////////
[7169]2188unsigned int t_ephBDS::IOD() const {
[9939]2189 return (int(_TOC.gpssec())/720) % 240; //return (int(_TOEsec)/720) % 240;
[7054]2190}
2191
[6601]2192// Compute BDS Satellite Position (virtual)
[6400]2193//////////////////////////////////////////////////////////////////////////////
[6600]2194t_irc t_ephBDS::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
[6400]2195
[6602]2196 static const double gmBDS = 398.6004418e12;
2197 static const double omegaBDS = 7292115.0000e-11;
[6400]2198
2199 xc[0] = xc[1] = xc[2] = xc[3] = 0.0;
2200 vv[0] = vv[1] = vv[2] = 0.0;
2201
2202 bncTime tt(GPSweek, GPSweeks);
2203
2204 if (_sqrt_A == 0) {
2205 return failure;
2206 }
2207 double a0 = _sqrt_A * _sqrt_A;
2208
[6602]2209 double n0 = sqrt(gmBDS/(a0*a0*a0));
[6400]2210 double tk = tt - _TOE;
2211 double n = n0 + _Delta_n;
2212 double M = _M0 + n*tk;
2213 double E = M;
2214 double E_last;
2215 int nLoop = 0;
2216 do {
2217 E_last = E;
2218 E = M + _e*sin(E);
2219
2220 if (++nLoop == 100) {
2221 return failure;
2222 }
2223 } while ( fabs(E-E_last)*a0 > 0.001 );
2224
2225 double v = atan2(sqrt(1-_e*_e) * sin(E), cos(E) - _e);
2226 double u0 = v + _omega;
2227 double sin2u0 = sin(2*u0);
2228 double cos2u0 = cos(2*u0);
2229 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
2230 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
2231 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
2232 double xp = r*cos(u);
2233 double yp = r*sin(u);
2234 double toesec = (_TOE.gpssec() - 14.0);
2235 double sinom = 0;
2236 double cosom = 0;
2237 double sini = 0;
2238 double cosi = 0;
[7278]2239
[7481]2240 // Velocity
2241 // --------
2242 double tanv2 = tan(v/2);
2243 double dEdM = 1 / (1 - _e*cos(E));
2244 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2)
2245 / (1 + tanv2*tanv2) * dEdM * n;
2246 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
2247 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
2248 double dotr = a0 * _e*sin(E) * dEdM * n
2249 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
2250
2251 double dotx = dotr*cos(u) - r*sin(u)*dotu;
2252 double doty = dotr*sin(u) + r*cos(u)*dotu;
2253
[6400]2254 const double iMaxGEO = 10.0 / 180.0 * M_PI;
2255
2256 // MEO/IGSO satellite
2257 // ------------------
2258 if (_i0 > iMaxGEO) {
[6602]2259 double OM = _OMEGA0 + (_OMEGADOT - omegaBDS)*tk - omegaBDS*toesec;
[6400]2260
2261 sinom = sin(OM);
2262 cosom = cos(OM);
2263 sini = sin(i);
2264 cosi = cos(i);
2265
2266 xc[0] = xp*cosom - yp*cosi*sinom;
2267 xc[1] = xp*sinom + yp*cosi*cosom;
[7278]2268 xc[2] = yp*sini;
[7481]2269
2270 // Velocity
2271 // --------
2272
2273 double dotom = _OMEGADOT - t_CST::omega;
2274
2275 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
2276 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
2277 + yp*sini*sinom*doti; // dX / di
2278
2279 vv[1] = sinom *dotx + cosi*cosom *doty
2280 + xp*cosom*dotom - yp*cosi*sinom*dotom
2281 - yp*sini*cosom*doti;
2282
2283 vv[2] = sini *doty + yp*cosi *doti;
2284
[6400]2285 }
2286
2287 // GEO satellite
2288 // -------------
2289 else {
[6602]2290 double OM = _OMEGA0 + _OMEGADOT*tk - omegaBDS*toesec;
2291 double ll = omegaBDS*tk;
[6400]2292
2293 sinom = sin(OM);
2294 cosom = cos(OM);
2295 sini = sin(i);
2296 cosi = cos(i);
2297
2298 double xx = xp*cosom - yp*cosi*sinom;
2299 double yy = xp*sinom + yp*cosi*cosom;
[7278]2300 double zz = yp*sini;
[6400]2301
[7487]2302 Matrix RX = BNC_PPP::t_astro::rotX(-5.0 / 180.0 * M_PI);
2303 Matrix RZ = BNC_PPP::t_astro::rotZ(ll);
[6400]2304
2305 ColumnVector X1(3); X1 << xx << yy << zz;
[7487]2306 ColumnVector X2 = RZ*RX*X1;
[6400]2307
2308 xc[0] = X2(1);
2309 xc[1] = X2(2);
2310 xc[2] = X2(3);
[7278]2311
[7481]2312 double dotom = _OMEGADOT;
[6400]2313
[7481]2314 double vx = cosom *dotx - cosi*sinom *doty
2315 - xp*sinom*dotom - yp*cosi*cosom*dotom
2316 + yp*sini*sinom*doti;
[6400]2317
[7481]2318 double vy = sinom *dotx + cosi*cosom *doty
2319 + xp*cosom*dotom - yp*cosi*sinom*dotom
2320 - yp*sini*cosom*doti;
[7278]2321
[7501]2322 double vz = sini *doty + yp*cosi *doti;
[6400]2323
[7501]2324 ColumnVector V(3); V << vx << vy << vz;
[7481]2325
[7487]2326 Matrix RdotZ(3,3);
[7481]2327 double C = cos(ll);
2328 double S = sin(ll);
2329 Matrix UU(3,3);
2330 UU[0][0] = -S; UU[0][1] = +C; UU[0][2] = 0.0;
2331 UU[1][0] = -C; UU[1][1] = -S; UU[1][2] = 0.0;
2332 UU[2][0] = 0.0; UU[2][1] = 0.0; UU[2][2] = 0.0;
[7487]2333 RdotZ = omegaBDS * UU;
[7481]2334
2335 ColumnVector VV(3);
[7487]2336 VV = RZ*RX*V + RdotZ*RX*X1;
[7481]2337
2338 vv[0] = VV(1);
2339 vv[1] = VV(2);
2340 vv[2] = VV(3);
2341 }
2342
2343 double tc = tt - _TOC;
2344 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
2345
[9132]2346// dotC = _clock_drift + _clock_driftrate*tc
[9290]2347// - 4.442807309e-10*_e * sqrt(a0) * cos(E) * dEdM * n;
[6400]2348
[7481]2349 // Relativistic Correction
2350 // -----------------------
[9290]2351 xc[3] -= 4.442807309e-10 * _e * sqrt(a0) *sin(E);
[7481]2352
[8542]2353 xc[4] = _clock_drift + _clock_driftrate*tc;
2354 xc[5] = _clock_driftrate;
[9126]2355
[6400]2356 return success;
2357}
2358
[9789]2359
2360// Health status of SBAS Ephemeris (virtual)
2361////////////////////////////////////////////////////////////////////////////
2362unsigned int t_ephBDS::isUnhealthy() const {
2363
2364 if (navType() == t_eph::CNV1 ||
2365 navType() == t_eph::CNV2 ||
2366 navType() == t_eph::CNV3) {
2367 return static_cast<unsigned int>(_health);
2368 }
2369
2370 return static_cast<unsigned int>(_SatH1);
2371
2372}
2373
2374
[6400]2375// RINEX Format String
2376//////////////////////////////////////////////////////////////////////////////
[6600]2377QString t_ephBDS::toString(double version) const {
[8419]2378
[9765]2379 QString navStr = navTypeString(_navType, _prn, version);
2380 QString rnxStr = navStr + rinexDateStr(_TOC-14.0, _prn, version);
[6400]2381
2382 QTextStream out(&rnxStr);
2383
2384 out << QString("%1%2%3\n")
2385 .arg(_clock_bias, 19, 'e', 12)
2386 .arg(_clock_drift, 19, 'e', 12)
2387 .arg(_clock_driftrate, 19, 'e', 12);
2388
2389 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
[9788]2390 // =====================
2391 // BROADCAST ORBIT - 1
2392 // =====================
[6400]2393 out << QString(fmt)
2394 .arg(double(_AODE), 19, 'e', 12)
2395 .arg(_Crs, 19, 'e', 12)
2396 .arg(_Delta_n, 19, 'e', 12)
2397 .arg(_M0, 19, 'e', 12);
[9788]2398 // =====================
2399 // BROADCAST ORBIT - 2
2400 // =====================
[6400]2401 out << QString(fmt)
2402 .arg(_Cuc, 19, 'e', 12)
2403 .arg(_e, 19, 'e', 12)
2404 .arg(_Cus, 19, 'e', 12)
2405 .arg(_sqrt_A, 19, 'e', 12);
[9788]2406 // =====================
2407 // BROADCAST ORBIT - 3
2408 // =====================
[6400]2409 out << QString(fmt)
[9785]2410 .arg(_TOEsec, 19, 'e', 12)
[6755]2411 .arg(_Cic, 19, 'e', 12)
2412 .arg(_OMEGA0, 19, 'e', 12)
2413 .arg(_Cis, 19, 'e', 12);
[9788]2414 // =====================
2415 // BROADCAST ORBIT - 4
2416 // =====================
[6400]2417 out << QString(fmt)
2418 .arg(_i0, 19, 'e', 12)
2419 .arg(_Crc, 19, 'e', 12)
2420 .arg(_omega, 19, 'e', 12)
2421 .arg(_OMEGADOT, 19, 'e', 12);
[9788]2422 // =====================
2423 // BROADCAST ORBIT - 5
2424 // =====================
2425 if (navType() == t_eph::CNV1 ||
2426 navType() == t_eph::CNV2 ||
2427 navType() == t_eph::CNV3 ) {
2428 out << QString(fmt)
2429 .arg(_IDOT, 19, 'e', 12)
2430 .arg(_Delta_n_dot, 19, 'e', 12)
2431 .arg(_satType, 19, 'e', 12)
2432 .arg(_top, 19, 'e', 12);
2433 }
2434 else { // D1, D2, undefined
2435 out << QString(fmt)
2436 .arg(_IDOT, 19, 'e', 12)
2437 .arg("", 19, QChar(' '))
2438 .arg(_BDTweek, 19, 'e', 12)
2439 .arg("", 19, QChar(' '));
2440 }
2441 // =====================
2442 // BROADCAST ORBIT - 6
2443 // =====================
2444 if (navType() == t_eph::CNV1 ||
2445 navType() == t_eph::CNV2 ||
2446 navType() == t_eph::CNV3 ) {
2447 out << QString(fmt)
2448 .arg(_SISAI_oe, 19, 'e', 12)
2449 .arg(_SISAI_ocb, 19, 'e', 12)
2450 .arg(_SISAI_oc1, 19, 'e', 12)
2451 .arg(_SISAI_oc2, 19, 'e', 12);
2452 }
2453 else { // D1, D2, undefined
2454 out << QString(fmt)
2455 .arg(_URA, 19, 'e', 12)
2456 .arg(double(_SatH1), 19, 'e', 12)
2457 .arg(_TGD1, 19, 'e', 12)
2458 .arg(_TGD2, 19, 'e', 12);
2459 }
2460 // =====================
2461 // BROADCAST ORBIT - 7
2462 // =====================
2463 if (navType() == t_eph::CNV1) {
2464 out << QString(fmt)
2465 .arg(_ISC_B1Cd, 19, 'e', 12)
2466 .arg("", 19, QChar(' '))
2467 .arg(_TGD_B1Cp, 19, 'e', 12)
2468 .arg(_TGD_B2ap, 19, 'e', 12);
2469 }
2470 else if (navType() == t_eph::CNV2) {
2471 out << QString(fmt)
2472 .arg("", 19, QChar(' '))
2473 .arg(_ISC_B2ad, 19, 'e', 12)
2474 .arg(_TGD_B1Cp, 19, 'e', 12)
2475 .arg(_TGD_B2ap, 19, 'e', 12);
2476 }
2477 else if (navType() == t_eph::CNV3) {
2478 out << QString(fmt)
2479 .arg(_SISMAI, 19, 'e', 12)
[9789]2480 .arg(double(_health), 19, 'e', 12)
[9788]2481 .arg(_INTEGRITYF_B2b, 19, 'e', 12)
2482 .arg(_TGD_B2bI, 19, 'e', 12);
2483 }
2484 else { // D1, D2, undefined
2485 double tots = 0.0;
2486 if (_receptDateTime.isValid()) {// RTCM stream input
2487 tots = _TOE.bdssec();
2488 }
2489 else { // RINEX input
2490 tots = _TOT;
2491 }
2492 out << QString(fmt)
2493 .arg(tots, 19, 'e', 12)
2494 .arg(double(_AODC), 19, 'e', 12)
2495 .arg("", 19, QChar(' '))
2496 .arg("", 19, QChar(' '));
2497 }
[6400]2498
[9788]2499 // =====================
2500 // BROADCAST ORBIT - 8
2501 // =====================
2502 if (navType() == t_eph::CNV1) {
2503 out << QString(fmt)
2504 .arg(_SISMAI, 19, 'e', 12)
[9789]2505 .arg(double(_health), 19, 'e', 12)
[9788]2506 .arg(_INTEGRITYF_B1C, 19, 'e', 12)
2507 .arg(_IODC, 19, 'e', 12);
2508 }
2509 else if (navType() == t_eph::CNV2) {
2510 out << QString(fmt)
2511 .arg(_SISMAI, 19, 'e', 12)
[9789]2512 .arg(double(_health), 19, 'e', 12)
[9788]2513 .arg(_INTEGRITYF_B2aB1C, 19, 'e', 12)
2514 .arg(_IODC, 19, 'e', 12);
2515 }
2516 else if (navType() == t_eph::CNV3) {
2517 out << QString(fmt)
2518 .arg(_TOT, 19, 'e', 12)
2519 .arg("", 19, QChar(' '))
2520 .arg("", 19, QChar(' '))
2521 .arg("", 19, QChar(' '));
2522 }
[6400]2523
[9788]2524 // =====================
2525 // BROADCAST ORBIT - 9
2526 // =====================
2527 if (navType() == t_eph::CNV1 ||
2528 navType() == t_eph::CNV2) {
2529 out << QString(fmt)
2530 .arg(_TOT, 19, 'e', 12)
2531 .arg("", 19, QChar(' '))
2532 .arg("", 19, QChar(' '))
2533 .arg(_IODE, 19, 'e', 12);
2534 }
[6400]2535
[9788]2536
[6400]2537 return rnxStr;
2538}
Note: See TracBrowser for help on using the repository browser.