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

Last change on this file since 10581 was 10580, checked in by stuerze, 2 weeks ago

updates regarding RINEX version 4.02 navigation information

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