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

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

considerationn of the aspect that Galileo navigation messages can be provided for the same epoch but with different flags, e.g.: I/NAV, F/NAV, changed DVS;
simplification for accuracy entries that can be provided as index or in meter

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