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

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