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

Last change on this file since 6799 was 6799, checked in by stuerze, 9 years ago

simplification and harmonization of the conversion from accuracy indices into metric values and vice versa

File size: 48.2 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
17using namespace std;
18
19// Constructor
20////////////////////////////////////////////////////////////////////////////
21t_eph::t_eph() {
22 _checkState = unchecked;
23 _orbCorr = 0;
24 _clkCorr = 0;
25 _flags = 0;
26}
27
28//
29////////////////////////////////////////////////////////////////////////////
30void t_eph::setOrbCorr(const t_orbCorr* orbCorr) {
31 delete _orbCorr;
32 _orbCorr = new t_orbCorr(*orbCorr);
33}
34
35//
36////////////////////////////////////////////////////////////////////////////
37void t_eph::setClkCorr(const t_clkCorr* clkCorr) {
38 delete _clkCorr;
39 _clkCorr = new t_clkCorr(*clkCorr);
40}
41
42//
43////////////////////////////////////////////////////////////////////////////
44t_irc t_eph::getCrd(const bncTime& tt, ColumnVector& xc, ColumnVector& vv, bool useCorr) const {
45
46 if (_checkState == bad) {
47 return failure;
48 }
49 const QVector<int> updateInt = QVector<int>() << 1 << 2 << 5 << 10 << 15 << 30
50 << 60 << 120 << 240 << 300 << 600
51 << 900 << 1800 << 3600 << 7200
52 << 10800;
53 xc.ReSize(4);
54 vv.ReSize(3);
55 if (position(tt.gpsw(), tt.gpssec(), xc.data(), vv.data()) != success) {
56 return failure;
57 }
58 if (useCorr) {
59 if (_orbCorr && _clkCorr) {
60 double dtO = tt - _orbCorr->_time;
61 if (_orbCorr->_updateInt) {
62 dtO -= (0.5 * updateInt[_orbCorr->_updateInt]);
63 }
64 ColumnVector dx(3);
65 dx[0] = _orbCorr->_xr[0] + _orbCorr->_dotXr[0] * dtO;
66 dx[1] = _orbCorr->_xr[1] + _orbCorr->_dotXr[1] * dtO;
67 dx[2] = _orbCorr->_xr[2] + _orbCorr->_dotXr[2] * dtO;
68
69 if (_orbCorr->_system == 'R') {
70 RSW_to_XYZ(xc.Rows(1,3), vv.Rows(1,3), dx, dx);
71 }
72
73 xc[0] -= dx[0];
74 xc[1] -= dx[1];
75 xc[2] -= dx[2];
76
77 double dtC = tt - _clkCorr->_time;
78 if (_clkCorr->_updateInt) {
79 dtC -= (0.5 * updateInt[_clkCorr->_updateInt]);
80 }
81 xc[3] += _clkCorr->_dClk + _clkCorr->_dotDClk * dtC + _clkCorr->_dotDotDClk * dtC * dtC;
82 }
83 else {
84 return failure;
85 }
86 }
87 return success;
88}
89
90// Set GPS Satellite Position
91////////////////////////////////////////////////////////////////////////////
92void t_ephGPS::set(const gpsephemeris* ee) {
93
94 _receptDateTime = currentDateAndTimeGPS();
95
96 if (PRN_GPS_START <= ee->satellite && ee->satellite <= PRN_GPS_END) {
97 _prn.set('G', ee->satellite);
98 }
99 else if (PRN_QZSS_START <= ee->satellite && ee->satellite <= PRN_QZSS_END) {
100 _prn.set('J', ee->satellite - PRN_QZSS_START + 1);
101 }
102 else {
103 _checkState = bad;
104 return;
105 }
106
107 _TOC.set(ee->GPSweek, ee->TOC);
108 _clock_bias = ee->clock_bias;
109 _clock_drift = ee->clock_drift;
110 _clock_driftrate = ee->clock_driftrate;
111
112 _IODE = ee->IODE;
113 _Crs = ee->Crs;
114 _Delta_n = ee->Delta_n;
115 _M0 = ee->M0;
116
117 _Cuc = ee->Cuc;
118 _e = ee->e;
119 _Cus = ee->Cus;
120 _sqrt_A = ee->sqrt_A;
121
122 _TOEsec = ee->TOE;
123 _Cic = ee->Cic;
124 _OMEGA0 = ee->OMEGA0;
125 _Cis = ee->Cis;
126
127 _i0 = ee->i0;
128 _Crc = ee->Crc;
129 _omega = ee->omega;
130 _OMEGADOT = ee->OMEGADOT;
131
132 _IDOT = ee->IDOT;
133 _L2Codes = 0.0;
134 _TOEweek = ee->GPSweek;
135 _L2PFlag = 0.0;
136
137 _ura = accuracyFromIndex(ee->URAindex, type());
138
139 _health = ee->SVhealth;
140 _TGD = ee->TGD;
141 _IODC = ee->IODC;
142
143 _TOT = 0.9999e9;
144 _fitInterval = 0.0;
145}
146
147// Compute GPS Satellite Position (virtual)
148////////////////////////////////////////////////////////////////////////////
149t_irc t_ephGPS::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
150
151 if (_checkState == bad) {
152 return failure;
153 }
154
155 static const double omegaEarth = 7292115.1467e-11;
156 static const double gmGRS = 398.6005e12;
157
158 memset(xc, 0, 4*sizeof(double));
159 memset(vv, 0, 3*sizeof(double));
160
161 double a0 = _sqrt_A * _sqrt_A;
162 if (a0 == 0) {
163 return failure;
164 }
165
166 double n0 = sqrt(gmGRS/(a0*a0*a0));
167
168 bncTime tt(GPSweek, GPSweeks);
169 double tk = tt - bncTime(int(_TOEweek), _TOEsec);
170
171 double n = n0 + _Delta_n;
172 double M = _M0 + n*tk;
173 double E = M;
174 double E_last;
175 do {
176 E_last = E;
177 E = M + _e*sin(E);
178 } while ( fabs(E-E_last)*a0 > 0.001 );
179 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
180 double u0 = v + _omega;
181 double sin2u0 = sin(2*u0);
182 double cos2u0 = cos(2*u0);
183 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
184 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
185 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
186 double xp = r*cos(u);
187 double yp = r*sin(u);
188 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
189 omegaEarth*_TOEsec;
190
191 double sinom = sin(OM);
192 double cosom = cos(OM);
193 double sini = sin(i);
194 double cosi = cos(i);
195 xc[0] = xp*cosom - yp*cosi*sinom;
196 xc[1] = xp*sinom + yp*cosi*cosom;
197 xc[2] = yp*sini;
198
199 double tc = tt - _TOC;
200 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
201
202 // Velocity
203 // --------
204 double tanv2 = tan(v/2);
205 double dEdM = 1 / (1 - _e*cos(E));
206 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
207 * dEdM * n;
208 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
209 double dotom = _OMEGADOT - omegaEarth;
210 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
211 double dotr = a0 * _e*sin(E) * dEdM * n
212 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
213 double dotx = dotr*cos(u) - r*sin(u)*dotu;
214 double doty = dotr*sin(u) + r*cos(u)*dotu;
215
216 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
217 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
218 + yp*sini*sinom*doti; // dX / di
219
220 vv[1] = sinom *dotx + cosi*cosom *doty
221 + xp*cosom*dotom - yp*cosi*sinom*dotom
222 - yp*sini*cosom*doti;
223
224 vv[2] = sini *doty + yp*cosi *doti;
225
226 // Relativistic Correction
227 // -----------------------
228 xc[3] -= 2.0 * (xc[0]*vv[0] + xc[1]*vv[1] + xc[2]*vv[2]) / t_CST::c / t_CST::c;
229
230 return success;
231}
232
233// Derivative of the state vector using a simple force model (static)
234////////////////////////////////////////////////////////////////////////////
235ColumnVector t_ephGlo::glo_deriv(double /* tt */, const ColumnVector& xv,
236 double* acc) {
237
238 // State vector components
239 // -----------------------
240 ColumnVector rr = xv.rows(1,3);
241 ColumnVector vv = xv.rows(4,6);
242
243 // Acceleration
244 // ------------
245 static const double gmWGS = 398.60044e12;
246 static const double AE = 6378136.0;
247 static const double OMEGA = 7292115.e-11;
248 static const double C20 = -1082.6257e-6;
249
250 double rho = rr.norm_Frobenius();
251 double t1 = -gmWGS/(rho*rho*rho);
252 double t2 = 3.0/2.0 * C20 * (gmWGS*AE*AE) / (rho*rho*rho*rho*rho);
253 double t3 = OMEGA * OMEGA;
254 double t4 = 2.0 * OMEGA;
255 double z2 = rr(3) * rr(3);
256
257 // Vector of derivatives
258 // ---------------------
259 ColumnVector va(6);
260 va(1) = vv(1);
261 va(2) = vv(2);
262 va(3) = vv(3);
263 va(4) = (t1 + t2*(1.0-5.0*z2/(rho*rho)) + t3) * rr(1) + t4*vv(2) + acc[0];
264 va(5) = (t1 + t2*(1.0-5.0*z2/(rho*rho)) + t3) * rr(2) - t4*vv(1) + acc[1];
265 va(6) = (t1 + t2*(3.0-5.0*z2/(rho*rho)) ) * rr(3) + acc[2];
266
267 return va;
268}
269
270// Compute Glonass Satellite Position (virtual)
271////////////////////////////////////////////////////////////////////////////
272t_irc t_ephGlo::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
273
274 if (_checkState == bad) {
275 return failure;
276 }
277
278 static const double nominalStep = 10.0;
279
280 memset(xc, 0, 4*sizeof(double));
281 memset(vv, 0, 3*sizeof(double));
282
283 double dtPos = bncTime(GPSweek, GPSweeks) - _tt;
284
285 if (fabs(dtPos) > 24*3600.0) {
286 return failure;
287 }
288
289 int nSteps = int(fabs(dtPos) / nominalStep) + 1;
290 double step = dtPos / nSteps;
291
292 double acc[3];
293 acc[0] = _x_acceleration * 1.e3;
294 acc[1] = _y_acceleration * 1.e3;
295 acc[2] = _z_acceleration * 1.e3;
296 for (int ii = 1; ii <= nSteps; ii++) {
297 _xv = rungeKutta4(_tt.gpssec(), _xv, step, acc, glo_deriv);
298 _tt = _tt + step;
299 }
300
301 // Position and Velocity
302 // ---------------------
303 xc[0] = _xv(1);
304 xc[1] = _xv(2);
305 xc[2] = _xv(3);
306
307 vv[0] = _xv(4);
308 vv[1] = _xv(5);
309 vv[2] = _xv(6);
310
311 // Clock Correction
312 // ----------------
313 double dtClk = bncTime(GPSweek, GPSweeks) - _TOC;
314 xc[3] = -_tau + _gamma * dtClk;
315
316 return success;
317}
318
319// IOD of Glonass Ephemeris (virtual)
320////////////////////////////////////////////////////////////////////////////
321int t_ephGlo::IOD() const {
322 bncTime tMoscow = _TOC - _gps_utc + 3 * 3600.0;
323 return int(tMoscow.daysec() / 900);
324}
325
326// Set Glonass Ephemeris
327////////////////////////////////////////////////////////////////////////////
328void t_ephGlo::set(const glonassephemeris* ee) {
329
330 _receptDateTime = currentDateAndTimeGPS();
331
332 _prn.set('R', ee->almanac_number);
333
334 int ww = ee->GPSWeek;
335 int tow = ee->GPSTOW;
336 updatetime(&ww, &tow, ee->tb*1000, 0); // Moscow -> GPS
337
338 // Check the day once more
339 // -----------------------
340 bool timeChanged = false;
341 {
342 const double secPerDay = 24 * 3600.0;
343 const double secPerWeek = 7 * secPerDay;
344 int ww_old = ww;
345 int tow_old = tow;
346 int currentWeek;
347 double currentSec;
348 currentGPSWeeks(currentWeek, currentSec);
349 bncTime currentTime(currentWeek, currentSec);
350 bncTime hTime(ww, (double) tow);
351
352 if (hTime - currentTime > secPerDay/2.0) {
353 timeChanged = true;
354 tow -= int(secPerDay);
355 if (tow < 0) {
356 tow += int(secPerWeek);
357 ww -= 1;
358 }
359 }
360 else if (hTime - currentTime < -secPerDay/2.0) {
361 timeChanged = true;
362 tow += int(secPerDay);
363 if (tow > secPerWeek) {
364 tow -= int(secPerWeek);
365 ww += 1;
366 }
367 }
368
369 if (false && timeChanged && BNC_CORE->mode() == t_bncCore::batchPostProcessing) {
370 bncTime newHTime(ww, (double) tow);
371 cout << "GLONASS " << ee->almanac_number << " Time Changed at "
372 << currentTime.datestr() << " " << currentTime.timestr()
373 << endl
374 << "old: " << hTime.datestr() << " " << hTime.timestr()
375 << endl
376 << "new: " << newHTime.datestr() << " " << newHTime.timestr()
377 << endl
378 << "eph: " << ee->GPSWeek << " " << ee->GPSTOW << " " << ee->tb
379 << endl
380 << "ww, tow (old): " << ww_old << " " << tow_old
381 << endl
382 << "ww, tow (new): " << ww << " " << tow
383 << endl << endl;
384 }
385 }
386
387 bncTime hlpTime(ww, (double) tow);
388 unsigned year, month, day;
389 hlpTime.civil_date(year, month, day);
390 _gps_utc = gnumleap(year, month, day);
391
392 _TOC.set(ww, tow);
393 _E = ee->E;
394 _tau = ee->tau;
395 _gamma = ee->gamma;
396 _x_pos = ee->x_pos;
397 _x_velocity = ee->x_velocity;
398 _x_acceleration = ee->x_acceleration;
399 _y_pos = ee->y_pos;
400 _y_velocity = ee->y_velocity;
401 _y_acceleration = ee->y_acceleration;
402 _z_pos = ee->z_pos;
403 _z_velocity = ee->z_velocity;
404 _z_acceleration = ee->z_acceleration;
405 _health = 0;
406 _frequency_number = ee->frequency_number;
407 _tki = ee->tk-3*60*60; if (_tki < 0) _tki += 86400;
408
409 // Initialize status vector
410 // ------------------------
411 _tt = _TOC;
412
413 _xv(1) = _x_pos * 1.e3;
414 _xv(2) = _y_pos * 1.e3;
415 _xv(3) = _z_pos * 1.e3;
416 _xv(4) = _x_velocity * 1.e3;
417 _xv(5) = _y_velocity * 1.e3;
418 _xv(6) = _z_velocity * 1.e3;
419}
420
421// Set Galileo Satellite Position
422////////////////////////////////////////////////////////////////////////////
423void t_ephGal::set(const galileoephemeris* ee) {
424
425 _receptDateTime = currentDateAndTimeGPS();
426
427 _prn.set('E', ee->satellite);
428
429 _TOC.set(ee->Week, ee->TOC);
430 _clock_bias = ee->clock_bias;
431 _clock_drift = ee->clock_drift;
432 _clock_driftrate = ee->clock_driftrate;
433
434 _IODnav = ee->IODnav;
435 _Crs = ee->Crs;
436 _Delta_n = ee->Delta_n;
437 _M0 = ee->M0;
438
439 _Cuc = ee->Cuc;
440 _e = ee->e;
441 _Cus = ee->Cus;
442 _sqrt_A = ee->sqrt_A;
443
444 _TOEsec = _TOC.gpssec();
445 // _TOEsec = ee->TOE; // TODO:
446
447 _Cic = ee->Cic;
448 _OMEGA0 = ee->OMEGA0;
449 _Cis = ee->Cis;
450
451 _i0 = ee->i0;
452 _Crc = ee->Crc;
453 _omega = ee->omega;
454 _OMEGADOT = ee->OMEGADOT;
455
456 _IDOT = ee->IDOT;
457 _TOEweek = ee->Week;
458
459 _SISA = accuracyFromIndex(ee->SISA, type());
460 _E5aHS = ee->E5aHS;
461 _E5bHS = ee->E5bHS;
462 _E1_bHS = ee->E1_HS;
463 _BGD_1_5A = ee->BGD_1_5A;
464 _BGD_1_5B = ee->BGD_1_5B;
465
466 _TOT = 0.9999e9;
467
468 _flags = ee->flags;
469}
470
471// Compute Galileo Satellite Position (virtual)
472////////////////////////////////////////////////////////////////////////////
473t_irc t_ephGal::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
474
475 if (_checkState == bad) {
476 return failure;
477 }
478
479 static const double omegaEarth = 7292115.1467e-11;
480 static const double gmWGS = 398.60044e12;
481
482 memset(xc, 0, 4*sizeof(double));
483 memset(vv, 0, 3*sizeof(double));
484
485 double a0 = _sqrt_A * _sqrt_A;
486 if (a0 == 0) {
487 return failure;
488 }
489
490 double n0 = sqrt(gmWGS/(a0*a0*a0));
491
492 bncTime tt(GPSweek, GPSweeks);
493 double tk = tt - bncTime(_TOC.gpsw(), _TOEsec);
494
495 double n = n0 + _Delta_n;
496 double M = _M0 + n*tk;
497 double E = M;
498 double E_last;
499 do {
500 E_last = E;
501 E = M + _e*sin(E);
502 } while ( fabs(E-E_last)*a0 > 0.001 );
503 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
504 double u0 = v + _omega;
505 double sin2u0 = sin(2*u0);
506 double cos2u0 = cos(2*u0);
507 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
508 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
509 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
510 double xp = r*cos(u);
511 double yp = r*sin(u);
512 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
513 omegaEarth*_TOEsec;
514
515 double sinom = sin(OM);
516 double cosom = cos(OM);
517 double sini = sin(i);
518 double cosi = cos(i);
519 xc[0] = xp*cosom - yp*cosi*sinom;
520 xc[1] = xp*sinom + yp*cosi*cosom;
521 xc[2] = yp*sini;
522
523 double tc = tt - _TOC;
524 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
525
526 // Velocity
527 // --------
528 double tanv2 = tan(v/2);
529 double dEdM = 1 / (1 - _e*cos(E));
530 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
531 * dEdM * n;
532 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
533 double dotom = _OMEGADOT - omegaEarth;
534 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
535 double dotr = a0 * _e*sin(E) * dEdM * n
536 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
537 double dotx = dotr*cos(u) - r*sin(u)*dotu;
538 double doty = dotr*sin(u) + r*cos(u)*dotu;
539
540 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
541 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
542 + yp*sini*sinom*doti; // dX / di
543
544 vv[1] = sinom *dotx + cosi*cosom *doty
545 + xp*cosom*dotom - yp*cosi*sinom*dotom
546 - yp*sini*cosom*doti;
547
548 vv[2] = sini *doty + yp*cosi *doti;
549
550 // Relativistic Correction
551 // -----------------------
552 // xc(4) -= 4.442807633e-10 * _e * sqrt(a0) *sin(E);
553 xc[3] -= 2.0 * (xc[0]*vv[0] + xc[1]*vv[1] + xc[2]*vv[2]) / t_CST::c / t_CST::c;
554
555 return success;
556}
557
558// Constructor
559//////////////////////////////////////////////////////////////////////////////
560t_ephGPS::t_ephGPS(float rnxVersion, const QStringList& lines) {
561
562 const int nLines = 8;
563
564 if (lines.size() != nLines) {
565 _checkState = bad;
566 return;
567 }
568
569 // RINEX Format
570 // ------------
571 int fieldLen = 19;
572
573 int pos[4];
574 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
575 pos[1] = pos[0] + fieldLen;
576 pos[2] = pos[1] + fieldLen;
577 pos[3] = pos[2] + fieldLen;
578
579 // Read eight lines
580 // ----------------
581 for (int iLine = 0; iLine < nLines; iLine++) {
582 QString line = lines[iLine];
583
584 if ( iLine == 0 ) {
585 QTextStream in(line.left(pos[1]).toAscii());
586
587 int year, month, day, hour, min;
588 double sec;
589
590 QString prnStr;
591 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
592 if (prnStr.at(0) == 'G') {
593 _prn.set('G', prnStr.mid(1).toInt());
594 }
595 else if (prnStr.at(0) == 'J') {
596 _prn.set('J', prnStr.mid(1).toInt());
597 }
598 else {
599 _prn.set('G', prnStr.toInt());
600 }
601
602 if (year < 80) {
603 year += 2000;
604 }
605 else if (year < 100) {
606 year += 1900;
607 }
608
609 _TOC.set(year, month, day, hour, min, sec);
610
611 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
612 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
613 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
614 _checkState = bad;
615 return;
616 }
617 }
618
619 else if ( iLine == 1 ) {
620 if ( readDbl(line, pos[0], fieldLen, _IODE ) ||
621 readDbl(line, pos[1], fieldLen, _Crs ) ||
622 readDbl(line, pos[2], fieldLen, _Delta_n) ||
623 readDbl(line, pos[3], fieldLen, _M0 ) ) {
624 _checkState = bad;
625 return;
626 }
627 }
628
629 else if ( iLine == 2 ) {
630 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
631 readDbl(line, pos[1], fieldLen, _e ) ||
632 readDbl(line, pos[2], fieldLen, _Cus ) ||
633 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
634 _checkState = bad;
635 return;
636 }
637 }
638
639 else if ( iLine == 3 ) {
640 if ( readDbl(line, pos[0], fieldLen, _TOEsec) ||
641 readDbl(line, pos[1], fieldLen, _Cic ) ||
642 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
643 readDbl(line, pos[3], fieldLen, _Cis ) ) {
644 _checkState = bad;
645 return;
646 }
647 }
648
649 else if ( iLine == 4 ) {
650 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
651 readDbl(line, pos[1], fieldLen, _Crc ) ||
652 readDbl(line, pos[2], fieldLen, _omega ) ||
653 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
654 _checkState = bad;
655 return;
656 }
657 }
658
659 else if ( iLine == 5 ) {
660 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
661 readDbl(line, pos[1], fieldLen, _L2Codes) ||
662 readDbl(line, pos[2], fieldLen, _TOEweek ) ||
663 readDbl(line, pos[3], fieldLen, _L2PFlag) ) {
664 _checkState = bad;
665 return;
666 }
667 }
668
669 else if ( iLine == 6 ) {
670 if ( readDbl(line, pos[0], fieldLen, _ura ) ||
671 readDbl(line, pos[1], fieldLen, _health) ||
672 readDbl(line, pos[2], fieldLen, _TGD ) ||
673 readDbl(line, pos[3], fieldLen, _IODC ) ) {
674 _checkState = bad;
675 return;
676 }
677 }
678
679 else if ( iLine == 7 ) {
680 if ( readDbl(line, pos[0], fieldLen, _TOT) ) {
681 _checkState = bad;
682 return;
683 }
684 readDbl(line, pos[1], fieldLen, _fitInterval); // _fitInterval optional
685 }
686 }
687}
688
689// Constructor
690//////////////////////////////////////////////////////////////////////////////
691t_ephGlo::t_ephGlo(float rnxVersion, const QStringList& lines) {
692
693 const int nLines = 4;
694
695 if (lines.size() != nLines) {
696 _checkState = bad;
697 return;
698 }
699
700 // RINEX Format
701 // ------------
702 int fieldLen = 19;
703
704 int pos[4];
705 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
706 pos[1] = pos[0] + fieldLen;
707 pos[2] = pos[1] + fieldLen;
708 pos[3] = pos[2] + fieldLen;
709
710 // Read four lines
711 // ---------------
712 for (int iLine = 0; iLine < nLines; iLine++) {
713 QString line = lines[iLine];
714
715 if ( iLine == 0 ) {
716 QTextStream in(line.left(pos[1]).toAscii());
717
718 int year, month, day, hour, min;
719 double sec;
720
721 QString prnStr;
722 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
723 if (prnStr.at(0) == 'R') {
724 _prn.set('R', prnStr.mid(1).toInt());
725 }
726 else {
727 _prn.set('R', prnStr.toInt());
728 }
729
730 if (year < 80) {
731 year += 2000;
732 }
733 else if (year < 100) {
734 year += 1900;
735 }
736
737 _gps_utc = gnumleap(year, month, day);
738
739 _TOC.set(year, month, day, hour, min, sec);
740 _TOC = _TOC + _gps_utc;
741
742 if ( readDbl(line, pos[1], fieldLen, _tau ) ||
743 readDbl(line, pos[2], fieldLen, _gamma) ||
744 readDbl(line, pos[3], fieldLen, _tki ) ) {
745 _checkState = bad;
746 return;
747 }
748
749 _tau = -_tau;
750 }
751
752 else if ( iLine == 1 ) {
753 if ( readDbl(line, pos[0], fieldLen, _x_pos ) ||
754 readDbl(line, pos[1], fieldLen, _x_velocity ) ||
755 readDbl(line, pos[2], fieldLen, _x_acceleration) ||
756 readDbl(line, pos[3], fieldLen, _health ) ) {
757 _checkState = bad;
758 return;
759 }
760 }
761
762 else if ( iLine == 2 ) {
763 if ( readDbl(line, pos[0], fieldLen, _y_pos ) ||
764 readDbl(line, pos[1], fieldLen, _y_velocity ) ||
765 readDbl(line, pos[2], fieldLen, _y_acceleration ) ||
766 readDbl(line, pos[3], fieldLen, _frequency_number) ) {
767 _checkState = bad;
768 return;
769 }
770 }
771
772 else if ( iLine == 3 ) {
773 if ( readDbl(line, pos[0], fieldLen, _z_pos ) ||
774 readDbl(line, pos[1], fieldLen, _z_velocity ) ||
775 readDbl(line, pos[2], fieldLen, _z_acceleration) ||
776 readDbl(line, pos[3], fieldLen, _E ) ) {
777 _checkState = bad;
778 return;
779 }
780 }
781 }
782
783 // Initialize status vector
784 // ------------------------
785 _tt = _TOC;
786 _xv.ReSize(6);
787 _xv(1) = _x_pos * 1.e3;
788 _xv(2) = _y_pos * 1.e3;
789 _xv(3) = _z_pos * 1.e3;
790 _xv(4) = _x_velocity * 1.e3;
791 _xv(5) = _y_velocity * 1.e3;
792 _xv(6) = _z_velocity * 1.e3;
793}
794
795// Constructor
796//////////////////////////////////////////////////////////////////////////////
797t_ephGal::t_ephGal(float rnxVersion, const QStringList& lines) {
798
799 const int nLines = 8;
800
801 if (lines.size() != nLines) {
802 _checkState = bad;
803 return;
804 }
805
806 // RINEX Format
807 // ------------
808 int fieldLen = 19;
809 double SVhealth = 0.0;
810 double datasource = 0.0;
811
812 int pos[4];
813 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
814 pos[1] = pos[0] + fieldLen;
815 pos[2] = pos[1] + fieldLen;
816 pos[3] = pos[2] + fieldLen;
817
818 // Read eight lines
819 // ----------------
820 for (int iLine = 0; iLine < nLines; iLine++) {
821 QString line = lines[iLine];
822
823 if ( iLine == 0 ) {
824 QTextStream in(line.left(pos[1]).toAscii());
825
826 int year, month, day, hour, min;
827 double sec;
828
829 QString prnStr;
830 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
831 if (prnStr.at(0) == 'E') {
832 _prn.set('E', prnStr.mid(1).toInt());
833 }
834 else {
835 _prn.set('E', prnStr.toInt());
836 }
837
838 if (year < 80) {
839 year += 2000;
840 }
841 else if (year < 100) {
842 year += 1900;
843 }
844
845 _TOC.set(year, month, day, hour, min, sec);
846
847 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
848 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
849 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
850 _checkState = bad;
851 return;
852 }
853 }
854
855 else if ( iLine == 1 ) {
856 if ( readDbl(line, pos[0], fieldLen, _IODnav ) ||
857 readDbl(line, pos[1], fieldLen, _Crs ) ||
858 readDbl(line, pos[2], fieldLen, _Delta_n) ||
859 readDbl(line, pos[3], fieldLen, _M0 ) ) {
860 _checkState = bad;
861 return;
862 }
863 }
864
865 else if ( iLine == 2 ) {
866 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
867 readDbl(line, pos[1], fieldLen, _e ) ||
868 readDbl(line, pos[2], fieldLen, _Cus ) ||
869 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
870 _checkState = bad;
871 return;
872 }
873 }
874
875 else if ( iLine == 3 ) {
876 if ( readDbl(line, pos[0], fieldLen, _TOEsec) ||
877 readDbl(line, pos[1], fieldLen, _Cic ) ||
878 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
879 readDbl(line, pos[3], fieldLen, _Cis ) ) {
880 _checkState = bad;
881 return;
882 }
883 }
884
885 else if ( iLine == 4 ) {
886 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
887 readDbl(line, pos[1], fieldLen, _Crc ) ||
888 readDbl(line, pos[2], fieldLen, _omega ) ||
889 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
890 _checkState = bad;
891 return;
892 }
893 }
894
895 else if ( iLine == 5 ) {
896 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
897 readDbl(line, pos[1], fieldLen, datasource) ||
898 readDbl(line, pos[2], fieldLen, _TOEweek ) ) {
899 _checkState = bad;
900 return;
901 } else {
902 if (int(datasource) & (1<<8)) {
903 _flags |= GALEPHF_FNAV;
904 } else if (int(datasource) & (1<<9)) {
905 _flags |= GALEPHF_INAV;
906 }
907 }
908 }
909
910 else if ( iLine == 6 ) {
911 if ( readDbl(line, pos[0], fieldLen, _SISA ) ||
912 readDbl(line, pos[1], fieldLen, SVhealth) ||
913 readDbl(line, pos[2], fieldLen, _BGD_1_5A) ||
914 readDbl(line, pos[3], fieldLen, _BGD_1_5B) ) {
915 _checkState = bad;
916 return;
917 } else {
918 // Bit 0
919 if (int(SVhealth) & (1<<0)) {
920 _flags |= GALEPHF_E1DINVALID;
921 }
922 // Bit 1-2
923 _E1_bHS = double((int(SVhealth) >> 1) & 0x3);
924 // Bit 3
925 if (int(SVhealth) & (1<<3)) {
926 _flags |= GALEPHF_E5ADINVALID;
927 }
928 // Bit 4-5
929 _E5aHS = double((int(SVhealth) >> 4) & 0x3);
930 // Bit 6
931 if (int(SVhealth) & (1<<6)) {
932 _flags |= GALEPHF_E5BDINVALID;
933 }
934 // Bit 7-8
935 _E5bHS = double((int(SVhealth) >> 7) & 0x3);
936 }
937 }
938
939 else if ( iLine == 7 ) {
940 if ( readDbl(line, pos[0], fieldLen, _TOT) ) {
941 _checkState = bad;
942 return;
943 }
944 }
945 }
946}
947
948//
949//////////////////////////////////////////////////////////////////////////////
950QString t_eph::rinexDateStr(const bncTime& tt, const t_prn& prn, double version) {
951 QString prnStr(prn.toString().c_str());
952 return rinexDateStr(tt, prnStr, version);
953}
954
955//
956//////////////////////////////////////////////////////////////////////////////
957QString t_eph::rinexDateStr(const bncTime& tt, const QString& prnStr, double version) {
958
959 QString datStr;
960
961 unsigned year, month, day, hour, min;
962 double sec;
963 tt.civil_date(year, month, day);
964 tt.civil_time(hour, min, sec);
965
966 QTextStream out(&datStr);
967
968 if (version < 3.0) {
969 QString prnHlp = prnStr.mid(1,2); if (prnHlp[0] == '0') prnHlp[0] = ' ';
970 out << prnHlp << QString(" %1 %2 %3 %4 %5%6")
971 .arg(year % 100, 2, 10, QChar('0'))
972 .arg(month, 2)
973 .arg(day, 2)
974 .arg(hour, 2)
975 .arg(min, 2)
976 .arg(sec, 5, 'f',1);
977 }
978 else {
979 out << prnStr << QString(" %1 %2 %3 %4 %5 %6")
980 .arg(year, 4)
981 .arg(month, 2, 10, QChar('0'))
982 .arg(day, 2, 10, QChar('0'))
983 .arg(hour, 2, 10, QChar('0'))
984 .arg(min, 2, 10, QChar('0'))
985 .arg(int(sec), 2, 10, QChar('0'));
986 }
987
988 return datStr;
989}
990
991// RINEX Format String
992//////////////////////////////////////////////////////////////////////////////
993QString t_ephGPS::toString(double version) const {
994
995 QString rnxStr = rinexDateStr(_TOC, _prn, version);
996
997 QTextStream out(&rnxStr);
998
999 out << QString("%1%2%3\n")
1000 .arg(_clock_bias, 19, 'e', 12)
1001 .arg(_clock_drift, 19, 'e', 12)
1002 .arg(_clock_driftrate, 19, 'e', 12);
1003
1004 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1005
1006 out << QString(fmt)
1007 .arg(_IODE, 19, 'e', 12)
1008 .arg(_Crs, 19, 'e', 12)
1009 .arg(_Delta_n, 19, 'e', 12)
1010 .arg(_M0, 19, 'e', 12);
1011
1012 out << QString(fmt)
1013 .arg(_Cuc, 19, 'e', 12)
1014 .arg(_e, 19, 'e', 12)
1015 .arg(_Cus, 19, 'e', 12)
1016 .arg(_sqrt_A, 19, 'e', 12);
1017
1018 out << QString(fmt)
1019 .arg(_TOEsec, 19, 'e', 12)
1020 .arg(_Cic, 19, 'e', 12)
1021 .arg(_OMEGA0, 19, 'e', 12)
1022 .arg(_Cis, 19, 'e', 12);
1023
1024 out << QString(fmt)
1025 .arg(_i0, 19, 'e', 12)
1026 .arg(_Crc, 19, 'e', 12)
1027 .arg(_omega, 19, 'e', 12)
1028 .arg(_OMEGADOT, 19, 'e', 12);
1029
1030 out << QString(fmt)
1031 .arg(_IDOT, 19, 'e', 12)
1032 .arg(_L2Codes, 19, 'e', 12)
1033 .arg(_TOEweek, 19, 'e', 12)
1034 .arg(_L2PFlag, 19, 'e', 12);
1035
1036 out << QString(fmt)
1037 .arg(_ura, 19, 'e', 12)
1038 .arg(_health, 19, 'e', 12)
1039 .arg(_TGD, 19, 'e', 12)
1040 .arg(_IODC, 19, 'e', 12);
1041
1042 out << QString(fmt)
1043 .arg(_TOT, 19, 'e', 12)
1044 .arg(_fitInterval, 19, 'e', 12)
1045 .arg("", 19, QChar(' '))
1046 .arg("", 19, QChar(' '));
1047
1048 return rnxStr;
1049}
1050
1051// RINEX Format String
1052//////////////////////////////////////////////////////////////////////////////
1053QString t_ephGlo::toString(double version) const {
1054
1055 QString rnxStr = rinexDateStr(_TOC-_gps_utc, _prn, version);
1056
1057 QTextStream out(&rnxStr);
1058
1059 out << QString("%1%2%3\n")
1060 .arg(-_tau, 19, 'e', 12)
1061 .arg(_gamma, 19, 'e', 12)
1062 .arg(_tki, 19, 'e', 12);
1063
1064 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1065
1066 out << QString(fmt)
1067 .arg(_x_pos, 19, 'e', 12)
1068 .arg(_x_velocity, 19, 'e', 12)
1069 .arg(_x_acceleration, 19, 'e', 12)
1070 .arg(_health, 19, 'e', 12);
1071
1072 out << QString(fmt)
1073 .arg(_y_pos, 19, 'e', 12)
1074 .arg(_y_velocity, 19, 'e', 12)
1075 .arg(_y_acceleration, 19, 'e', 12)
1076 .arg(_frequency_number, 19, 'e', 12);
1077
1078 out << QString(fmt)
1079 .arg(_z_pos, 19, 'e', 12)
1080 .arg(_z_velocity, 19, 'e', 12)
1081 .arg(_z_acceleration, 19, 'e', 12)
1082 .arg(_E, 19, 'e', 12);
1083
1084 return rnxStr;
1085}
1086
1087// RINEX Format String
1088//////////////////////////////////////////////////////////////////////////////
1089QString t_ephGal::toString(double version) const {
1090
1091 QString rnxStr = rinexDateStr(_TOC, _prn, version);
1092
1093 QTextStream out(&rnxStr);
1094
1095 out << QString("%1%2%3\n")
1096 .arg(_clock_bias, 19, 'e', 12)
1097 .arg(_clock_drift, 19, 'e', 12)
1098 .arg(_clock_driftrate, 19, 'e', 12);
1099
1100 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1101
1102 out << QString(fmt)
1103 .arg(_IODnav, 19, 'e', 12)
1104 .arg(_Crs, 19, 'e', 12)
1105 .arg(_Delta_n, 19, 'e', 12)
1106 .arg(_M0, 19, 'e', 12);
1107
1108 out << QString(fmt)
1109 .arg(_Cuc, 19, 'e', 12)
1110 .arg(_e, 19, 'e', 12)
1111 .arg(_Cus, 19, 'e', 12)
1112 .arg(_sqrt_A, 19, 'e', 12);
1113
1114 out << QString(fmt)
1115 .arg(_TOEsec, 19, 'e', 12)
1116 .arg(_Cic, 19, 'e', 12)
1117 .arg(_OMEGA0, 19, 'e', 12)
1118 .arg(_Cis, 19, 'e', 12);
1119
1120 out << QString(fmt)
1121 .arg(_i0, 19, 'e', 12)
1122 .arg(_Crc, 19, 'e', 12)
1123 .arg(_omega, 19, 'e', 12)
1124 .arg(_OMEGADOT, 19, 'e', 12);
1125
1126 int dataSource = 0;
1127 int SVhealth = 0;
1128 double BGD_1_5A = _BGD_1_5A;
1129 double BGD_1_5B = _BGD_1_5B;
1130 if ((_flags & GALEPHF_FNAV) == GALEPHF_FNAV) {
1131 dataSource |= (1<<1);
1132 dataSource |= (1<<8);
1133 BGD_1_5B = 0.0;
1134 // SVhealth
1135 // Bit 3 : E5a DVS
1136 if ((_flags & GALEPHF_E5ADINVALID) == GALEPHF_E5ADINVALID) {
1137 SVhealth |= (1<<3);
1138 }
1139 // Bit 4-5: E5a HS
1140 if (_E5aHS == 1.0) {
1141 SVhealth |= (1<<4);
1142 }
1143 else if (_E5aHS == 2.0) {
1144 SVhealth |= (1<<5);
1145 }
1146 else if (_E5aHS == 3.0) {
1147 SVhealth |= (1<<4);
1148 SVhealth |= (1<<5);
1149 }
1150 }
1151 else if ((_flags & GALEPHF_INAV) == GALEPHF_INAV) {
1152 dataSource |= (1<<0);
1153 dataSource |= (1<<2);
1154 dataSource |= (1<<9);
1155 // SVhealth
1156 // Bit 0 : E1-B DVS
1157 if ((_flags & GALEPHF_E1DINVALID) == GALEPHF_E1DINVALID) {
1158 SVhealth |= (1<<0);
1159 }
1160 // Bit 1-2: E1-B HS
1161 if (_E1_bHS == 1.0) {
1162 SVhealth |= (1<<1);
1163 }
1164 else if (_E1_bHS == 2.0) {
1165 SVhealth |= (1<<2);
1166 }
1167 else if (_E1_bHS == 3.0) {
1168 SVhealth |= (1<<1);
1169 SVhealth |= (1<<2);
1170 }
1171 // Bit 6 : E5b DVS
1172 if ((_flags & GALEPHF_E1DINVALID) == GALEPHF_E1DINVALID) {
1173 SVhealth |= (1<<6);
1174 }
1175 // Bit 7-8: E5b HS
1176 if (_E5bHS == 1.0) {
1177 SVhealth |= (1<<7);
1178 }
1179 else if (_E5bHS == 2.0) {
1180 SVhealth |= (1<<8);
1181 }
1182 else if (_E5bHS == 3.0) {
1183 SVhealth |= (1<<7);
1184 SVhealth |= (1<<8);
1185 }
1186 }
1187
1188 out << QString(fmt)
1189 .arg(_IDOT, 19, 'e', 12)
1190 .arg(double(dataSource), 19, 'e', 12)
1191 .arg(_TOEweek, 19, 'e', 12)
1192 .arg(0.0, 19, 'e', 12);
1193
1194 out << QString(fmt)
1195 .arg(_SISA, 19, 'e', 12)
1196 .arg(double(SVhealth), 19, 'e', 12)
1197 .arg(BGD_1_5A, 19, 'e', 12)
1198 .arg(BGD_1_5B, 19, 'e', 12);
1199
1200 out << QString(fmt)
1201 .arg(_TOT, 19, 'e', 12)
1202 .arg("", 19, QChar(' '))
1203 .arg("", 19, QChar(' '))
1204 .arg("", 19, QChar(' '));
1205
1206 return rnxStr;
1207}
1208
1209// Constructor
1210//////////////////////////////////////////////////////////////////////////////
1211t_ephSBAS::t_ephSBAS(float rnxVersion, const QStringList& lines) {
1212
1213 const int nLines = 4;
1214
1215 if (lines.size() != nLines) {
1216 _checkState = bad;
1217 return;
1218 }
1219
1220 // RINEX Format
1221 // ------------
1222 int fieldLen = 19;
1223
1224 int pos[4];
1225 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
1226 pos[1] = pos[0] + fieldLen;
1227 pos[2] = pos[1] + fieldLen;
1228 pos[3] = pos[2] + fieldLen;
1229
1230 // Read four lines
1231 // ---------------
1232 for (int iLine = 0; iLine < nLines; iLine++) {
1233 QString line = lines[iLine];
1234
1235 if ( iLine == 0 ) {
1236 QTextStream in(line.left(pos[1]).toAscii());
1237
1238 int year, month, day, hour, min;
1239 double sec;
1240
1241 QString prnStr;
1242 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
1243 if (prnStr.at(0) == 'S') {
1244 _prn.set('S', prnStr.mid(1).toInt());
1245 }
1246 else {
1247 _prn.set('S', prnStr.toInt());
1248 }
1249
1250 if (year < 80) {
1251 year += 2000;
1252 }
1253 else if (year < 100) {
1254 year += 1900;
1255 }
1256
1257 _TOC.set(year, month, day, hour, min, sec);
1258
1259 if ( readDbl(line, pos[1], fieldLen, _agf0 ) ||
1260 readDbl(line, pos[2], fieldLen, _agf1 ) ||
1261 readDbl(line, pos[3], fieldLen, _TOW ) ) {
1262 _checkState = bad;
1263 return;
1264 }
1265 }
1266
1267 else if ( iLine == 1 ) {
1268 if ( readDbl(line, pos[0], fieldLen, _x_pos ) ||
1269 readDbl(line, pos[1], fieldLen, _x_velocity ) ||
1270 readDbl(line, pos[2], fieldLen, _x_acceleration) ||
1271 readDbl(line, pos[3], fieldLen, _health ) ) {
1272 _checkState = bad;
1273 return;
1274 }
1275 }
1276
1277 else if ( iLine == 2 ) {
1278 if ( readDbl(line, pos[0], fieldLen, _y_pos ) ||
1279 readDbl(line, pos[1], fieldLen, _y_velocity ) ||
1280 readDbl(line, pos[2], fieldLen, _y_acceleration ) ||
1281 readDbl(line, pos[3], fieldLen, _ura ) ) {
1282 _checkState = bad;
1283 return;
1284 }
1285 }
1286
1287 else if ( iLine == 3 ) {
1288 double iodn;
1289 if ( readDbl(line, pos[0], fieldLen, _z_pos ) ||
1290 readDbl(line, pos[1], fieldLen, _z_velocity ) ||
1291 readDbl(line, pos[2], fieldLen, _z_acceleration) ||
1292 readDbl(line, pos[3], fieldLen, iodn ) ) {
1293 _checkState = bad;
1294 return;
1295 _IODN = int(iodn);
1296 }
1297 }
1298 }
1299
1300 _x_pos *= 1.e3;
1301 _y_pos *= 1.e3;
1302 _z_pos *= 1.e3;
1303 _x_velocity *= 1.e3;
1304 _y_velocity *= 1.e3;
1305 _z_velocity *= 1.e3;
1306 _x_acceleration *= 1.e3;
1307 _y_acceleration *= 1.e3;
1308 _z_acceleration *= 1.e3;
1309}
1310
1311// Set SBAS Satellite Position
1312////////////////////////////////////////////////////////////////////////////
1313void t_ephSBAS::set(const sbasephemeris* ee) {
1314
1315 _prn.set('S', ee->satellite - PRN_SBAS_START + 20);
1316 _TOC.set(ee->GPSweek_TOE, double(ee->TOE));
1317
1318 _IODN = ee->IODN;
1319 _TOW = ee->TOW;
1320
1321 _agf0 = ee->agf0;
1322 _agf1 = ee->agf1;
1323
1324 _x_pos = ee->x_pos;
1325 _x_velocity = ee->x_velocity;
1326 _x_acceleration = ee->x_acceleration;
1327
1328 _y_pos = ee->y_pos;
1329 _y_velocity = ee->y_velocity;
1330 _y_acceleration = ee->y_acceleration;
1331
1332 _z_pos = ee->z_pos;
1333 _z_velocity = ee->z_velocity;
1334 _z_acceleration = ee->z_acceleration;
1335
1336 _ura = accuracyFromIndex(ee->URA, type());
1337
1338 _health = 0;
1339}
1340
1341// Compute SBAS Satellite Position (virtual)
1342////////////////////////////////////////////////////////////////////////////
1343t_irc t_ephSBAS::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
1344
1345 if (_checkState == bad) {
1346 return failure;
1347 }
1348
1349 bncTime tt(GPSweek, GPSweeks);
1350 double dt = tt - _TOC;
1351
1352 xc[0] = _x_pos + _x_velocity * dt + _x_acceleration * dt * dt / 2.0;
1353 xc[1] = _y_pos + _y_velocity * dt + _y_acceleration * dt * dt / 2.0;
1354 xc[2] = _z_pos + _z_velocity * dt + _z_acceleration * dt * dt / 2.0;
1355
1356 vv[0] = _x_velocity + _x_acceleration * dt;
1357 vv[1] = _y_velocity + _y_acceleration * dt;
1358 vv[2] = _z_velocity + _z_acceleration * dt;
1359
1360 xc[3] = _agf0 + _agf1 * dt;
1361
1362 return success;
1363}
1364
1365// RINEX Format String
1366//////////////////////////////////////////////////////////////////////////////
1367QString t_ephSBAS::toString(double version) const {
1368
1369 QString rnxStr = rinexDateStr(_TOC, _prn, version);
1370
1371 QTextStream out(&rnxStr);
1372
1373 out << QString("%1%2%3\n")
1374 .arg(_agf0, 19, 'e', 12)
1375 .arg(_agf1, 19, 'e', 12)
1376 .arg(_TOW, 19, 'e', 12);
1377
1378 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1379
1380 out << QString(fmt)
1381 .arg(1.e-3*_x_pos, 19, 'e', 12)
1382 .arg(1.e-3*_x_velocity, 19, 'e', 12)
1383 .arg(1.e-3*_x_acceleration, 19, 'e', 12)
1384 .arg(_health, 19, 'e', 12);
1385
1386 out << QString(fmt)
1387 .arg(1.e-3*_y_pos, 19, 'e', 12)
1388 .arg(1.e-3*_y_velocity, 19, 'e', 12)
1389 .arg(1.e-3*_y_acceleration, 19, 'e', 12)
1390 .arg(_ura, 19, 'e', 12);
1391
1392 out << QString(fmt)
1393 .arg(1.e-3*_z_pos, 19, 'e', 12)
1394 .arg(1.e-3*_z_velocity, 19, 'e', 12)
1395 .arg(1.e-3*_z_acceleration, 19, 'e', 12)
1396 .arg(double(_IODN), 19, 'e', 12);
1397
1398 return rnxStr;
1399}
1400
1401// Constructor
1402//////////////////////////////////////////////////////////////////////////////
1403t_ephBDS::t_ephBDS(float rnxVersion, const QStringList& lines) {
1404
1405 const int nLines = 8;
1406
1407 if (lines.size() != nLines) {
1408 _checkState = bad;
1409 return;
1410 }
1411
1412 // RINEX Format
1413 // ------------
1414 int fieldLen = 19;
1415 double TOEw;
1416
1417 int pos[4];
1418 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
1419 pos[1] = pos[0] + fieldLen;
1420 pos[2] = pos[1] + fieldLen;
1421 pos[3] = pos[2] + fieldLen;
1422
1423 // Read eight lines
1424 // ----------------
1425 for (int iLine = 0; iLine < nLines; iLine++) {
1426 QString line = lines[iLine];
1427
1428 if ( iLine == 0 ) {
1429 QTextStream in(line.left(pos[1]).toAscii());
1430
1431 int year, month, day, hour, min;
1432 double sec;
1433
1434 QString prnStr;
1435 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
1436 if (prnStr.at(0) == 'C') {
1437 _prn.set('C', prnStr.mid(1).toInt());
1438 }
1439 else {
1440 _prn.set('C', prnStr.toInt());
1441 }
1442
1443 if (year < 80) {
1444 year += 2000;
1445 }
1446 else if (year < 100) {
1447 year += 1900;
1448 }
1449
1450 _TOC_bdt.set(year, month, day, hour, min, sec);
1451
1452 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
1453 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
1454 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
1455 _checkState = bad;
1456 return;
1457 }
1458 }
1459
1460 else if ( iLine == 1 ) {
1461 double aode;
1462 if ( readDbl(line, pos[0], fieldLen, aode ) ||
1463 readDbl(line, pos[1], fieldLen, _Crs ) ||
1464 readDbl(line, pos[2], fieldLen, _Delta_n) ||
1465 readDbl(line, pos[3], fieldLen, _M0 ) ) {
1466 _checkState = bad;
1467 return;
1468 }
1469 _AODE = int(aode);
1470 }
1471
1472 else if ( iLine == 2 ) {
1473 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
1474 readDbl(line, pos[1], fieldLen, _e ) ||
1475 readDbl(line, pos[2], fieldLen, _Cus ) ||
1476 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
1477 _checkState = bad;
1478 return;
1479 }
1480 }
1481
1482 else if ( iLine == 3 ) {
1483 if ( readDbl(line, pos[0], fieldLen, _TOEs ) ||
1484 readDbl(line, pos[1], fieldLen, _Cic ) ||
1485 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
1486 readDbl(line, pos[3], fieldLen, _Cis ) ) {
1487 _checkState = bad;
1488 return;
1489 }
1490 }
1491
1492 else if ( iLine == 4 ) {
1493 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
1494 readDbl(line, pos[1], fieldLen, _Crc ) ||
1495 readDbl(line, pos[2], fieldLen, _omega ) ||
1496 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
1497 _checkState = bad;
1498 return;
1499 }
1500 }
1501
1502 else if ( iLine == 5 ) {
1503 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
1504 readDbl(line, pos[2], fieldLen, TOEw) ) {
1505 _checkState = bad;
1506 return;
1507 }
1508 }
1509
1510 else if ( iLine == 6 ) {
1511 double SatH1;
1512 if ( readDbl(line, pos[0], fieldLen, _URA ) ||
1513 readDbl(line, pos[1], fieldLen, SatH1) ||
1514 readDbl(line, pos[2], fieldLen, _TGD1) ||
1515 readDbl(line, pos[3], fieldLen, _TGD2) ) {
1516 _checkState = bad;
1517 return;
1518 }
1519 _SatH1 = int(SatH1);
1520 }
1521
1522 else if ( iLine == 7 ) {
1523 double aodc;
1524 if ( readDbl(line, pos[0], fieldLen, _TOTs) ||
1525 readDbl(line, pos[1], fieldLen, aodc) ) {
1526 _checkState = bad;
1527 return;
1528 }
1529 if (_TOTs == 0.9999e9) { // 0.9999e9 means not known (RINEX standard)
1530 _TOTs = _TOEs;
1531 }
1532 _AODC = int(aodc);
1533 }
1534 }
1535
1536 TOEw += 1356; // BDT -> GPS week number
1537 _TOE_bdt.set(int(TOEw), _TOEs);
1538
1539 // GPS->BDT
1540 // --------
1541 _TOC = _TOC_bdt + 14.0;
1542 _TOE = _TOE_bdt + 14.0;
1543
1544 // remark: actually should be computed from second_tot
1545 // but it seems to be unreliable in RINEX files
1546 _TOT = _TOC;
1547}
1548
1549// Set BDS Satellite Position
1550////////////////////////////////////////////////////////////////////////////
1551void t_ephBDS::set(const bdsephemeris* ee) {
1552
1553 // RTCM usage: set RINEX File entries to zero
1554 // ------------------------------------------
1555 _TOTs = 0.0;
1556 _TOEs = 0.0;
1557
1558 _receptDateTime = currentDateAndTimeGPS();
1559
1560 _prn.set('C', ee->satellite - PRN_BDS_START + 1);
1561
1562 _TOE_bdt.set(1356 + ee->BDSweek, ee->TOE);
1563 _TOE = _TOE_bdt + 14.0;
1564
1565 _TOC_bdt.set(1356 + ee->BDSweek, ee->TOC);
1566 _TOC = _TOC_bdt + 14.0;
1567
1568 _AODE = ee->AODE;
1569 _AODC = ee->AODC;
1570
1571 _clock_bias = ee->clock_bias;
1572 _clock_drift = ee->clock_drift;
1573 _clock_driftrate = ee->clock_driftrate;
1574
1575 _Crs = ee->Crs;
1576 _Delta_n = ee->Delta_n;
1577 _M0 = ee->M0;
1578
1579 _Cuc = ee->Cuc;
1580 _e = ee->e;
1581 _Cus = ee->Cus;
1582 _sqrt_A = ee->sqrt_A;
1583
1584 _Cic = ee->Cic;
1585 _OMEGA0 = ee->OMEGA0;
1586 _Cis = ee->Cis;
1587
1588 _i0 = ee->i0;
1589 _Crc = ee->Crc;
1590 _omega = ee->omega;
1591 _OMEGADOT = ee->OMEGADOT;
1592
1593 _IDOT = ee->IDOT;
1594
1595 _URA = accuracyFromIndex(ee->URAI, type());
1596 _SatH1 = (ee->flags & BDSEPHF_SATH1) ? 1: 0;
1597 _TGD1 = ee->TGD_B1_B3;
1598 _TGD2 = ee->TGD_B2_B3;
1599
1600
1601}
1602
1603// Compute BDS Satellite Position (virtual)
1604//////////////////////////////////////////////////////////////////////////////
1605t_irc t_ephBDS::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
1606
1607 if (_checkState == bad) {
1608 return failure;
1609 }
1610
1611 static const double gmBDS = 398.6004418e12;
1612 static const double omegaBDS = 7292115.0000e-11;
1613
1614 xc[0] = xc[1] = xc[2] = xc[3] = 0.0;
1615 vv[0] = vv[1] = vv[2] = 0.0;
1616
1617 bncTime tt(GPSweek, GPSweeks);
1618
1619 if (_sqrt_A == 0) {
1620 return failure;
1621 }
1622 double a0 = _sqrt_A * _sqrt_A;
1623
1624 double n0 = sqrt(gmBDS/(a0*a0*a0));
1625 double tk = tt - _TOE;
1626 double n = n0 + _Delta_n;
1627 double M = _M0 + n*tk;
1628 double E = M;
1629 double E_last;
1630 int nLoop = 0;
1631 do {
1632 E_last = E;
1633 E = M + _e*sin(E);
1634
1635 if (++nLoop == 100) {
1636 return failure;
1637 }
1638 } while ( fabs(E-E_last)*a0 > 0.001 );
1639
1640 double v = atan2(sqrt(1-_e*_e) * sin(E), cos(E) - _e);
1641 double u0 = v + _omega;
1642 double sin2u0 = sin(2*u0);
1643 double cos2u0 = cos(2*u0);
1644 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
1645 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
1646 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
1647 double xp = r*cos(u);
1648 double yp = r*sin(u);
1649 double toesec = (_TOE.gpssec() - 14.0);
1650
1651 double sinom = 0;
1652 double cosom = 0;
1653 double sini = 0;
1654 double cosi = 0;
1655
1656 const double iMaxGEO = 10.0 / 180.0 * M_PI;
1657
1658 // MEO/IGSO satellite
1659 // ------------------
1660 if (_i0 > iMaxGEO) {
1661 double OM = _OMEGA0 + (_OMEGADOT - omegaBDS)*tk - omegaBDS*toesec;
1662
1663 sinom = sin(OM);
1664 cosom = cos(OM);
1665 sini = sin(i);
1666 cosi = cos(i);
1667
1668 xc[0] = xp*cosom - yp*cosi*sinom;
1669 xc[1] = xp*sinom + yp*cosi*cosom;
1670 xc[2] = yp*sini;
1671 }
1672
1673 // GEO satellite
1674 // -------------
1675 else {
1676 double OM = _OMEGA0 + _OMEGADOT*tk - omegaBDS*toesec;
1677 double ll = omegaBDS*tk;
1678
1679 sinom = sin(OM);
1680 cosom = cos(OM);
1681 sini = sin(i);
1682 cosi = cos(i);
1683
1684 double xx = xp*cosom - yp*cosi*sinom;
1685 double yy = xp*sinom + yp*cosi*cosom;
1686 double zz = yp*sini;
1687
1688 Matrix R1 = BNC_PPP::t_astro::rotX(-5.0 / 180.0 * M_PI);
1689 Matrix R2 = BNC_PPP::t_astro::rotZ(ll);
1690
1691 ColumnVector X1(3); X1 << xx << yy << zz;
1692 ColumnVector X2 = R2*R1*X1;
1693
1694 xc[0] = X2(1);
1695 xc[1] = X2(2);
1696 xc[2] = X2(3);
1697 }
1698
1699 double tc = tt - _TOC;
1700 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc
1701 - 4.442807633e-10 * _e * sqrt(a0) *sin(E);
1702
1703 // Velocity
1704 // --------
1705 double tanv2 = tan(v/2);
1706 double dEdM = 1 / (1 - _e*cos(E));
1707 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2)
1708 / (1 + tanv2*tanv2) * dEdM * n;
1709 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
1710 double dotom = _OMEGADOT - t_CST::omega;
1711 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
1712 double dotr = a0 * _e*sin(E) * dEdM * n
1713 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
1714 double dotx = dotr*cos(u) - r*sin(u)*dotu;
1715 double doty = dotr*sin(u) + r*cos(u)*dotu;
1716
1717 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
1718 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
1719 + yp*sini*sinom*doti; // dX / di
1720
1721 vv[1] = sinom *dotx + cosi*cosom *doty
1722 + xp*cosom*dotom - yp*cosi*sinom*dotom
1723 - yp*sini*cosom*doti;
1724
1725 vv[2] = sini *doty + yp*cosi *doti;
1726
1727 // dotC = _clock_drift + _clock_driftrate*tc
1728 // - 4.442807633e-10*_e*sqrt(a0)*cos(E) * dEdM * n;
1729
1730 return success;
1731}
1732
1733// RINEX Format String
1734//////////////////////////////////////////////////////////////////////////////
1735QString t_ephBDS::toString(double version) const {
1736
1737 QString rnxStr = rinexDateStr(_TOC_bdt, _prn, version);
1738
1739 QTextStream out(&rnxStr);
1740
1741 out << QString("%1%2%3\n")
1742 .arg(_clock_bias, 19, 'e', 12)
1743 .arg(_clock_drift, 19, 'e', 12)
1744 .arg(_clock_driftrate, 19, 'e', 12);
1745
1746 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1747
1748 out << QString(fmt)
1749 .arg(double(_AODE), 19, 'e', 12)
1750 .arg(_Crs, 19, 'e', 12)
1751 .arg(_Delta_n, 19, 'e', 12)
1752 .arg(_M0, 19, 'e', 12);
1753
1754 out << QString(fmt)
1755 .arg(_Cuc, 19, 'e', 12)
1756 .arg(_e, 19, 'e', 12)
1757 .arg(_Cus, 19, 'e', 12)
1758 .arg(_sqrt_A, 19, 'e', 12);
1759
1760 double toes = _TOEs;
1761 if (!toes) { // RTCM stream input
1762 toes = _TOE_bdt.gpssec();
1763 }
1764 out << QString(fmt)
1765 .arg(toes, 19, 'e', 12)
1766 .arg(_Cic, 19, 'e', 12)
1767 .arg(_OMEGA0, 19, 'e', 12)
1768 .arg(_Cis, 19, 'e', 12);
1769
1770 out << QString(fmt)
1771 .arg(_i0, 19, 'e', 12)
1772 .arg(_Crc, 19, 'e', 12)
1773 .arg(_omega, 19, 'e', 12)
1774 .arg(_OMEGADOT, 19, 'e', 12);
1775
1776 out << QString(fmt)
1777 .arg(_IDOT, 19, 'e', 12)
1778 .arg(0.0, 19, 'e', 12)
1779 .arg(double(_TOE_bdt.gpsw() - 1356.0), 19, 'e', 12)
1780 .arg(0.0, 19, 'e', 12);
1781
1782 out << QString(fmt)
1783 .arg(_URA, 19, 'e', 12)
1784 .arg(double(_SatH1), 19, 'e', 12)
1785 .arg(_TGD1, 19, 'e', 12)
1786 .arg(_TGD2, 19, 'e', 12);
1787
1788 double tots = _TOTs;
1789 if (!tots) { // RTCM stream input
1790 tots = _TOE_bdt.gpssec();
1791 }
1792 out << QString(fmt)
1793 .arg(tots, 19, 'e', 12)
1794 .arg(double(_AODC), 19, 'e', 12)
1795 .arg("", 19, QChar(' '))
1796 .arg("", 19, QChar(' '));
1797 return rnxStr;
1798}
1799
Note: See TracBrowser for help on using the repository browser.