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

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

separate consideration of ssr update interval

File size: 44.8 KB
RevLine 
[1025]1#include <math.h>
2#include <sstream>
[2234]3#include <iostream>
[1025]4#include <iomanip>
[1239]5#include <cstring>
[1025]6
[2234]7#include <newmatio.h>
8
[1025]9#include "ephemeris.h"
[2221]10#include "bncutils.h"
[2285]11#include "bnctime.h"
[5070]12#include "bnccore.h"
[5839]13#include "bncutils.h"
[6141]14#include "satObs.h"
[6044]15#include "pppInclude.h"
[6400]16#include "pppModel.h"
[1025]17
18using namespace std;
19
[5749]20// Constructor
21////////////////////////////////////////////////////////////////////////////
22t_eph::t_eph() {
[6518]23 _checkState = unchecked;
24 _orbCorr = 0;
25 _clkCorr = 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();
449 //// _TOEsec = ee->TOE; //// TODO:
[2771]450 _Cic = ee->Cic;
451 _OMEGA0 = ee->OMEGA0;
452 _Cis = ee->Cis;
[4018]453
[2771]454 _i0 = ee->i0;
455 _Crc = ee->Crc;
456 _omega = ee->omega;
457 _OMEGADOT = ee->OMEGADOT;
[4018]458
[2771]459 _IDOT = ee->IDOT;
[4018]460 _TOEweek = ee->Week;
461
[3734]462 _SISA = ee->SISA;
[4018]463 _E5aHS = ee->E5aHS;
[5541]464 _E5bHS = ee->E5bHS;
[3734]465 _BGD_1_5A = ee->BGD_1_5A;
466 _BGD_1_5B = ee->BGD_1_5B;
[3659]467
[4018]468 _TOT = 0.9999e9;
469
[5539]470 _flags = ee->flags;
[2771]471}
472
473// Compute Galileo Satellite Position (virtual)
474////////////////////////////////////////////////////////////////////////////
[6213]475t_irc t_ephGal::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
[2771]476
[6518]477 if (_checkState == bad) {
478 return failure;
479 }
480
[2771]481 static const double omegaEarth = 7292115.1467e-11;
[5277]482 static const double gmWGS = 398.60044e12;
[2771]483
484 memset(xc, 0, 4*sizeof(double));
485 memset(vv, 0, 3*sizeof(double));
486
487 double a0 = _sqrt_A * _sqrt_A;
488 if (a0 == 0) {
[6213]489 return failure;
[2771]490 }
491
492 double n0 = sqrt(gmWGS/(a0*a0*a0));
[4018]493
494 bncTime tt(GPSweek, GPSweeks);
495 double tk = tt - bncTime(_TOC.gpsw(), _TOEsec);
496
[2771]497 double n = n0 + _Delta_n;
498 double M = _M0 + n*tk;
499 double E = M;
500 double E_last;
501 do {
502 E_last = E;
503 E = M + _e*sin(E);
504 } while ( fabs(E-E_last)*a0 > 0.001 );
505 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
506 double u0 = v + _omega;
507 double sin2u0 = sin(2*u0);
508 double cos2u0 = cos(2*u0);
509 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
510 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
511 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
512 double xp = r*cos(u);
513 double yp = r*sin(u);
514 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
[4018]515 omegaEarth*_TOEsec;
[2771]516
517 double sinom = sin(OM);
518 double cosom = cos(OM);
519 double sini = sin(i);
520 double cosi = cos(i);
521 xc[0] = xp*cosom - yp*cosi*sinom;
522 xc[1] = xp*sinom + yp*cosi*cosom;
523 xc[2] = yp*sini;
524
[4018]525 double tc = tt - _TOC;
[2771]526 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
527
528 // Velocity
529 // --------
530 double tanv2 = tan(v/2);
531 double dEdM = 1 / (1 - _e*cos(E));
532 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
533 * dEdM * n;
534 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
535 double dotom = _OMEGADOT - omegaEarth;
536 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
537 double dotr = a0 * _e*sin(E) * dEdM * n
538 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
539 double dotx = dotr*cos(u) - r*sin(u)*dotu;
540 double doty = dotr*sin(u) + r*cos(u)*dotu;
541
542 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
543 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
544 + yp*sini*sinom*doti; // dX / di
545
546 vv[1] = sinom *dotx + cosi*cosom *doty
547 + xp*cosom*dotom - yp*cosi*sinom*dotom
548 - yp*sini*cosom*doti;
549
550 vv[2] = sini *doty + yp*cosi *doti;
551
552 // Relativistic Correction
553 // -----------------------
554 // xc(4) -= 4.442807633e-10 * _e * sqrt(a0) *sin(E);
555 xc[3] -= 2.0 * (xc[0]*vv[0] + xc[1]*vv[1] + xc[2]*vv[2]) / t_CST::c / t_CST::c;
[6213]556
557 return success;
[2771]558}
559
[3659]560// Constructor
561//////////////////////////////////////////////////////////////////////////////
562t_ephGPS::t_ephGPS(float rnxVersion, const QStringList& lines) {
[3664]563
[3699]564 const int nLines = 8;
565
566 if (lines.size() != nLines) {
[6518]567 _checkState = bad;
[3660]568 return;
569 }
[3664]570
[3668]571 // RINEX Format
572 // ------------
573 int fieldLen = 19;
574
[3666]575 int pos[4];
576 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
[3668]577 pos[1] = pos[0] + fieldLen;
578 pos[2] = pos[1] + fieldLen;
579 pos[3] = pos[2] + fieldLen;
[3664]580
581 // Read eight lines
582 // ----------------
[3699]583 for (int iLine = 0; iLine < nLines; iLine++) {
[3664]584 QString line = lines[iLine];
585
586 if ( iLine == 0 ) {
[3666]587 QTextStream in(line.left(pos[1]).toAscii());
588
589 int year, month, day, hour, min;
590 double sec;
591
[5776]592 QString prnStr;
593 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
[6377]594 if (prnStr.at(0) == 'G') {
[5776]595 _prn.set('G', prnStr.mid(1).toInt());
596 }
[6377]597 else if (prnStr.at(0) == 'J') {
598 _prn.set('J', prnStr.mid(1).toInt());
599 }
[5776]600 else {
601 _prn.set('G', prnStr.toInt());
602 }
[3666]603
604 if (year < 80) {
605 year += 2000;
[3664]606 }
[3666]607 else if (year < 100) {
608 year += 1900;
609 }
610
[4018]611 _TOC.set(year, month, day, hour, min, sec);
[3666]612
613 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
614 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
615 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
[6518]616 _checkState = bad;
[3666]617 return;
618 }
[3660]619 }
[3664]620
621 else if ( iLine == 1 ) {
[3666]622 if ( readDbl(line, pos[0], fieldLen, _IODE ) ||
623 readDbl(line, pos[1], fieldLen, _Crs ) ||
624 readDbl(line, pos[2], fieldLen, _Delta_n) ||
625 readDbl(line, pos[3], fieldLen, _M0 ) ) {
[6518]626 _checkState = bad;
[3664]627 return;
628 }
629 }
630
631 else if ( iLine == 2 ) {
[3666]632 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
633 readDbl(line, pos[1], fieldLen, _e ) ||
634 readDbl(line, pos[2], fieldLen, _Cus ) ||
635 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
[6518]636 _checkState = bad;
[3664]637 return;
638 }
639 }
640
641 else if ( iLine == 3 ) {
[4018]642 if ( readDbl(line, pos[0], fieldLen, _TOEsec) ||
[3666]643 readDbl(line, pos[1], fieldLen, _Cic ) ||
644 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
645 readDbl(line, pos[3], fieldLen, _Cis ) ) {
[6518]646 _checkState = bad;
[3664]647 return;
648 }
649 }
650
651 else if ( iLine == 4 ) {
[3666]652 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
653 readDbl(line, pos[1], fieldLen, _Crc ) ||
654 readDbl(line, pos[2], fieldLen, _omega ) ||
655 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
[6518]656 _checkState = bad;
[3664]657 return;
658 }
659 }
660
661 else if ( iLine == 5 ) {
[4018]662 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
663 readDbl(line, pos[1], fieldLen, _L2Codes) ||
664 readDbl(line, pos[2], fieldLen, _TOEweek ) ||
665 readDbl(line, pos[3], fieldLen, _L2PFlag) ) {
[6518]666 _checkState = bad;
[3664]667 return;
668 }
669 }
670
671 else if ( iLine == 6 ) {
[4018]672 if ( readDbl(line, pos[0], fieldLen, _ura ) ||
[3666]673 readDbl(line, pos[1], fieldLen, _health) ||
674 readDbl(line, pos[2], fieldLen, _TGD ) ||
675 readDbl(line, pos[3], fieldLen, _IODC ) ) {
[6518]676 _checkState = bad;
[3664]677 return;
678 }
679 }
680
681 else if ( iLine == 7 ) {
[4224]682 if ( readDbl(line, pos[0], fieldLen, _TOT) ) {
[6518]683 _checkState = bad;
[3664]684 return;
685 }
[4224]686 readDbl(line, pos[1], fieldLen, _fitInterval); // _fitInterval optional
[3664]687 }
[3660]688 }
[3659]689}
690
691// Constructor
692//////////////////////////////////////////////////////////////////////////////
693t_ephGlo::t_ephGlo(float rnxVersion, const QStringList& lines) {
694
[3699]695 const int nLines = 4;
696
697 if (lines.size() != nLines) {
[6518]698 _checkState = bad;
[3699]699 return;
700 }
701
702 // RINEX Format
703 // ------------
704 int fieldLen = 19;
705
706 int pos[4];
707 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
708 pos[1] = pos[0] + fieldLen;
709 pos[2] = pos[1] + fieldLen;
710 pos[3] = pos[2] + fieldLen;
711
712 // Read four lines
713 // ---------------
714 for (int iLine = 0; iLine < nLines; iLine++) {
715 QString line = lines[iLine];
716
717 if ( iLine == 0 ) {
718 QTextStream in(line.left(pos[1]).toAscii());
719
720 int year, month, day, hour, min;
721 double sec;
722
[5776]723 QString prnStr;
724 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
725 if (prnStr.at(0) == 'R') {
726 _prn.set('R', prnStr.mid(1).toInt());
727 }
728 else {
729 _prn.set('R', prnStr.toInt());
730 }
[3699]731
732 if (year < 80) {
733 year += 2000;
734 }
735 else if (year < 100) {
736 year += 1900;
737 }
738
[3760]739 _gps_utc = gnumleap(year, month, day);
740
[4018]741 _TOC.set(year, month, day, hour, min, sec);
742 _TOC = _TOC + _gps_utc;
[3699]743
[4018]744 if ( readDbl(line, pos[1], fieldLen, _tau ) ||
745 readDbl(line, pos[2], fieldLen, _gamma) ||
746 readDbl(line, pos[3], fieldLen, _tki ) ) {
[6518]747 _checkState = bad;
[3699]748 return;
749 }
[3765]750
751 _tau = -_tau;
[3699]752 }
753
754 else if ( iLine == 1 ) {
755 if ( readDbl(line, pos[0], fieldLen, _x_pos ) ||
756 readDbl(line, pos[1], fieldLen, _x_velocity ) ||
757 readDbl(line, pos[2], fieldLen, _x_acceleration) ||
758 readDbl(line, pos[3], fieldLen, _health ) ) {
[6518]759 _checkState = bad;
[3699]760 return;
761 }
762 }
763
764 else if ( iLine == 2 ) {
765 if ( readDbl(line, pos[0], fieldLen, _y_pos ) ||
766 readDbl(line, pos[1], fieldLen, _y_velocity ) ||
767 readDbl(line, pos[2], fieldLen, _y_acceleration ) ||
768 readDbl(line, pos[3], fieldLen, _frequency_number) ) {
[6518]769 _checkState = bad;
[3699]770 return;
771 }
772 }
773
774 else if ( iLine == 3 ) {
775 if ( readDbl(line, pos[0], fieldLen, _z_pos ) ||
776 readDbl(line, pos[1], fieldLen, _z_velocity ) ||
777 readDbl(line, pos[2], fieldLen, _z_acceleration) ||
778 readDbl(line, pos[3], fieldLen, _E ) ) {
[6518]779 _checkState = bad;
[3699]780 return;
781 }
782 }
783 }
784
785 // Initialize status vector
786 // ------------------------
[4018]787 _tt = _TOC;
788 _xv.ReSize(6);
[3699]789 _xv(1) = _x_pos * 1.e3;
790 _xv(2) = _y_pos * 1.e3;
791 _xv(3) = _z_pos * 1.e3;
792 _xv(4) = _x_velocity * 1.e3;
793 _xv(5) = _y_velocity * 1.e3;
794 _xv(6) = _z_velocity * 1.e3;
[3659]795}
796
797// Constructor
798//////////////////////////////////////////////////////////////////////////////
[4891]799t_ephGal::t_ephGal(float rnxVersion, const QStringList& lines) {
[3659]800
[4891]801 const int nLines = 8;
802
803 if (lines.size() != nLines) {
[6518]804 _checkState = bad;
[4891]805 return;
806 }
807
808 // RINEX Format
809 // ------------
810 int fieldLen = 19;
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
[5776]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 }
[4891]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) ) {
[6518]850 _checkState = bad;
[4891]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 ) ) {
[6518]860 _checkState = bad;
[4891]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) ) {
[6518]870 _checkState = bad;
[4891]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 ) ) {
[6518]880 _checkState = bad;
[4891]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) ) {
[6518]890 _checkState = bad;
[4891]891 return;
892 }
893 }
894
895 else if ( iLine == 5 ) {
896 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
897 readDbl(line, pos[2], fieldLen, _TOEweek) ) {
[6518]898 _checkState = bad;
[4891]899 return;
900 }
901 }
902
903 else if ( iLine == 6 ) {
904 if ( readDbl(line, pos[0], fieldLen, _SISA ) ||
905 readDbl(line, pos[1], fieldLen, _E5aHS ) ||
906 readDbl(line, pos[2], fieldLen, _BGD_1_5A) ||
907 readDbl(line, pos[3], fieldLen, _BGD_1_5B) ) {
[6518]908 _checkState = bad;
[4891]909 return;
910 }
911 }
912
913 else if ( iLine == 7 ) {
914 if ( readDbl(line, pos[0], fieldLen, _TOT) ) {
[6518]915 _checkState = bad;
[4891]916 return;
917 }
918 }
919 }
[3659]920}
[4013]921
[4021]922//
[4013]923//////////////////////////////////////////////////////////////////////////////
[5776]924QString t_eph::rinexDateStr(const bncTime& tt, const t_prn& prn, double version) {
925 QString prnStr(prn.toString().c_str());
926 return rinexDateStr(tt, prnStr, version);
927}
[4013]928
[5776]929//
930//////////////////////////////////////////////////////////////////////////////
931QString t_eph::rinexDateStr(const bncTime& tt, const QString& prnStr, double version) {
932
[4021]933 QString datStr;
[4013]934
935 unsigned year, month, day, hour, min;
[4018]936 double sec;
[4029]937 tt.civil_date(year, month, day);
938 tt.civil_time(hour, min, sec);
[4013]939
[4021]940 QTextStream out(&datStr);
[4013]941
942 if (version < 3.0) {
[5776]943 QString prnHlp = prnStr.mid(1,2); if (prnHlp[0] == '0') prnHlp[0] = ' ';
[4017]944 out << prnHlp << QString(" %1 %2 %3 %4 %5%6")
[4013]945 .arg(year % 100, 2, 10, QChar('0'))
946 .arg(month, 2)
947 .arg(day, 2)
948 .arg(hour, 2)
949 .arg(min, 2)
[4016]950 .arg(sec, 5, 'f',1);
[4013]951 }
952 else {
[5776]953 out << prnStr << QString(" %1 %2 %3 %4 %5 %6")
[4013]954 .arg(year, 4)
955 .arg(month, 2, 10, QChar('0'))
956 .arg(day, 2, 10, QChar('0'))
957 .arg(hour, 2, 10, QChar('0'))
958 .arg(min, 2, 10, QChar('0'))
959 .arg(int(sec), 2, 10, QChar('0'));
960 }
[4021]961
962 return datStr;
963}
964
965// RINEX Format String
966//////////////////////////////////////////////////////////////////////////////
967QString t_ephGPS::toString(double version) const {
968
[4029]969 QString rnxStr = rinexDateStr(_TOC, _prn, version);
[4013]970
[4021]971 QTextStream out(&rnxStr);
972
[4013]973 out << QString("%1%2%3\n")
974 .arg(_clock_bias, 19, 'e', 12)
975 .arg(_clock_drift, 19, 'e', 12)
976 .arg(_clock_driftrate, 19, 'e', 12);
977
[4015]978 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
979
980 out << QString(fmt)
[4013]981 .arg(_IODE, 19, 'e', 12)
982 .arg(_Crs, 19, 'e', 12)
983 .arg(_Delta_n, 19, 'e', 12)
984 .arg(_M0, 19, 'e', 12);
985
[4015]986 out << QString(fmt)
[4013]987 .arg(_Cuc, 19, 'e', 12)
988 .arg(_e, 19, 'e', 12)
989 .arg(_Cus, 19, 'e', 12)
990 .arg(_sqrt_A, 19, 'e', 12);
991
[4015]992 out << QString(fmt)
[4018]993 .arg(_TOEsec, 19, 'e', 12)
[4013]994 .arg(_Cic, 19, 'e', 12)
995 .arg(_OMEGA0, 19, 'e', 12)
996 .arg(_Cis, 19, 'e', 12);
997
[4015]998 out << QString(fmt)
[4013]999 .arg(_i0, 19, 'e', 12)
1000 .arg(_Crc, 19, 'e', 12)
1001 .arg(_omega, 19, 'e', 12)
1002 .arg(_OMEGADOT, 19, 'e', 12);
1003
[4015]1004 out << QString(fmt)
[4018]1005 .arg(_IDOT, 19, 'e', 12)
1006 .arg(_L2Codes, 19, 'e', 12)
1007 .arg(_TOEweek, 19, 'e', 12)
1008 .arg(_L2PFlag, 19, 'e', 12);
[4013]1009
[4015]1010 out << QString(fmt)
[4018]1011 .arg(_ura, 19, 'e', 12)
[4013]1012 .arg(_health, 19, 'e', 12)
1013 .arg(_TGD, 19, 'e', 12)
1014 .arg(_IODC, 19, 'e', 12);
1015
[4015]1016 out << QString(fmt)
[4018]1017 .arg(_TOT, 19, 'e', 12)
1018 .arg(_fitInterval, 19, 'e', 12)
[4024]1019 .arg("", 19, QChar(' '))
1020 .arg("", 19, QChar(' '));
[4013]1021
1022 return rnxStr;
1023}
[4023]1024
1025// RINEX Format String
1026//////////////////////////////////////////////////////////////////////////////
1027QString t_ephGlo::toString(double version) const {
1028
[4029]1029 QString rnxStr = rinexDateStr(_TOC-_gps_utc, _prn, version);
[4023]1030
1031 QTextStream out(&rnxStr);
1032
1033 out << QString("%1%2%3\n")
1034 .arg(-_tau, 19, 'e', 12)
1035 .arg(_gamma, 19, 'e', 12)
1036 .arg(_tki, 19, 'e', 12);
1037
1038 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1039
1040 out << QString(fmt)
1041 .arg(_x_pos, 19, 'e', 12)
1042 .arg(_x_velocity, 19, 'e', 12)
1043 .arg(_x_acceleration, 19, 'e', 12)
1044 .arg(_health, 19, 'e', 12);
1045
1046 out << QString(fmt)
1047 .arg(_y_pos, 19, 'e', 12)
1048 .arg(_y_velocity, 19, 'e', 12)
1049 .arg(_y_acceleration, 19, 'e', 12)
1050 .arg(_frequency_number, 19, 'e', 12);
1051
1052 out << QString(fmt)
1053 .arg(_z_pos, 19, 'e', 12)
1054 .arg(_z_velocity, 19, 'e', 12)
1055 .arg(_z_acceleration, 19, 'e', 12)
1056 .arg(_E, 19, 'e', 12);
1057
1058 return rnxStr;
1059}
1060
1061// RINEX Format String
1062//////////////////////////////////////////////////////////////////////////////
1063QString t_ephGal::toString(double version) const {
1064
[4029]1065 QString rnxStr = rinexDateStr(_TOC, _prn, version);
[4023]1066
1067 QTextStream out(&rnxStr);
1068
1069 out << QString("%1%2%3\n")
1070 .arg(_clock_bias, 19, 'e', 12)
1071 .arg(_clock_drift, 19, 'e', 12)
1072 .arg(_clock_driftrate, 19, 'e', 12);
1073
1074 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1075
1076 out << QString(fmt)
1077 .arg(_IODnav, 19, 'e', 12)
1078 .arg(_Crs, 19, 'e', 12)
1079 .arg(_Delta_n, 19, 'e', 12)
1080 .arg(_M0, 19, 'e', 12);
1081
1082 out << QString(fmt)
1083 .arg(_Cuc, 19, 'e', 12)
1084 .arg(_e, 19, 'e', 12)
1085 .arg(_Cus, 19, 'e', 12)
1086 .arg(_sqrt_A, 19, 'e', 12);
1087
1088 out << QString(fmt)
1089 .arg(_TOEsec, 19, 'e', 12)
1090 .arg(_Cic, 19, 'e', 12)
1091 .arg(_OMEGA0, 19, 'e', 12)
1092 .arg(_Cis, 19, 'e', 12);
1093
1094 out << QString(fmt)
1095 .arg(_i0, 19, 'e', 12)
1096 .arg(_Crc, 19, 'e', 12)
1097 .arg(_omega, 19, 'e', 12)
1098 .arg(_OMEGADOT, 19, 'e', 12);
1099
[5532]1100 int dataSource = 0;
[5542]1101 double HS = 0.0;
[5539]1102 if ( (_flags & GALEPHF_INAV) == GALEPHF_INAV ) {
1103 dataSource |= (1<<0);
[5540]1104 dataSource |= (1<<9);
[5542]1105 HS = _E5bHS;
[5539]1106 }
1107 else if ( (_flags & GALEPHF_FNAV) == GALEPHF_FNAV ) {
1108 dataSource |= (1<<1);
[5540]1109 dataSource |= (1<<8);
[5542]1110 HS = _E5aHS;
[5539]1111 }
[4023]1112 out << QString(fmt)
[5532]1113 .arg(_IDOT, 19, 'e', 12)
1114 .arg(double(dataSource), 19, 'e', 12)
1115 .arg(_TOEweek, 19, 'e', 12)
1116 .arg(0.0, 19, 'e', 12);
[4023]1117
1118 out << QString(fmt)
1119 .arg(_SISA, 19, 'e', 12)
[5542]1120 .arg(HS, 19, 'e', 12)
[4023]1121 .arg(_BGD_1_5A, 19, 'e', 12)
1122 .arg(_BGD_1_5B, 19, 'e', 12);
1123
1124 out << QString(fmt)
1125 .arg(_TOT, 19, 'e', 12)
[4024]1126 .arg("", 19, QChar(' '))
1127 .arg("", 19, QChar(' '))
1128 .arg("", 19, QChar(' '));
[4023]1129
1130 return rnxStr;
1131}
1132
[6385]1133// Constructor
1134//////////////////////////////////////////////////////////////////////////////
[6390]1135t_ephSBAS::t_ephSBAS(float rnxVersion, const QStringList& lines) {
1136
1137 const int nLines = 4;
1138
1139 if (lines.size() != nLines) {
[6518]1140 _checkState = bad;
[6390]1141 return;
1142 }
1143
1144 // RINEX Format
1145 // ------------
1146 int fieldLen = 19;
1147
1148 int pos[4];
1149 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
1150 pos[1] = pos[0] + fieldLen;
1151 pos[2] = pos[1] + fieldLen;
1152 pos[3] = pos[2] + fieldLen;
1153
1154 // Read four lines
1155 // ---------------
1156 for (int iLine = 0; iLine < nLines; iLine++) {
1157 QString line = lines[iLine];
1158
1159 if ( iLine == 0 ) {
1160 QTextStream in(line.left(pos[1]).toAscii());
1161
1162 int year, month, day, hour, min;
1163 double sec;
1164
1165 QString prnStr;
1166 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
1167 if (prnStr.at(0) == 'S') {
1168 _prn.set('S', prnStr.mid(1).toInt());
1169 }
1170 else {
1171 _prn.set('S', prnStr.toInt());
1172 }
1173
1174 if (year < 80) {
1175 year += 2000;
1176 }
1177 else if (year < 100) {
1178 year += 1900;
1179 }
1180
1181 _TOC.set(year, month, day, hour, min, sec);
1182
1183 if ( readDbl(line, pos[1], fieldLen, _agf0 ) ||
1184 readDbl(line, pos[2], fieldLen, _agf1 ) ||
1185 readDbl(line, pos[3], fieldLen, _TOW ) ) {
[6518]1186 _checkState = bad;
[6390]1187 return;
1188 }
1189 }
1190
1191 else if ( iLine == 1 ) {
1192 if ( readDbl(line, pos[0], fieldLen, _x_pos ) ||
1193 readDbl(line, pos[1], fieldLen, _x_velocity ) ||
1194 readDbl(line, pos[2], fieldLen, _x_acceleration) ||
1195 readDbl(line, pos[3], fieldLen, _health ) ) {
[6518]1196 _checkState = bad;
[6390]1197 return;
1198 }
1199 }
1200
1201 else if ( iLine == 2 ) {
1202 if ( readDbl(line, pos[0], fieldLen, _y_pos ) ||
1203 readDbl(line, pos[1], fieldLen, _y_velocity ) ||
1204 readDbl(line, pos[2], fieldLen, _y_acceleration ) ||
1205 readDbl(line, pos[3], fieldLen, _ura ) ) {
[6518]1206 _checkState = bad;
[6390]1207 return;
1208 }
1209 }
1210
1211 else if ( iLine == 3 ) {
[6536]1212 double iodn;
[6390]1213 if ( readDbl(line, pos[0], fieldLen, _z_pos ) ||
1214 readDbl(line, pos[1], fieldLen, _z_velocity ) ||
1215 readDbl(line, pos[2], fieldLen, _z_acceleration) ||
[6536]1216 readDbl(line, pos[3], fieldLen, iodn ) ) {
[6518]1217 _checkState = bad;
[6390]1218 return;
[6536]1219 _IODN = int(iodn);
[6390]1220 }
1221 }
1222 }
1223
1224 _x_pos *= 1.e3;
1225 _y_pos *= 1.e3;
1226 _z_pos *= 1.e3;
1227 _x_velocity *= 1.e3;
1228 _y_velocity *= 1.e3;
1229 _z_velocity *= 1.e3;
1230 _x_acceleration *= 1.e3;
1231 _y_acceleration *= 1.e3;
1232 _z_acceleration *= 1.e3;
[6385]1233}
1234
1235// Set SBAS Satellite Position
1236////////////////////////////////////////////////////////////////////////////
1237void t_ephSBAS::set(const sbasephemeris* ee) {
[6386]1238
[6389]1239 _prn.set('S', ee->satellite - PRN_SBAS_START + 20);
[6386]1240 _TOC.set(ee->GPSweek_TOE, double(ee->TOE));
1241
1242 _IODN = ee->IODN;
1243 _TOW = ee->TOW;
1244
1245 _agf0 = ee->agf0;
1246 _agf1 = ee->agf1;
1247
[6389]1248 _x_pos = ee->x_pos;
1249 _x_velocity = ee->x_velocity;
1250 _x_acceleration = ee->x_acceleration;
[6386]1251
[6389]1252 _y_pos = ee->y_pos;
1253 _y_velocity = ee->y_velocity;
1254 _y_acceleration = ee->y_acceleration;
[6386]1255
[6389]1256 _z_pos = ee->z_pos;
1257 _z_velocity = ee->z_velocity;
1258 _z_acceleration = ee->z_acceleration;
[6386]1259
1260 _ura = ee->URA;
[6390]1261
1262 _health = 0;
[6385]1263}
1264
1265// Compute SBAS Satellite Position (virtual)
1266////////////////////////////////////////////////////////////////////////////
1267t_irc t_ephSBAS::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
[6386]1268
[6518]1269 if (_checkState == bad) {
1270 return failure;
1271 }
1272
[6386]1273 bncTime tt(GPSweek, GPSweeks);
1274 double dt = tt - _TOC;
1275
1276 xc[0] = _x_pos + _x_velocity * dt + _x_acceleration * dt * dt / 2.0;
1277 xc[1] = _y_pos + _y_velocity * dt + _y_acceleration * dt * dt / 2.0;
1278 xc[2] = _z_pos + _z_velocity * dt + _z_acceleration * dt * dt / 2.0;
1279
1280 vv[0] = _x_velocity + _x_acceleration * dt;
1281 vv[1] = _y_velocity + _y_acceleration * dt;
1282 vv[2] = _z_velocity + _z_acceleration * dt;
1283
1284 xc[3] = _agf0 + _agf1 * dt;
1285
1286 return success;
[6385]1287}
1288
1289// RINEX Format String
1290//////////////////////////////////////////////////////////////////////////////
[6388]1291QString t_ephSBAS::toString(double version) const {
1292
1293 QString rnxStr = rinexDateStr(_TOC, _prn, version);
1294
1295 QTextStream out(&rnxStr);
1296
1297 out << QString("%1%2%3\n")
[6390]1298 .arg(_agf0, 19, 'e', 12)
1299 .arg(_agf1, 19, 'e', 12)
1300 .arg(_TOW, 19, 'e', 12);
[6388]1301
1302 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1303
1304 out << QString(fmt)
1305 .arg(1.e-3*_x_pos, 19, 'e', 12)
1306 .arg(1.e-3*_x_velocity, 19, 'e', 12)
1307 .arg(1.e-3*_x_acceleration, 19, 'e', 12)
[6390]1308 .arg(_health, 19, 'e', 12);
[6388]1309
1310 out << QString(fmt)
1311 .arg(1.e-3*_y_pos, 19, 'e', 12)
1312 .arg(1.e-3*_y_velocity, 19, 'e', 12)
1313 .arg(1.e-3*_y_acceleration, 19, 'e', 12)
[6390]1314 .arg(_ura, 19, 'e', 12);
[6388]1315
1316 out << QString(fmt)
1317 .arg(1.e-3*_z_pos, 19, 'e', 12)
1318 .arg(1.e-3*_z_velocity, 19, 'e', 12)
1319 .arg(1.e-3*_z_acceleration, 19, 'e', 12)
[6536]1320 .arg(double(_IODN), 19, 'e', 12);
[6388]1321
1322 return rnxStr;
[6385]1323}
[6400]1324
1325// Constructor
1326//////////////////////////////////////////////////////////////////////////////
1327t_ephCompass::t_ephCompass(float rnxVersion, const QStringList& lines) {
1328
1329 const int nLines = 8;
1330
1331 if (lines.size() != nLines) {
[6518]1332 _checkState = bad;
[6400]1333 return;
1334 }
1335
1336 // RINEX Format
1337 // ------------
1338 int fieldLen = 19;
1339
1340 int pos[4];
1341 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
1342 pos[1] = pos[0] + fieldLen;
1343 pos[2] = pos[1] + fieldLen;
1344 pos[3] = pos[2] + fieldLen;
1345
1346 double TOTs;
1347 double TOEs;
1348 double TOEw;
1349
1350 // Read eight lines
1351 // ----------------
1352 for (int iLine = 0; iLine < nLines; iLine++) {
1353 QString line = lines[iLine];
1354
1355 if ( iLine == 0 ) {
1356 QTextStream in(line.left(pos[1]).toAscii());
1357
1358 int year, month, day, hour, min;
1359 double sec;
1360
1361 QString prnStr;
1362 in >> prnStr >> year >> month >> day >> hour >> min >> sec;
1363 if (prnStr.at(0) == 'C') {
1364 _prn.set('C', prnStr.mid(1).toInt());
1365 }
1366 else {
1367 _prn.set('C', prnStr.toInt());
1368 }
1369
1370 if (year < 80) {
1371 year += 2000;
1372 }
1373 else if (year < 100) {
1374 year += 1900;
1375 }
1376
1377 _TOC_bdt.set(year, month, day, hour, min, sec);
1378
1379 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
1380 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
1381 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
[6518]1382 _checkState = bad;
[6400]1383 return;
1384 }
1385 }
1386
1387 else if ( iLine == 1 ) {
1388 double aode;
1389 if ( readDbl(line, pos[0], fieldLen, aode ) ||
1390 readDbl(line, pos[1], fieldLen, _Crs ) ||
1391 readDbl(line, pos[2], fieldLen, _Delta_n) ||
1392 readDbl(line, pos[3], fieldLen, _M0 ) ) {
[6518]1393 _checkState = bad;
[6400]1394 return;
1395 }
1396 _AODE = int(aode);
1397 }
1398
1399 else if ( iLine == 2 ) {
1400 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
1401 readDbl(line, pos[1], fieldLen, _e ) ||
1402 readDbl(line, pos[2], fieldLen, _Cus ) ||
1403 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
[6518]1404 _checkState = bad;
[6400]1405 return;
1406 }
1407 }
1408
1409 else if ( iLine == 3 ) {
1410 if ( readDbl(line, pos[0], fieldLen, TOEs ) ||
1411 readDbl(line, pos[1], fieldLen, _Cic ) ||
1412 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
1413 readDbl(line, pos[3], fieldLen, _Cis ) ) {
[6518]1414 _checkState = bad;
[6400]1415 return;
1416 }
1417 }
1418
1419 else if ( iLine == 4 ) {
1420 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
1421 readDbl(line, pos[1], fieldLen, _Crc ) ||
1422 readDbl(line, pos[2], fieldLen, _omega ) ||
1423 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
[6518]1424 _checkState = bad;
[6400]1425 return;
1426 }
1427 }
1428
1429 else if ( iLine == 5 ) {
1430 if ( readDbl(line, pos[0], fieldLen, _IDOT ) ||
1431 readDbl(line, pos[2], fieldLen, TOEw) ) {
[6518]1432 _checkState = bad;
[6400]1433 return;
1434 }
1435 }
1436
1437 else if ( iLine == 6 ) {
1438 double SatH1;
1439 if ( readDbl(line, pos[1], fieldLen, SatH1) ||
1440 readDbl(line, pos[2], fieldLen, _TGD1) ||
1441 readDbl(line, pos[3], fieldLen, _TGD2) ) {
[6518]1442 _checkState = bad;
[6400]1443 return;
1444 }
1445 _SatH1 = int(SatH1);
1446 }
1447
1448 else if ( iLine == 7 ) {
1449 double aodc;
1450 if ( readDbl(line, pos[0], fieldLen, TOTs) ||
1451 readDbl(line, pos[1], fieldLen, aodc) ) {
[6518]1452 _checkState = bad;
[6400]1453 return;
1454 }
1455 if (TOTs == 0.9999e9) { // 0.9999e9 means not known (RINEX standard)
1456 TOTs = TOEs;
1457 }
1458 _AODC = int(aodc);
1459 }
1460 }
1461
1462 TOEw += 1356; // BDT -> GPS week number
[6537]1463 _TOE_bdt.set(int(TOEw), TOEs);
[6400]1464
1465 // GPS->BDT
1466 // --------
1467 _TOC = _TOC_bdt + 14.0;
1468 _TOE = _TOE_bdt + 14.0;
1469
1470 // remark: actually should be computed from second_tot
1471 // but it seems to be unreliable in RINEX files
1472 _TOT = _TOC;
1473}
1474
1475// Constructor
1476//////////////////////////////////////////////////////////////////////////////
1477t_irc t_ephCompass::position(int GPSweek, double GPSweeks, double* xc, double* vv) const {
1478
[6518]1479 if (_checkState == bad) {
1480 return failure;
1481 }
1482
[6400]1483 static const double gmCompass = 398.6004418e12;
1484 static const double omegaCompass = 7292115.0000e-11;
1485
1486 xc[0] = xc[1] = xc[2] = xc[3] = 0.0;
1487 vv[0] = vv[1] = vv[2] = 0.0;
1488
1489 bncTime tt(GPSweek, GPSweeks);
1490
1491 if (_sqrt_A == 0) {
1492 return failure;
1493 }
1494 double a0 = _sqrt_A * _sqrt_A;
1495
1496 double n0 = sqrt(gmCompass/(a0*a0*a0));
1497 double tk = tt - _TOE;
1498 double n = n0 + _Delta_n;
1499 double M = _M0 + n*tk;
1500 double E = M;
1501 double E_last;
1502 int nLoop = 0;
1503 do {
1504 E_last = E;
1505 E = M + _e*sin(E);
1506
1507 if (++nLoop == 100) {
1508 return failure;
1509 }
1510 } while ( fabs(E-E_last)*a0 > 0.001 );
1511
1512 double v = atan2(sqrt(1-_e*_e) * sin(E), cos(E) - _e);
1513 double u0 = v + _omega;
1514 double sin2u0 = sin(2*u0);
1515 double cos2u0 = cos(2*u0);
1516 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
1517 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
1518 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
1519 double xp = r*cos(u);
1520 double yp = r*sin(u);
1521 double toesec = (_TOE.gpssec() - 14.0);
1522
1523 double sinom = 0;
1524 double cosom = 0;
1525 double sini = 0;
1526 double cosi = 0;
1527
1528 const double iMaxGEO = 10.0 / 180.0 * M_PI;
1529
1530 // MEO/IGSO satellite
1531 // ------------------
1532 if (_i0 > iMaxGEO) {
1533 double OM = _OMEGA0 + (_OMEGADOT - omegaCompass)*tk - omegaCompass*toesec;
1534
1535 sinom = sin(OM);
1536 cosom = cos(OM);
1537 sini = sin(i);
1538 cosi = cos(i);
1539
1540 xc[0] = xp*cosom - yp*cosi*sinom;
1541 xc[1] = xp*sinom + yp*cosi*cosom;
1542 xc[2] = yp*sini;
1543 }
1544
1545 // GEO satellite
1546 // -------------
1547 else {
1548 double OM = _OMEGA0 + _OMEGADOT*tk - omegaCompass*toesec;
1549 double ll = omegaCompass*tk;
1550
1551 sinom = sin(OM);
1552 cosom = cos(OM);
1553 sini = sin(i);
1554 cosi = cos(i);
1555
1556 double xx = xp*cosom - yp*cosi*sinom;
1557 double yy = xp*sinom + yp*cosi*cosom;
1558 double zz = yp*sini;
1559
1560 Matrix R1 = BNC_PPP::t_astro::rotX(-5.0 / 180.0 * M_PI);
1561 Matrix R2 = BNC_PPP::t_astro::rotZ(ll);
1562
1563 ColumnVector X1(3); X1 << xx << yy << zz;
1564 ColumnVector X2 = R2*R1*X1;
1565
1566 xc[0] = X2(1);
1567 xc[1] = X2(2);
1568 xc[2] = X2(3);
1569 }
1570
1571 double tc = tt - _TOC;
1572 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc
1573 - 4.442807633e-10 * _e * sqrt(a0) *sin(E);
1574
1575 // Velocity
1576 // --------
1577 double tanv2 = tan(v/2);
1578 double dEdM = 1 / (1 - _e*cos(E));
1579 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2)
1580 / (1 + tanv2*tanv2) * dEdM * n;
1581 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
1582 double dotom = _OMEGADOT - t_CST::omega;
1583 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
1584 double dotr = a0 * _e*sin(E) * dEdM * n
1585 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
1586 double dotx = dotr*cos(u) - r*sin(u)*dotu;
1587 double doty = dotr*sin(u) + r*cos(u)*dotu;
1588
1589 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
1590 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
1591 + yp*sini*sinom*doti; // dX / di
1592
1593 vv[1] = sinom *dotx + cosi*cosom *doty
1594 + xp*cosom*dotom - yp*cosi*sinom*dotom
1595 - yp*sini*cosom*doti;
1596
1597 vv[2] = sini *doty + yp*cosi *doti;
1598
1599 // dotC = _clock_drift + _clock_driftrate*tc
1600 // - 4.442807633e-10*_e*sqrt(a0)*cos(E) * dEdM * n;
1601
1602 return success;
1603}
1604
1605// RINEX Format String
1606//////////////////////////////////////////////////////////////////////////////
1607QString t_ephCompass::toString(double version) const {
1608
1609 QString rnxStr = rinexDateStr(_TOC_bdt, _prn, version);
1610
1611 QTextStream out(&rnxStr);
1612
1613 out << QString("%1%2%3\n")
1614 .arg(_clock_bias, 19, 'e', 12)
1615 .arg(_clock_drift, 19, 'e', 12)
1616 .arg(_clock_driftrate, 19, 'e', 12);
1617
1618 QString fmt = version < 3.0 ? " %1%2%3%4\n" : " %1%2%3%4\n";
1619
1620 out << QString(fmt)
1621 .arg(double(_AODE), 19, 'e', 12)
1622 .arg(_Crs, 19, 'e', 12)
1623 .arg(_Delta_n, 19, 'e', 12)
1624 .arg(_M0, 19, 'e', 12);
1625
1626 out << QString(fmt)
1627 .arg(_Cuc, 19, 'e', 12)
1628 .arg(_e, 19, 'e', 12)
1629 .arg(_Cus, 19, 'e', 12)
1630 .arg(_sqrt_A, 19, 'e', 12);
1631
1632 out << QString(fmt)
1633 .arg(_TOE_bdt.gpssec(), 19, 'e', 12)
1634 .arg(_Cic, 19, 'e', 12)
1635 .arg(_OMEGA0, 19, 'e', 12)
1636 .arg(_Cis, 19, 'e', 12);
1637
1638 out << QString(fmt)
1639 .arg(_i0, 19, 'e', 12)
1640 .arg(_Crc, 19, 'e', 12)
1641 .arg(_omega, 19, 'e', 12)
1642 .arg(_OMEGADOT, 19, 'e', 12);
1643
1644 out << QString(fmt)
1645 .arg(_IDOT, 19, 'e', 12)
1646 .arg(0.0, 19, 'e', 12)
1647 .arg(double(_TOE_bdt.gpsw()), 19, 'e', 12)
1648 .arg(0.0, 19, 'e', 12);
1649
1650 out << QString(fmt)
1651 .arg(0.0, 19, 'e', 12)
1652 .arg(double(_SatH1), 19, 'e', 12)
1653 .arg(_TGD1, 19, 'e', 12)
1654 .arg(_TGD2, 19, 'e', 12);
1655
1656 out << QString(fmt)
1657 .arg(_TOE_bdt.gpssec(), 19, 'e', 12)
[6537]1658 .arg(double(_AODC), 19, 'e', 12);
[6400]1659
1660 return rnxStr;
1661}
1662
Note: See TracBrowser for help on using the repository browser.