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

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

last unit chages cancelled because they all were correct together

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