source: ntrip/trunk/BNC/RTCM3/ephemeris.cpp@ 3699

Last change on this file since 3699 was 3699, checked in by mervart, 12 years ago
File size: 30.5 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 "timeutils.h"
12#include "bnctime.h"
13#include "bncapp.h"
14
15using namespace std;
16
17#define PI 3.1415926535898
18// Returns nearest integer value
19////////////////////////////////////////////////////////////////////////////
20static double NearestInt(double fl, double * remain)
21{
22 bool isneg = fl < 0.0;
23 double intval;
24 if(isneg) fl *= -1.0;
25 intval = (double)((unsigned long)(fl+0.5));
26 if(isneg) {fl *= -1.0; intval *= -1.0;}
27 if(remain)
28 *remain = fl-intval;
29 return intval;
30} /* NearestInt() */
31
32// Returns CRC24
33////////////////////////////////////////////////////////////////////////////
34static unsigned long CRC24(long size, const unsigned char *buf)
35{
36 unsigned long crc = 0;
37 int i;
38
39 while(size--)
40 {
41 crc ^= (*buf++) << (16);
42 for(i = 0; i < 8; i++)
43 {
44 crc <<= 1;
45 if(crc & 0x1000000)
46 crc ^= 0x01864cfb;
47 }
48 }
49 return crc;
50} /* CRC24 */
51
52//
53////////////////////////////////////////////////////////////////////////////
54bool t_eph::isNewerThan(const t_eph* eph) const {
55 if (_GPSweek > eph->_GPSweek ||
56 (_GPSweek == eph->_GPSweek && _GPSweeks > eph->_GPSweeks)) {
57 return true;
58 }
59 else {
60 return false;
61 }
62}
63
64// Set GPS Satellite Position
65////////////////////////////////////////////////////////////////////////////
66void t_ephGPS::set(const gpsephemeris* ee) {
67
68 _prn = QString("G%1").arg(ee->satellite, 2, 10, QChar('0'));
69
70 // TODO: check if following two lines are correct
71 _GPSweek = ee->GPSweek;
72 _GPSweeks = ee->TOE;
73
74 _TOW = ee->TOW;
75 _TOC = ee->TOC;
76 _TOE = ee->TOE;
77 _IODE = ee->IODE;
78 _IODC = ee->IODC;
79
80 _clock_bias = ee->clock_bias ;
81 _clock_drift = ee->clock_drift ;
82 _clock_driftrate = ee->clock_driftrate;
83
84 _Crs = ee->Crs;
85 _Delta_n = ee->Delta_n;
86 _M0 = ee->M0;
87 _Cuc = ee->Cuc;
88 _e = ee->e;
89 _Cus = ee->Cus;
90 _sqrt_A = ee->sqrt_A;
91 _Cic = ee->Cic;
92 _OMEGA0 = ee->OMEGA0;
93 _Cis = ee->Cis;
94 _i0 = ee->i0;
95 _Crc = ee->Crc;
96 _omega = ee->omega;
97 _OMEGADOT = ee->OMEGADOT;
98 _IDOT = ee->IDOT;
99
100 _TGD = ee->TGD;
101
102 _ok = true;
103}
104
105// Compute GPS Satellite Position (virtual)
106////////////////////////////////////////////////////////////////////////////
107void t_ephGPS::position(int GPSweek, double GPSweeks,
108 double* xc,
109 double* vv) const {
110
111 static const double secPerWeek = 7 * 86400.0;
112 static const double omegaEarth = 7292115.1467e-11;
113 static const double gmWGS = 398.6005e12;
114
115 memset(xc, 0, 4*sizeof(double));
116 memset(vv, 0, 3*sizeof(double));
117
118 double a0 = _sqrt_A * _sqrt_A;
119 if (a0 == 0) {
120 return;
121 }
122
123 double n0 = sqrt(gmWGS/(a0*a0*a0));
124 double tk = GPSweeks - _TOE;
125 if (GPSweek != _GPSweek) {
126 tk += (GPSweek - _GPSweek) * secPerWeek;
127 }
128 double n = n0 + _Delta_n;
129 double M = _M0 + n*tk;
130 double E = M;
131 double E_last;
132 do {
133 E_last = E;
134 E = M + _e*sin(E);
135 } while ( fabs(E-E_last)*a0 > 0.001 );
136 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
137 double u0 = v + _omega;
138 double sin2u0 = sin(2*u0);
139 double cos2u0 = cos(2*u0);
140 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
141 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
142 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
143 double xp = r*cos(u);
144 double yp = r*sin(u);
145 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
146 omegaEarth*_TOE;
147
148 double sinom = sin(OM);
149 double cosom = cos(OM);
150 double sini = sin(i);
151 double cosi = cos(i);
152 xc[0] = xp*cosom - yp*cosi*sinom;
153 xc[1] = xp*sinom + yp*cosi*cosom;
154 xc[2] = yp*sini;
155
156 double tc = GPSweeks - _TOC;
157 if (GPSweek != _GPSweek) {
158 tc += (GPSweek - _GPSweek) * secPerWeek;
159 }
160 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
161
162 // Velocity
163 // --------
164 double tanv2 = tan(v/2);
165 double dEdM = 1 / (1 - _e*cos(E));
166 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
167 * dEdM * n;
168 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
169 double dotom = _OMEGADOT - omegaEarth;
170 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
171 double dotr = a0 * _e*sin(E) * dEdM * n
172 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
173 double dotx = dotr*cos(u) - r*sin(u)*dotu;
174 double doty = dotr*sin(u) + r*cos(u)*dotu;
175
176 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
177 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
178 + yp*sini*sinom*doti; // dX / di
179
180 vv[1] = sinom *dotx + cosi*cosom *doty
181 + xp*cosom*dotom - yp*cosi*sinom*dotom
182 - yp*sini*cosom*doti;
183
184 vv[2] = sini *doty + yp*cosi *doti;
185
186 // Relativistic Correction
187 // -----------------------
188 // xc(4) -= 4.442807633e-10 * _e * sqrt(a0) *sin(E);
189 xc[3] -= 2.0 * (xc[0]*vv[0] + xc[1]*vv[1] + xc[2]*vv[2]) / t_CST::c / t_CST::c;
190}
191
192// build up RTCM3 for GPS
193////////////////////////////////////////////////////////////////////////////
194#define GPSTOINT(type, value) static_cast<type>(NearestInt(value,0))
195
196#define GPSADDBITS(a, b) {bitbuffer = (bitbuffer<<(a)) \
197 |(GPSTOINT(long long,b)&((1ULL<<a)-1)); \
198 numbits += (a); \
199 while(numbits >= 8) { \
200 buffer[size++] = bitbuffer>>(numbits-8);numbits -= 8;}}
201#define GPSADDBITSFLOAT(a,b,c) {long long i = GPSTOINT(long long,(b)/(c)); \
202 GPSADDBITS(a,i)};
203
204int t_ephGPS::RTCM3(unsigned char *buffer)
205{
206
207 unsigned char *startbuffer = buffer;
208 buffer= buffer+3;
209 int size = 0;
210 int numbits = 0;
211 unsigned long long bitbuffer = 0;
212 if (_ura <= 2.40){
213 _ura = 0;
214 }
215 else if (_ura <= 3.40){
216 _ura = 1;
217 }
218 else if (_ura <= 6.85){
219 _ura = 2;
220 }
221 else if (_ura <= 9.65){
222 _ura = 3;
223 }
224 else if (_ura <= 13.65){
225 _ura = 4;
226 }
227 else if (_ura <= 24.00){
228 _ura = 5;
229 }
230 else if (_ura <= 48.00){
231 _ura = 6;
232 }
233 else if (_ura <= 96.00){
234 _ura = 7;
235 }
236 else if (_ura <= 192.00){
237 _ura = 8;
238 }
239 else if (_ura <= 384.00){
240 _ura = 9;
241 }
242 else if (_ura <= 768.00){
243 _ura = 10;
244 }
245 else if (_ura <= 1536.00){
246 _ura = 11;
247 }
248 else if (_ura <= 1536.00){
249 _ura = 12;
250 }
251 else if (_ura <= 2072.00){
252 _ura = 13;
253 }
254 else if (_ura <= 6144.00){
255 _ura = 14;
256 }
257 else{
258 _ura = 15;
259 }
260
261 GPSADDBITS(12, 1019)
262 GPSADDBITS(6,_prn.right((_prn.length()-1)).toInt())
263 GPSADDBITS(10, _GPSweek)
264 GPSADDBITS(4, _ura)
265 GPSADDBITS(2,_L2Codes)
266 GPSADDBITSFLOAT(14, _IDOT, PI/static_cast<double>(1<<30)
267 /static_cast<double>(1<<13))
268 GPSADDBITS(8, _IODE)
269 GPSADDBITS(16, static_cast<int>(_TOC)>>4)
270 GPSADDBITSFLOAT(8, _clock_driftrate, 1.0/static_cast<double>(1<<30)
271 /static_cast<double>(1<<25))
272 GPSADDBITSFLOAT(16, _clock_drift, 1.0/static_cast<double>(1<<30)
273 /static_cast<double>(1<<13))
274 GPSADDBITSFLOAT(22, _clock_bias, 1.0/static_cast<double>(1<<30)
275 /static_cast<double>(1<<1))
276 GPSADDBITS(10, _IODC)
277 GPSADDBITSFLOAT(16, _Crs, 1.0/static_cast<double>(1<<5))
278 GPSADDBITSFLOAT(16, _Delta_n, PI/static_cast<double>(1<<30)
279 /static_cast<double>(1<<13))
280 GPSADDBITSFLOAT(32, _M0, PI/static_cast<double>(1<<30)/static_cast<double>(1<<1))
281 GPSADDBITSFLOAT(16, _Cuc, 1.0/static_cast<double>(1<<29))
282 GPSADDBITSFLOAT(32, _e, 1.0/static_cast<double>(1<<30)/static_cast<double>(1<<3))
283 GPSADDBITSFLOAT(16, _Cus, 1.0/static_cast<double>(1<<29))
284 GPSADDBITSFLOAT(32, _sqrt_A, 1.0/static_cast<double>(1<<19))
285 GPSADDBITS(16, static_cast<int>(_TOE)>>4)
286 GPSADDBITSFLOAT(16, _Cic, 1.0/static_cast<double>(1<<29))
287 GPSADDBITSFLOAT(32, _OMEGA0, PI/static_cast<double>(1<<30)
288 /static_cast<double>(1<<1))
289 GPSADDBITSFLOAT(16, _Cis, 1.0/static_cast<double>(1<<29))
290 GPSADDBITSFLOAT(32, _i0, PI/static_cast<double>(1<<30)/static_cast<double>(1<<1))
291 GPSADDBITSFLOAT(16, _Crc, 1.0/static_cast<double>(1<<5))
292 GPSADDBITSFLOAT(32, _omega, PI/static_cast<double>(1<<30)
293 /static_cast<double>(1<<1))
294 GPSADDBITSFLOAT(24, _OMEGADOT, PI/static_cast<double>(1<<30)
295 /static_cast<double>(1<<13))
296 GPSADDBITSFLOAT(8, _TGD, 1.0/static_cast<double>(1<<30)/static_cast<double>(1<<1))
297 GPSADDBITS(6, _health)
298 GPSADDBITS(1, _L2PFlag)
299 GPSADDBITS(1, 0) /* GPS fit interval */
300
301 startbuffer[0]=0xD3;
302 startbuffer[1]=(size >> 8);
303 startbuffer[2]=size;
304 unsigned long i = CRC24(size+3, startbuffer);
305 buffer[size++] = i >> 16;
306 buffer[size++] = i >> 8;
307 buffer[size++] = i;
308 size += 3;
309 return size;
310}
311
312// Derivative of the state vector using a simple force model (static)
313////////////////////////////////////////////////////////////////////////////
314ColumnVector t_ephGlo::glo_deriv(double /* tt */, const ColumnVector& xv,
315 double* acc) {
316
317 // State vector components
318 // -----------------------
319 ColumnVector rr = xv.rows(1,3);
320 ColumnVector vv = xv.rows(4,6);
321
322 // Acceleration
323 // ------------
324 static const double GM = 398.60044e12;
325 static const double AE = 6378136.0;
326 static const double OMEGA = 7292115.e-11;
327 static const double C20 = -1082.6257e-6;
328
329 double rho = rr.norm_Frobenius();
330 double t1 = -GM/(rho*rho*rho);
331 double t2 = 3.0/2.0 * C20 * (GM*AE*AE) / (rho*rho*rho*rho*rho);
332 double t3 = OMEGA * OMEGA;
333 double t4 = 2.0 * OMEGA;
334 double z2 = rr(3) * rr(3);
335
336 // Vector of derivatives
337 // ---------------------
338 ColumnVector va(6);
339 va(1) = vv(1);
340 va(2) = vv(2);
341 va(3) = vv(3);
342 va(4) = (t1 + t2*(1.0-5.0*z2/(rho*rho)) + t3) * rr(1) + t4*vv(2) + acc[0];
343 va(5) = (t1 + t2*(1.0-5.0*z2/(rho*rho)) + t3) * rr(2) - t4*vv(1) + acc[1];
344 va(6) = (t1 + t2*(3.0-5.0*z2/(rho*rho)) ) * rr(3) + acc[2];
345
346 return va;
347}
348
349// Compute Glonass Satellite Position (virtual)
350////////////////////////////////////////////////////////////////////////////
351void t_ephGlo::position(int GPSweek, double GPSweeks,
352 double* xc, double* vv) const {
353
354 static const double secPerWeek = 7 * 86400.0;
355 static const double nominalStep = 10.0;
356
357 memset(xc, 0, 4*sizeof(double));
358 memset(vv, 0, 3*sizeof(double));
359
360 double dtPos = GPSweeks - _tt;
361 if (GPSweek != _GPSweek) {
362 dtPos += (GPSweek - _GPSweek) * secPerWeek;
363 }
364
365 int nSteps = int(fabs(dtPos) / nominalStep) + 1;
366 double step = dtPos / nSteps;
367
368 double acc[3];
369 acc[0] = _x_acceleration * 1.e3;
370 acc[1] = _y_acceleration * 1.e3;
371 acc[2] = _z_acceleration * 1.e3;
372 for (int ii = 1; ii <= nSteps; ii++) {
373 _xv = rungeKutta4(_tt, _xv, step, acc, glo_deriv);
374 _tt += step;
375 }
376
377 // Position and Velocity
378 // ---------------------
379 xc[0] = _xv(1);
380 xc[1] = _xv(2);
381 xc[2] = _xv(3);
382
383 vv[0] = _xv(4);
384 vv[1] = _xv(5);
385 vv[2] = _xv(6);
386
387 // Clock Correction
388 // ----------------
389 double dtClk = GPSweeks - _GPSweeks;
390 if (GPSweek != _GPSweek) {
391 dtClk += (GPSweek - _GPSweek) * secPerWeek;
392 }
393 xc[3] = -_tau + _gamma * dtClk;
394}
395
396// IOD of Glonass Ephemeris (virtual)
397////////////////////////////////////////////////////////////////////////////
398int t_ephGlo::IOD() const {
399 bncTime tGPS(_GPSweek, _GPSweeks);
400 bncTime tMoscow = tGPS - _gps_utc + 3 * 3600.0;
401 return int(tMoscow.daysec() / 900);
402}
403
404// Set Glonass Ephemeris
405////////////////////////////////////////////////////////////////////////////
406void t_ephGlo::set(const glonassephemeris* ee) {
407
408 _prn = QString("R%1").arg(ee->almanac_number, 2, 10, QChar('0'));
409
410 int ww = ee->GPSWeek;
411 int tow = ee->GPSTOW;
412 updatetime(&ww, &tow, ee->tb*1000, 0); // Moscow -> GPS
413
414 // Check the day once more
415 // -----------------------
416 {
417 const double secPerDay = 24 * 3600.0;
418 const double secPerWeek = 7 * secPerDay;
419 int ww_old = ww;
420 int tow_old = tow;
421 int currentWeek;
422 double currentSec;
423 currentGPSWeeks(currentWeek, currentSec);
424 bncTime currentTime(currentWeek, currentSec);
425 bncTime hTime(ww, (double) tow);
426
427 bool changed = false;
428 if (hTime - currentTime > secPerDay/2.0) {
429 changed = true;
430 tow -= secPerDay;
431 if (tow < 0) {
432 tow += secPerWeek;
433 ww -= 1;
434 }
435 }
436 else if (hTime - currentTime < -secPerDay/2.0) {
437 changed = true;
438 tow += secPerDay;
439 if (tow > secPerWeek) {
440 tow -= secPerWeek;
441 ww += 1;
442 }
443 }
444
445 if (changed && ((bncApp*) qApp)->mode() == bncApp::batchPostProcessing) {
446 bncTime newHTime(ww, (double) tow);
447 cout << "GLONASS " << ee->almanac_number << " Time Changed at "
448 << currentTime.datestr() << " " << currentTime.timestr()
449 << endl
450 << "old: " << hTime.datestr() << " " << hTime.timestr()
451 << endl
452 << "new: " << newHTime.datestr() << " " << newHTime.timestr()
453 << endl
454 << "eph: " << ee->GPSWeek << " " << ee->GPSTOW << " " << ee->tb
455 << endl
456 << "ww, tow (old): " << ww_old << " " << tow_old
457 << endl
458 << "ww, tow (new): " << ww << " " << tow
459 << endl << endl;
460 }
461 }
462
463 bncTime hlpTime(ww, (double) tow);
464 unsigned year, month, day;
465 hlpTime.civil_date(year, month, day);
466 _gps_utc = gnumleap(year, month, day);
467
468 _GPSweek = ww;
469 _GPSweeks = tow;
470 _E = ee->E;
471 _tau = ee->tau;
472 _gamma = ee->gamma;
473 _x_pos = ee->x_pos;
474 _x_velocity = ee->x_velocity;
475 _x_acceleration = ee->x_acceleration;
476 _y_pos = ee->y_pos;
477 _y_velocity = ee->y_velocity;
478 _y_acceleration = ee->y_acceleration;
479 _z_pos = ee->z_pos;
480 _z_velocity = ee->z_velocity;
481 _z_acceleration = ee->z_acceleration;
482 _health = 0;
483 _frequency_number = ee->frequency_number;
484 _tki = ee->tk-3*60*60; if (_tki < 0) _tki += 86400;
485
486 // Initialize status vector
487 // ------------------------
488 _tt = _GPSweeks;
489
490 _xv(1) = _x_pos * 1.e3;
491 _xv(2) = _y_pos * 1.e3;
492 _xv(3) = _z_pos * 1.e3;
493 _xv(4) = _x_velocity * 1.e3;
494 _xv(5) = _y_velocity * 1.e3;
495 _xv(6) = _z_velocity * 1.e3;
496
497 _ok = true;
498}
499
500// build up RTCM3 for GLONASS
501////////////////////////////////////////////////////////////////////////////
502#define GLONASSTOINT(type, value) static_cast<type>(NearestInt(value,0))
503
504#define GLONASSADDBITS(a, b) {bitbuffer = (bitbuffer<<(a)) \
505 |(GLONASSTOINT(long long,b)&((1ULL<<(a))-1)); \
506 numbits += (a); \
507 while(numbits >= 8) { \
508 buffer[size++] = bitbuffer>>(numbits-8);numbits -= 8;}}
509#define GLONASSADDBITSFLOATM(a,b,c) {int s; long long i; \
510 if(b < 0.0) \
511 { \
512 s = 1; \
513 i = GLONASSTOINT(long long,(-b)/(c)); \
514 if(!i) s = 0; \
515 } \
516 else \
517 { \
518 s = 0; \
519 i = GLONASSTOINT(long long,(b)/(c)); \
520 } \
521 GLONASSADDBITS(1,s) \
522 GLONASSADDBITS(a-1,i)}
523
524int t_ephGlo::RTCM3(unsigned char *buffer)
525{
526
527 int size = 0;
528 int numbits = 0;
529 long long bitbuffer = 0;
530 unsigned char *startbuffer = buffer;
531 buffer= buffer+3;
532
533 GLONASSADDBITS(12, 1020)
534 GLONASSADDBITS(6, _prn.right((_prn.length()-1)).toInt())
535 GLONASSADDBITS(5, 7+_frequency_number)
536 GLONASSADDBITS(1, 0)
537 GLONASSADDBITS(1, 0)
538 GLONASSADDBITS(2, 0)
539 _tki=_tki+3*60*60;
540 GLONASSADDBITS(5, static_cast<int>(_tki)/(60*60))
541 GLONASSADDBITS(6, (static_cast<int>(_tki)/60)%60)
542 GLONASSADDBITS(1, (static_cast<int>(_tki)/30)%30)
543 GLONASSADDBITS(1, _health)
544 GLONASSADDBITS(1, 0)
545 unsigned long long timeofday = (static_cast<int>(_tt+3*60*60-_gps_utc)%86400);
546 GLONASSADDBITS(7, timeofday/60/15)
547 GLONASSADDBITSFLOATM(24, _x_velocity*1000, 1000.0/static_cast<double>(1<<20))
548 GLONASSADDBITSFLOATM(27, _x_pos*1000, 1000.0/static_cast<double>(1<<11))
549 GLONASSADDBITSFLOATM(5, _x_acceleration*1000, 1000.0/static_cast<double>(1<<30))
550 GLONASSADDBITSFLOATM(24, _y_velocity*1000, 1000.0/static_cast<double>(1<<20))
551 GLONASSADDBITSFLOATM(27, _y_pos*1000, 1000.0/static_cast<double>(1<<11))
552 GLONASSADDBITSFLOATM(5, _y_acceleration*1000, 1000.0/static_cast<double>(1<<30))
553 GLONASSADDBITSFLOATM(24, _z_velocity*1000, 1000.0/static_cast<double>(1<<20))
554 GLONASSADDBITSFLOATM(27,_z_pos*1000, 1000.0/static_cast<double>(1<<11))
555 GLONASSADDBITSFLOATM(5, _z_acceleration*1000, 1000.0/static_cast<double>(1<<30))
556 GLONASSADDBITS(1, 0)
557 GLONASSADDBITSFLOATM(11, _gamma, 1.0/static_cast<double>(1<<30)
558 /static_cast<double>(1<<10))
559 GLONASSADDBITS(2, 0) /* GLONASS-M P */
560 GLONASSADDBITS(1, 0) /* GLONASS-M ln(3) */
561 GLONASSADDBITSFLOATM(22, _tau, 1.0/static_cast<double>(1<<30))
562 GLONASSADDBITS(5, 0) /* GLONASS-M delta tau */
563 GLONASSADDBITS(5, _E)
564 GLONASSADDBITS(1, 0) /* GLONASS-M P4 */
565 GLONASSADDBITS(4, 0) /* GLONASS-M FT */
566 GLONASSADDBITS(11, 0) /* GLONASS-M NT */
567 GLONASSADDBITS(2, 0) /* GLONASS-M active? */
568 GLONASSADDBITS(1, 0) /* GLONASS additional data */
569 GLONASSADDBITS(11, 0) /* GLONASS NA */
570 GLONASSADDBITS(32, 0) /* GLONASS tau C */
571 GLONASSADDBITS(5, 0) /* GLONASS-M N4 */
572 GLONASSADDBITS(22, 0) /* GLONASS-M tau GPS */
573 GLONASSADDBITS(1, 0) /* GLONASS-M ln(5) */
574 GLONASSADDBITS(7, 0) /* Reserved */
575
576 startbuffer[0]=0xD3;
577 startbuffer[1]=(size >> 8);
578 startbuffer[2]=size;
579 unsigned long i = CRC24(size+3, startbuffer);
580 buffer[size++] = i >> 16;
581 buffer[size++] = i >> 8;
582 buffer[size++] = i;
583 size += 3;
584 return size;
585}
586
587// Set Galileo Satellite Position
588////////////////////////////////////////////////////////////////////////////
589void t_ephGal::set(const galileoephemeris* ee) {
590
591 _prn = QString("E%1").arg(ee->satellite, 2, 10, QChar('0'));
592
593 _GPSweek = ee->Week;
594 _GPSweeks = ee->TOE;
595
596 _TOC = ee->TOC;
597 _TOE = ee->TOE;
598 _IODnav = ee->IODnav;
599
600 _clock_bias = ee->clock_bias ;
601 _clock_drift = ee->clock_drift ;
602 _clock_driftrate = ee->clock_driftrate;
603
604 _Crs = ee->Crs;
605 _Delta_n = ee->Delta_n;
606 _M0 = ee->M0;
607 _Cuc = ee->Cuc;
608 _e = ee->e;
609 _Cus = ee->Cus;
610 _sqrt_A = ee->sqrt_A;
611 _Cic = ee->Cic;
612 _OMEGA0 = ee->OMEGA0;
613 _Cis = ee->Cis;
614 _i0 = ee->i0;
615 _Crc = ee->Crc;
616 _omega = ee->omega;
617 _OMEGADOT = ee->OMEGADOT;
618 _IDOT = ee->IDOT;
619
620 _ok = true;
621}
622
623// Compute Galileo Satellite Position (virtual)
624////////////////////////////////////////////////////////////////////////////
625void t_ephGal::position(int GPSweek, double GPSweeks,
626 double* xc,
627 double* vv) const {
628
629 static const double secPerWeek = 7 * 86400.0;
630 static const double omegaEarth = 7292115.1467e-11;
631 static const double gmWGS = 398.6005e12;
632
633 memset(xc, 0, 4*sizeof(double));
634 memset(vv, 0, 3*sizeof(double));
635
636 double a0 = _sqrt_A * _sqrt_A;
637 if (a0 == 0) {
638 return;
639 }
640
641 double n0 = sqrt(gmWGS/(a0*a0*a0));
642 double tk = GPSweeks - _TOE;
643 if (GPSweek != _GPSweek) {
644 tk += (GPSweek - _GPSweek) * secPerWeek;
645 }
646 double n = n0 + _Delta_n;
647 double M = _M0 + n*tk;
648 double E = M;
649 double E_last;
650 do {
651 E_last = E;
652 E = M + _e*sin(E);
653 } while ( fabs(E-E_last)*a0 > 0.001 );
654 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
655 double u0 = v + _omega;
656 double sin2u0 = sin(2*u0);
657 double cos2u0 = cos(2*u0);
658 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
659 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
660 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
661 double xp = r*cos(u);
662 double yp = r*sin(u);
663 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
664 omegaEarth*_TOE;
665
666 double sinom = sin(OM);
667 double cosom = cos(OM);
668 double sini = sin(i);
669 double cosi = cos(i);
670 xc[0] = xp*cosom - yp*cosi*sinom;
671 xc[1] = xp*sinom + yp*cosi*cosom;
672 xc[2] = yp*sini;
673
674 double tc = GPSweeks - _TOC;
675 if (GPSweek != _GPSweek) {
676 tc += (GPSweek - _GPSweek) * secPerWeek;
677 }
678 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
679
680 // Velocity
681 // --------
682 double tanv2 = tan(v/2);
683 double dEdM = 1 / (1 - _e*cos(E));
684 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
685 * dEdM * n;
686 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
687 double dotom = _OMEGADOT - omegaEarth;
688 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
689 double dotr = a0 * _e*sin(E) * dEdM * n
690 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
691 double dotx = dotr*cos(u) - r*sin(u)*dotu;
692 double doty = dotr*sin(u) + r*cos(u)*dotu;
693
694 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
695 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
696 + yp*sini*sinom*doti; // dX / di
697
698 vv[1] = sinom *dotx + cosi*cosom *doty
699 + xp*cosom*dotom - yp*cosi*sinom*dotom
700 - yp*sini*cosom*doti;
701
702 vv[2] = sini *doty + yp*cosi *doti;
703
704 // Relativistic Correction
705 // -----------------------
706 // xc(4) -= 4.442807633e-10 * _e * sqrt(a0) *sin(E);
707 xc[3] -= 2.0 * (xc[0]*vv[0] + xc[1]*vv[1] + xc[2]*vv[2]) / t_CST::c / t_CST::c;
708}
709
710// build up RTCM3 for Galileo
711////////////////////////////////////////////////////////////////////////////
712#define GALILEOTOINT(type, value) static_cast<type>(NearestInt(value, 0))
713
714#define GALILEOADDBITS(a, b) {bitbuffer = (bitbuffer<<(a)) \
715 |(GALILEOTOINT(long long,b)&((1LL<<a)-1)); \
716 numbits += (a); \
717 while(numbits >= 8) { \
718 buffer[size++] = bitbuffer>>(numbits-8);numbits -= 8;}}
719#define GALILEOADDBITSFLOAT(a,b,c) {long long i = GALILEOTOINT(long long,(b)/(c)); \
720 GALILEOADDBITS(a,i)};
721
722int t_ephGal::RTCM3(unsigned char *buffer) {
723 int size = 0;
724 int numbits = 0;
725 long long bitbuffer = 0;
726 unsigned char *startbuffer = buffer;
727 buffer= buffer+3;
728
729 GALILEOADDBITS(12, /*inav ? 1046 :*/ 1045)
730 GALILEOADDBITS(6, _prn.right((_prn.length()-1)).toInt())
731 GALILEOADDBITS(12, _GPSweek)
732 GALILEOADDBITS(10, _IODnav)
733 GALILEOADDBITS(8, _SISA)
734 GALILEOADDBITSFLOAT(14, _IDOT, PI/static_cast<double>(1<<30)
735 /static_cast<double>(1<<13))
736 GALILEOADDBITS(14, _TOC/60)
737 GALILEOADDBITSFLOAT(6, _clock_driftrate, 1.0/static_cast<double>(1<<30)
738 /static_cast<double>(1<<29))
739 GALILEOADDBITSFLOAT(21, _clock_drift, 1.0/static_cast<double>(1<<30)
740 /static_cast<double>(1<<16))
741 GALILEOADDBITSFLOAT(31, _clock_bias, 1.0/static_cast<double>(1<<30)
742 /static_cast<double>(1<<4))
743 GALILEOADDBITSFLOAT(16, _Crs, 1.0/static_cast<double>(1<<5))
744 GALILEOADDBITSFLOAT(16, _Delta_n, PI/static_cast<double>(1<<30)
745 /static_cast<double>(1<<13))
746 GALILEOADDBITSFLOAT(32, _M0, PI/static_cast<double>(1<<30)/static_cast<double>(1<<1))
747 GALILEOADDBITSFLOAT(16, _Cuc, 1.0/static_cast<double>(1<<29))
748 GALILEOADDBITSFLOAT(32, _e, 1.0/static_cast<double>(1<<30)/static_cast<double>(1<<3))
749 GALILEOADDBITSFLOAT(16, _Cus, 1.0/static_cast<double>(1<<29))
750 GALILEOADDBITSFLOAT(32, _sqrt_A, 1.0/static_cast<double>(1<<19))
751 GALILEOADDBITS(14, _TOE/60)
752 GALILEOADDBITSFLOAT(16, _Cic, 1.0/static_cast<double>(1<<29))
753 GALILEOADDBITSFLOAT(32, _OMEGA0, PI/static_cast<double>(1<<30)
754 /static_cast<double>(1<<1))
755 GALILEOADDBITSFLOAT(16, _Cis, 1.0/static_cast<double>(1<<29))
756 GALILEOADDBITSFLOAT(32, _i0, PI/static_cast<double>(1<<30)/static_cast<double>(1<<1))
757 GALILEOADDBITSFLOAT(16, _Crc, 1.0/static_cast<double>(1<<5))
758 GALILEOADDBITSFLOAT(32, _omega, PI/static_cast<double>(1<<30)
759 /static_cast<double>(1<<1))
760 GALILEOADDBITSFLOAT(24, _OMEGADOT, PI/static_cast<double>(1<<30)
761 /static_cast<double>(1<<13))
762 GALILEOADDBITSFLOAT(10, _BGD_1_5A, 1.0/static_cast<double>(1<<30)
763 /static_cast<double>(1<<2))
764 /*if(inav)
765 {
766 GALILEOADDBITSFLOAT(10, _BGD_1_5B, 1.0/static_cast<double>(1<<30)
767 /static_cast<double>(1<<2))
768 GALILEOADDBITS(2, _E5bHS)
769 GALILEOADDBITS(1, flags & MNFGALEPHF_E5BDINVALID)
770 }
771 else*/
772 {
773 GALILEOADDBITS(2, _E5aHS)
774 GALILEOADDBITS(1, /*flags & MNFGALEPHF_E5ADINVALID*/0)
775 }
776 _TOE = 0.9999E9;
777 GALILEOADDBITS(20, _TOE)
778
779 GALILEOADDBITS(/*inav ? 1 :*/ 3, 0) /* fill up */
780
781 startbuffer[0]=0xD3;
782 startbuffer[1]=(size >> 8);
783 startbuffer[2]=size;
784 unsigned long i = CRC24(size+3, startbuffer);
785 buffer[size++] = i >> 16;
786 buffer[size++] = i >> 8;
787 buffer[size++] = i;
788 size += 3;
789 return size;
790}
791
792// Constructor
793//////////////////////////////////////////////////////////////////////////////
794t_ephGPS::t_ephGPS(float rnxVersion, const QStringList& lines) {
795
796 const int nLines = 8;
797
798 _ok = false;
799
800 if (lines.size() != nLines) {
801 return;
802 }
803
804 // RINEX Format
805 // ------------
806 int fieldLen = 19;
807
808 int pos[4];
809 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
810 pos[1] = pos[0] + fieldLen;
811 pos[2] = pos[1] + fieldLen;
812 pos[3] = pos[2] + fieldLen;
813
814 // Read eight lines
815 // ----------------
816 for (int iLine = 0; iLine < nLines; iLine++) {
817 QString line = lines[iLine];
818
819 if ( iLine == 0 ) {
820 QTextStream in(line.left(pos[1]).toAscii());
821
822 int year, month, day, hour, min;
823 double sec;
824
825 in >> _prn >> year >> month >> day >> hour >> min >> sec;
826
827 if (_prn.at(0) != 'G') {
828 _prn = QString("G%1").arg(_prn.toInt(), 2, 10, QLatin1Char('0'));
829 }
830
831 if (year < 80) {
832 year += 2000;
833 }
834 else if (year < 100) {
835 year += 1900;
836 }
837
838 bncTime hlpTime;
839 hlpTime.set(year, month, day, hour, min, sec);
840 _GPSweek = hlpTime.gpsw();
841 _GPSweeks = hlpTime.gpssec();
842 _TOC = _GPSweeks;
843
844 if ( readDbl(line, pos[1], fieldLen, _clock_bias ) ||
845 readDbl(line, pos[2], fieldLen, _clock_drift ) ||
846 readDbl(line, pos[3], fieldLen, _clock_driftrate) ) {
847 return;
848 }
849 }
850
851 else if ( iLine == 1 ) {
852 if ( readDbl(line, pos[0], fieldLen, _IODE ) ||
853 readDbl(line, pos[1], fieldLen, _Crs ) ||
854 readDbl(line, pos[2], fieldLen, _Delta_n) ||
855 readDbl(line, pos[3], fieldLen, _M0 ) ) {
856 return;
857 }
858 }
859
860 else if ( iLine == 2 ) {
861 if ( readDbl(line, pos[0], fieldLen, _Cuc ) ||
862 readDbl(line, pos[1], fieldLen, _e ) ||
863 readDbl(line, pos[2], fieldLen, _Cus ) ||
864 readDbl(line, pos[3], fieldLen, _sqrt_A) ) {
865 return;
866 }
867 }
868
869 else if ( iLine == 3 ) {
870 if ( readDbl(line, pos[0], fieldLen, _TOE ) ||
871 readDbl(line, pos[1], fieldLen, _Cic ) ||
872 readDbl(line, pos[2], fieldLen, _OMEGA0) ||
873 readDbl(line, pos[3], fieldLen, _Cis ) ) {
874 return;
875 }
876 }
877
878 else if ( iLine == 4 ) {
879 if ( readDbl(line, pos[0], fieldLen, _i0 ) ||
880 readDbl(line, pos[1], fieldLen, _Crc ) ||
881 readDbl(line, pos[2], fieldLen, _omega ) ||
882 readDbl(line, pos[3], fieldLen, _OMEGADOT) ) {
883 return;
884 }
885 }
886
887 else if ( iLine == 5 ) {
888 double dummy, TOEw;
889 if ( readDbl(line, pos[0], fieldLen, _IDOT) ||
890 readDbl(line, pos[1], fieldLen, dummy) ||
891 readDbl(line, pos[2], fieldLen, TOEw ) ||
892 readDbl(line, pos[3], fieldLen, dummy) ) {
893 return;
894 }
895 }
896
897 else if ( iLine == 6 ) {
898 double dummy;
899 if ( readDbl(line, pos[0], fieldLen, dummy ) ||
900 readDbl(line, pos[1], fieldLen, _health) ||
901 readDbl(line, pos[2], fieldLen, _TGD ) ||
902 readDbl(line, pos[3], fieldLen, _IODC ) ) {
903 return;
904 }
905 }
906
907 else if ( iLine == 7 ) {
908 double TOT;
909 if ( readDbl(line, pos[0], fieldLen, TOT) ) {
910 return;
911 }
912 }
913 }
914
915 _ok = true;
916}
917
918// Constructor
919//////////////////////////////////////////////////////////////////////////////
920t_ephGlo::t_ephGlo(float rnxVersion, const QStringList& lines) {
921
922 const int nLines = 4;
923
924 _ok = false;
925
926 if (lines.size() != nLines) {
927 return;
928 }
929
930 // RINEX Format
931 // ------------
932 int fieldLen = 19;
933
934 int pos[4];
935 pos[0] = (rnxVersion <= 2.12) ? 3 : 4;
936 pos[1] = pos[0] + fieldLen;
937 pos[2] = pos[1] + fieldLen;
938 pos[3] = pos[2] + fieldLen;
939
940 // Read four lines
941 // ---------------
942 for (int iLine = 0; iLine < nLines; iLine++) {
943 QString line = lines[iLine];
944
945 if ( iLine == 0 ) {
946 QTextStream in(line.left(pos[1]).toAscii());
947
948 int year, month, day, hour, min;
949 double sec;
950
951 in >> _prn >> year >> month >> day >> hour >> min >> sec;
952
953 if (_prn.at(0) != 'R') {
954 _prn = QString("R%1").arg(_prn.toInt(), 2, 10, QLatin1Char('0'));
955 }
956
957 if (year < 80) {
958 year += 2000;
959 }
960 else if (year < 100) {
961 year += 1900;
962 }
963
964 bncTime hlpTime;
965 hlpTime.set(year, month, day, hour, min, sec);
966 _GPSweek = hlpTime.gpsw();
967 _GPSweeks = hlpTime.gpssec();
968
969 _gps_utc = gnumleap(year, month, day);
970 // double _tki; // message frame time
971
972 double second_tot;
973 if ( readDbl(line, pos[1], fieldLen, _tau ) ||
974 readDbl(line, pos[2], fieldLen, _gamma ) ||
975 readDbl(line, pos[3], fieldLen, second_tot) ) {
976 return;
977 }
978 }
979
980 else if ( iLine == 1 ) {
981 if ( readDbl(line, pos[0], fieldLen, _x_pos ) ||
982 readDbl(line, pos[1], fieldLen, _x_velocity ) ||
983 readDbl(line, pos[2], fieldLen, _x_acceleration) ||
984 readDbl(line, pos[3], fieldLen, _health ) ) {
985 return;
986 }
987 }
988
989 else if ( iLine == 2 ) {
990 if ( readDbl(line, pos[0], fieldLen, _y_pos ) ||
991 readDbl(line, pos[1], fieldLen, _y_velocity ) ||
992 readDbl(line, pos[2], fieldLen, _y_acceleration ) ||
993 readDbl(line, pos[3], fieldLen, _frequency_number) ) {
994 return;
995 }
996 }
997
998 else if ( iLine == 3 ) {
999 if ( readDbl(line, pos[0], fieldLen, _z_pos ) ||
1000 readDbl(line, pos[1], fieldLen, _z_velocity ) ||
1001 readDbl(line, pos[2], fieldLen, _z_acceleration) ||
1002 readDbl(line, pos[3], fieldLen, _E ) ) {
1003 return;
1004 }
1005 }
1006 }
1007
1008 // Initialize status vector
1009 // ------------------------
1010 _tt = _GPSweeks;
1011
1012 _xv.ReSize(6);
1013
1014 _xv(1) = _x_pos * 1.e3;
1015 _xv(2) = _y_pos * 1.e3;
1016 _xv(3) = _z_pos * 1.e3;
1017 _xv(4) = _x_velocity * 1.e3;
1018 _xv(5) = _y_velocity * 1.e3;
1019 _xv(6) = _z_velocity * 1.e3;
1020
1021 _ok = true;
1022}
1023
1024// Constructor
1025//////////////////////////////////////////////////////////////////////////////
1026t_ephGal::t_ephGal(float /* rnxVersion */, const QStringList& /* lines */) {
1027
1028 _ok = false;
1029}
Note: See TracBrowser for help on using the repository browser.