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

Last change on this file since 3280 was 3280, checked in by mervart, 13 years ago
File size: 24.8 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
103// Compute GPS Satellite Position (virtual)
104////////////////////////////////////////////////////////////////////////////
105void t_ephGPS::position(int GPSweek, double GPSweeks,
106 double* xc,
107 double* vv) const {
108
109 static const double secPerWeek = 7 * 86400.0;
110 static const double omegaEarth = 7292115.1467e-11;
111 static const double gmWGS = 398.6005e12;
112
113 memset(xc, 0, 4*sizeof(double));
114 memset(vv, 0, 3*sizeof(double));
115
116 double a0 = _sqrt_A * _sqrt_A;
117 if (a0 == 0) {
118 return;
119 }
120
121 double n0 = sqrt(gmWGS/(a0*a0*a0));
122 double tk = GPSweeks - _TOE;
123 if (GPSweek != _GPSweek) {
124 tk += (GPSweek - _GPSweek) * secPerWeek;
125 }
126 double n = n0 + _Delta_n;
127 double M = _M0 + n*tk;
128 double E = M;
129 double E_last;
130 do {
131 E_last = E;
132 E = M + _e*sin(E);
133 } while ( fabs(E-E_last)*a0 > 0.001 );
134 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
135 double u0 = v + _omega;
136 double sin2u0 = sin(2*u0);
137 double cos2u0 = cos(2*u0);
138 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
139 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
140 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
141 double xp = r*cos(u);
142 double yp = r*sin(u);
143 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
144 omegaEarth*_TOE;
145
146 double sinom = sin(OM);
147 double cosom = cos(OM);
148 double sini = sin(i);
149 double cosi = cos(i);
150 xc[0] = xp*cosom - yp*cosi*sinom;
151 xc[1] = xp*sinom + yp*cosi*cosom;
152 xc[2] = yp*sini;
153
154 double tc = GPSweeks - _TOC;
155 if (GPSweek != _GPSweek) {
156 tc += (GPSweek - _GPSweek) * secPerWeek;
157 }
158 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
159
160 // Velocity
161 // --------
162 double tanv2 = tan(v/2);
163 double dEdM = 1 / (1 - _e*cos(E));
164 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
165 * dEdM * n;
166 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
167 double dotom = _OMEGADOT - omegaEarth;
168 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
169 double dotr = a0 * _e*sin(E) * dEdM * n
170 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
171 double dotx = dotr*cos(u) - r*sin(u)*dotu;
172 double doty = dotr*sin(u) + r*cos(u)*dotu;
173
174 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
175 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
176 + yp*sini*sinom*doti; // dX / di
177
178 vv[1] = sinom *dotx + cosi*cosom *doty
179 + xp*cosom*dotom - yp*cosi*sinom*dotom
180 - yp*sini*cosom*doti;
181
182 vv[2] = sini *doty + yp*cosi *doti;
183
184 // Relativistic Correction
185 // -----------------------
186 // xc(4) -= 4.442807633e-10 * _e * sqrt(a0) *sin(E);
187 xc[3] -= 2.0 * (xc[0]*vv[0] + xc[1]*vv[1] + xc[2]*vv[2]) / t_CST::c / t_CST::c;
188}
189
190// build up RTCM3 for GPS
191////////////////////////////////////////////////////////////////////////////
192#define GPSTOINT(type, value) static_cast<type>(NearestInt(value,0))
193
194#define GPSADDBITS(a, b) {bitbuffer = (bitbuffer<<(a)) \
195 |(GPSTOINT(long long,b)&((1ULL<<a)-1)); \
196 numbits += (a); \
197 while(numbits >= 8) { \
198 buffer[size++] = bitbuffer>>(numbits-8);numbits -= 8;}}
199#define GPSADDBITSFLOAT(a,b,c) {long long i = GPSTOINT(long long,(b)/(c)); \
200 GPSADDBITS(a,i)};
201
202int t_ephGPS::RTCM3(unsigned char *buffer)
203{
204
205 unsigned char *startbuffer = buffer;
206 buffer= buffer+3;
207 int size = 0;
208 int numbits = 0;
209 unsigned long long bitbuffer = 0;
210 if (_ura <= 2.40){
211 _ura = 0;
212 }
213 else if (_ura <= 3.40){
214 _ura = 1;
215 }
216 else if (_ura <= 6.85){
217 _ura = 2;
218 }
219 else if (_ura <= 9.65){
220 _ura = 3;
221 }
222 else if (_ura <= 13.65){
223 _ura = 4;
224 }
225 else if (_ura <= 24.00){
226 _ura = 5;
227 }
228 else if (_ura <= 48.00){
229 _ura = 6;
230 }
231 else if (_ura <= 96.00){
232 _ura = 7;
233 }
234 else if (_ura <= 192.00){
235 _ura = 8;
236 }
237 else if (_ura <= 384.00){
238 _ura = 9;
239 }
240 else if (_ura <= 768.00){
241 _ura = 10;
242 }
243 else if (_ura <= 1536.00){
244 _ura = 11;
245 }
246 else if (_ura <= 1536.00){
247 _ura = 12;
248 }
249 else if (_ura <= 2072.00){
250 _ura = 13;
251 }
252 else if (_ura <= 6144.00){
253 _ura = 14;
254 }
255 else{
256 _ura = 15;
257 }
258
259 GPSADDBITS(12, 1019)
260 GPSADDBITS(6,_prn.right((_prn.length()-1)).toInt())
261 GPSADDBITS(10, _GPSweek)
262 GPSADDBITS(4, _ura)
263 GPSADDBITS(2,_L2Codes)
264 GPSADDBITSFLOAT(14, _IDOT, PI/static_cast<double>(1<<30)
265 /static_cast<double>(1<<13))
266 GPSADDBITS(8, _IODE)
267 GPSADDBITS(16, static_cast<int>(_TOC)>>4)
268 GPSADDBITSFLOAT(8, _clock_driftrate, 1.0/static_cast<double>(1<<30)
269 /static_cast<double>(1<<25))
270 GPSADDBITSFLOAT(16, _clock_drift, 1.0/static_cast<double>(1<<30)
271 /static_cast<double>(1<<13))
272 GPSADDBITSFLOAT(22, _clock_bias, 1.0/static_cast<double>(1<<30)
273 /static_cast<double>(1<<1))
274 GPSADDBITS(10, _IODC)
275 GPSADDBITSFLOAT(16, _Crs, 1.0/static_cast<double>(1<<5))
276 GPSADDBITSFLOAT(16, _Delta_n, PI/static_cast<double>(1<<30)
277 /static_cast<double>(1<<13))
278 GPSADDBITSFLOAT(32, _M0, PI/static_cast<double>(1<<30)/static_cast<double>(1<<1))
279 GPSADDBITSFLOAT(16, _Cuc, 1.0/static_cast<double>(1<<29))
280 GPSADDBITSFLOAT(32, _e, 1.0/static_cast<double>(1<<30)/static_cast<double>(1<<3))
281 GPSADDBITSFLOAT(16, _Cus, 1.0/static_cast<double>(1<<29))
282 GPSADDBITSFLOAT(32, _sqrt_A, 1.0/static_cast<double>(1<<19))
283 GPSADDBITS(16, static_cast<int>(_TOE)>>4)
284 GPSADDBITSFLOAT(16, _Cic, 1.0/static_cast<double>(1<<29))
285 GPSADDBITSFLOAT(32, _OMEGA0, PI/static_cast<double>(1<<30)
286 /static_cast<double>(1<<1))
287 GPSADDBITSFLOAT(16, _Cis, 1.0/static_cast<double>(1<<29))
288 GPSADDBITSFLOAT(32, _i0, PI/static_cast<double>(1<<30)/static_cast<double>(1<<1))
289 GPSADDBITSFLOAT(16, _Crc, 1.0/static_cast<double>(1<<5))
290 GPSADDBITSFLOAT(32, _omega, PI/static_cast<double>(1<<30)
291 /static_cast<double>(1<<1))
292 GPSADDBITSFLOAT(24, _OMEGADOT, PI/static_cast<double>(1<<30)
293 /static_cast<double>(1<<13))
294 GPSADDBITSFLOAT(8, _TGD, 1.0/static_cast<double>(1<<30)/static_cast<double>(1<<1))
295 GPSADDBITS(6, _health)
296 GPSADDBITS(1, _L2PFlag)
297 GPSADDBITS(1, 0) /* GPS fit interval */
298
299 startbuffer[0]=0xD3;
300 startbuffer[1]=(size >> 8);
301 startbuffer[2]=size;
302 unsigned long i = CRC24(size+3, startbuffer);
303 buffer[size++] = i >> 16;
304 buffer[size++] = i >> 8;
305 buffer[size++] = i;
306 size += 3;
307 return size;
308}
309
310// Derivative of the state vector using a simple force model (static)
311////////////////////////////////////////////////////////////////////////////
312ColumnVector t_ephGlo::glo_deriv(double /* tt */, const ColumnVector& xv,
313 double* acc) {
314
315 // State vector components
316 // -----------------------
317 ColumnVector rr = xv.rows(1,3);
318 ColumnVector vv = xv.rows(4,6);
319
320 // Acceleration
321 // ------------
322 static const double GM = 398.60044e12;
323 static const double AE = 6378136.0;
324 static const double OMEGA = 7292115.e-11;
325 static const double C20 = -1082.6257e-6;
326
327 double rho = rr.norm_Frobenius();
328 double t1 = -GM/(rho*rho*rho);
329 double t2 = 3.0/2.0 * C20 * (GM*AE*AE) / (rho*rho*rho*rho*rho);
330 double t3 = OMEGA * OMEGA;
331 double t4 = 2.0 * OMEGA;
332 double z2 = rr(3) * rr(3);
333
334 // Vector of derivatives
335 // ---------------------
336 ColumnVector va(6);
337 va(1) = vv(1);
338 va(2) = vv(2);
339 va(3) = vv(3);
340 va(4) = (t1 + t2*(1.0-5.0*z2/(rho*rho)) + t3) * rr(1) + t4*vv(2) + acc[0];
341 va(5) = (t1 + t2*(1.0-5.0*z2/(rho*rho)) + t3) * rr(2) - t4*vv(1) + acc[1];
342 va(6) = (t1 + t2*(3.0-5.0*z2/(rho*rho)) ) * rr(3) + acc[2];
343
344 return va;
345}
346
347// Compute Glonass Satellite Position (virtual)
348////////////////////////////////////////////////////////////////////////////
349void t_ephGlo::position(int GPSweek, double GPSweeks,
350 double* xc, double* vv) const {
351
352 static const double secPerWeek = 7 * 86400.0;
353 static const double nominalStep = 10.0;
354
355 memset(xc, 0, 4*sizeof(double));
356 memset(vv, 0, 3*sizeof(double));
357
358 double dtPos = GPSweeks - _tt;
359 if (GPSweek != _GPSweek) {
360 dtPos += (GPSweek - _GPSweek) * secPerWeek;
361 }
362
363 int nSteps = int(fabs(dtPos) / nominalStep) + 1;
364 double step = dtPos / nSteps;
365
366 double acc[3];
367 acc[0] = _x_acceleration * 1.e3;
368 acc[1] = _y_acceleration * 1.e3;
369 acc[2] = _z_acceleration * 1.e3;
370 for (int ii = 1; ii <= nSteps; ii++) {
371 _xv = rungeKutta4(_tt, _xv, step, acc, glo_deriv);
372 _tt += step;
373 }
374
375 // Position and Velocity
376 // ---------------------
377 xc[0] = _xv(1);
378 xc[1] = _xv(2);
379 xc[2] = _xv(3);
380
381 vv[0] = _xv(4);
382 vv[1] = _xv(5);
383 vv[2] = _xv(6);
384
385 // Clock Correction
386 // ----------------
387 double dtClk = GPSweeks - _GPSweeks;
388 if (GPSweek != _GPSweek) {
389 dtClk += (GPSweek - _GPSweek) * secPerWeek;
390 }
391 xc[3] = -_tau + _gamma * dtClk;
392}
393
394// IOD of Glonass Ephemeris (virtual)
395////////////////////////////////////////////////////////////////////////////
396int t_ephGlo::IOD() const {
397
398 bool old = false;
399
400 if (old) { // 5 LSBs of iod are equal to 5 LSBs of tb
401 unsigned int tb = int(fmod(_GPSweeks,86400.0)); //sec of day
402 const int shift = sizeof(tb) * 8 - 5;
403 unsigned int iod = tb << shift;
404 return (iod >> shift);
405 }
406 else {
407 bncTime tGPS(_GPSweek, _GPSweeks);
408 int hlpWeek = _GPSweek;
409 int hlpSec = int(_GPSweeks);
410 int hlpMsec = int(_GPSweeks * 1000);
411 updatetime(&hlpWeek, &hlpSec, hlpMsec, 0);
412 bncTime tHlp(hlpWeek, hlpSec);
413 double diffSec = tGPS - tHlp;
414 bncTime tMoscow = tGPS + diffSec;
415 return int(tMoscow.daysec() / 900);
416 }
417}
418
419// Set Glonass Ephemeris
420////////////////////////////////////////////////////////////////////////////
421void t_ephGlo::set(const glonassephemeris* ee) {
422
423 _prn = QString("R%1").arg(ee->almanac_number, 2, 10, QChar('0'));
424
425 int ww = ee->GPSWeek;
426 int tow = ee->GPSTOW;
427 updatetime(&ww, &tow, ee->tb*1000, 0); // Moscow -> GPS
428
429 // Check the day once more
430 // -----------------------
431 {
432 const double secPerDay = 24 * 3600.0;
433 const double secPerWeek = 7 * secPerDay;
434 int ww_old = ww;
435 int tow_old = tow;
436 int currentWeek;
437 double currentSec;
438 currentGPSWeeks(currentWeek, currentSec);
439 bncTime currentTime(currentWeek, currentSec);
440 bncTime hTime(ww, (double) tow);
441
442 bool changed = false;
443 if (hTime - currentTime > secPerDay/2.0) {
444 changed = true;
445 tow -= secPerDay;
446 if (tow < 0) {
447 tow += secPerWeek;
448 ww -= 1;
449 }
450 }
451 else if (hTime - currentTime < -secPerDay/2.0) {
452 changed = true;
453 tow += secPerDay;
454 if (tow > secPerWeek) {
455 tow -= secPerWeek;
456 ww += 1;
457 }
458 }
459
460 if (changed && ((bncApp*) qApp)->mode() == bncApp::batchPostProcessing) {
461 bncTime newHTime(ww, (double) tow);
462 cout << "GLONASS " << ee->almanac_number << " Time Changed at "
463 << currentTime.datestr() << " " << currentTime.timestr()
464 << endl
465 << "old: " << hTime.datestr() << " " << hTime.timestr()
466 << endl
467 << "new: " << newHTime.datestr() << " " << newHTime.timestr()
468 << endl
469 << "eph: " << ee->GPSWeek << " " << ee->GPSTOW << " " << ee->tb
470 << endl
471 << "ww, tow (old): " << ww_old << " " << tow_old
472 << endl
473 << "ww, tow (new): " << ww << " " << tow
474 << endl << endl;
475 }
476 }
477
478 bncTime hlpTime(ww, (double) tow);
479 unsigned year, month, day;
480 hlpTime.civil_date(year, month, day);
481 _gps_utc = gnumleap(year, month, day);
482
483 _GPSweek = ww;
484 _GPSweeks = tow;
485 _E = ee->E;
486 _tau = ee->tau;
487 _gamma = ee->gamma;
488 _x_pos = ee->x_pos;
489 _x_velocity = ee->x_velocity;
490 _x_acceleration = ee->x_acceleration;
491 _y_pos = ee->y_pos;
492 _y_velocity = ee->y_velocity;
493 _y_acceleration = ee->y_acceleration;
494 _z_pos = ee->z_pos;
495 _z_velocity = ee->z_velocity;
496 _z_acceleration = ee->z_acceleration;
497 _health = 0;
498 _frequency_number = ee->frequency_number;
499 _tki = ee->tk-3*60*60; if (_tki < 0) _tki += 86400;
500
501 // Initialize status vector
502 // ------------------------
503 _tt = _GPSweeks;
504
505 _xv(1) = _x_pos * 1.e3;
506 _xv(2) = _y_pos * 1.e3;
507 _xv(3) = _z_pos * 1.e3;
508 _xv(4) = _x_velocity * 1.e3;
509 _xv(5) = _y_velocity * 1.e3;
510 _xv(6) = _z_velocity * 1.e3;
511}
512
513// build up RTCM3 for GLONASS
514////////////////////////////////////////////////////////////////////////////
515#define GLONASSTOINT(type, value) static_cast<type>(NearestInt(value,0))
516
517#define GLONASSADDBITS(a, b) {bitbuffer = (bitbuffer<<(a)) \
518 |(GLONASSTOINT(long long,b)&((1ULL<<(a))-1)); \
519 numbits += (a); \
520 while(numbits >= 8) { \
521 buffer[size++] = bitbuffer>>(numbits-8);numbits -= 8;}}
522#define GLONASSADDBITSFLOATM(a,b,c) {int s; long long i; \
523 if(b < 0.0) \
524 { \
525 s = 1; \
526 i = GLONASSTOINT(long long,(-b)/(c)); \
527 if(!i) s = 0; \
528 } \
529 else \
530 { \
531 s = 0; \
532 i = GLONASSTOINT(long long,(b)/(c)); \
533 } \
534 GLONASSADDBITS(1,s) \
535 GLONASSADDBITS(a-1,i)}
536
537int t_ephGlo::RTCM3(unsigned char *buffer)
538{
539
540 int size = 0;
541 int numbits = 0;
542 long long bitbuffer = 0;
543 unsigned char *startbuffer = buffer;
544 buffer= buffer+3;
545
546 GLONASSADDBITS(12, 1020)
547 GLONASSADDBITS(6, _prn.right((_prn.length()-1)).toInt())
548 GLONASSADDBITS(5, 7+_frequency_number)
549 GLONASSADDBITS(1, 0)
550 GLONASSADDBITS(1, 0)
551 GLONASSADDBITS(2, 0)
552 _tki=_tki+3*60*60;
553 GLONASSADDBITS(5, static_cast<int>(_tki)/(60*60))
554 GLONASSADDBITS(6, (static_cast<int>(_tki)/60)%60)
555 GLONASSADDBITS(1, (static_cast<int>(_tki)/30)%30)
556 GLONASSADDBITS(1, _health)
557 GLONASSADDBITS(1, 0)
558 unsigned long long timeofday = (static_cast<int>(_tt+3*60*60-_gps_utc)%86400);
559 GLONASSADDBITS(7, timeofday/60/15)
560 GLONASSADDBITSFLOATM(24, _x_velocity*1000, 1000.0/static_cast<double>(1<<20))
561 GLONASSADDBITSFLOATM(27, _x_pos*1000, 1000.0/static_cast<double>(1<<11))
562 GLONASSADDBITSFLOATM(5, _x_acceleration*1000, 1000.0/static_cast<double>(1<<30))
563 GLONASSADDBITSFLOATM(24, _y_velocity*1000, 1000.0/static_cast<double>(1<<20))
564 GLONASSADDBITSFLOATM(27, _y_pos*1000, 1000.0/static_cast<double>(1<<11))
565 GLONASSADDBITSFLOATM(5, _y_acceleration*1000, 1000.0/static_cast<double>(1<<30))
566 GLONASSADDBITSFLOATM(24, _z_velocity*1000, 1000.0/static_cast<double>(1<<20))
567 GLONASSADDBITSFLOATM(27,_z_pos*1000, 1000.0/static_cast<double>(1<<11))
568 GLONASSADDBITSFLOATM(5, _z_acceleration*1000, 1000.0/static_cast<double>(1<<30))
569 GLONASSADDBITS(1, 0)
570 GLONASSADDBITSFLOATM(11, _gamma, 1.0/static_cast<double>(1<<30)
571 /static_cast<double>(1<<10))
572 GLONASSADDBITS(2, 0) /* GLONASS-M P */
573 GLONASSADDBITS(1, 0) /* GLONASS-M ln(3) */
574 GLONASSADDBITSFLOATM(22, _tau, 1.0/static_cast<double>(1<<30))
575 GLONASSADDBITS(5, 0) /* GLONASS-M delta tau */
576 GLONASSADDBITS(5, _E)
577 GLONASSADDBITS(1, 0) /* GLONASS-M P4 */
578 GLONASSADDBITS(4, 0) /* GLONASS-M FT */
579 GLONASSADDBITS(11, 0) /* GLONASS-M NT */
580 GLONASSADDBITS(2, 0) /* GLONASS-M active? */
581 GLONASSADDBITS(1, 0) /* GLONASS additional data */
582 GLONASSADDBITS(11, 0) /* GLONASS NA */
583 GLONASSADDBITS(32, 0) /* GLONASS tau C */
584 GLONASSADDBITS(5, 0) /* GLONASS-M N4 */
585 GLONASSADDBITS(22, 0) /* GLONASS-M tau GPS */
586 GLONASSADDBITS(1, 0) /* GLONASS-M ln(5) */
587 GLONASSADDBITS(7, 0) /* Reserved */
588
589 startbuffer[0]=0xD3;
590 startbuffer[1]=(size >> 8);
591 startbuffer[2]=size;
592 unsigned long i = CRC24(size+3, startbuffer);
593 buffer[size++] = i >> 16;
594 buffer[size++] = i >> 8;
595 buffer[size++] = i;
596 size += 3;
597 return size;
598}
599
600// Set Galileo Satellite Position
601////////////////////////////////////////////////////////////////////////////
602void t_ephGal::set(const galileoephemeris* ee) {
603
604 _prn = QString("E%1").arg(ee->satellite, 2, 10, QChar('0'));
605
606 _GPSweek = ee->Week;
607 _GPSweeks = ee->TOE;
608
609 _TOC = ee->TOC;
610 _TOE = ee->TOE;
611 _IODnav = ee->IODnav;
612
613 _clock_bias = ee->clock_bias ;
614 _clock_drift = ee->clock_drift ;
615 _clock_driftrate = ee->clock_driftrate;
616
617 _Crs = ee->Crs;
618 _Delta_n = ee->Delta_n;
619 _M0 = ee->M0;
620 _Cuc = ee->Cuc;
621 _e = ee->e;
622 _Cus = ee->Cus;
623 _sqrt_A = ee->sqrt_A;
624 _Cic = ee->Cic;
625 _OMEGA0 = ee->OMEGA0;
626 _Cis = ee->Cis;
627 _i0 = ee->i0;
628 _Crc = ee->Crc;
629 _omega = ee->omega;
630 _OMEGADOT = ee->OMEGADOT;
631 _IDOT = ee->IDOT;
632}
633
634// Compute Galileo Satellite Position (virtual)
635////////////////////////////////////////////////////////////////////////////
636void t_ephGal::position(int GPSweek, double GPSweeks,
637 double* xc,
638 double* vv) const {
639
640 static const double secPerWeek = 7 * 86400.0;
641 static const double omegaEarth = 7292115.1467e-11;
642 static const double gmWGS = 398.6005e12;
643
644 memset(xc, 0, 4*sizeof(double));
645 memset(vv, 0, 3*sizeof(double));
646
647 double a0 = _sqrt_A * _sqrt_A;
648 if (a0 == 0) {
649 return;
650 }
651
652 double n0 = sqrt(gmWGS/(a0*a0*a0));
653 double tk = GPSweeks - _TOE;
654 if (GPSweek != _GPSweek) {
655 tk += (GPSweek - _GPSweek) * secPerWeek;
656 }
657 double n = n0 + _Delta_n;
658 double M = _M0 + n*tk;
659 double E = M;
660 double E_last;
661 do {
662 E_last = E;
663 E = M + _e*sin(E);
664 } while ( fabs(E-E_last)*a0 > 0.001 );
665 double v = 2.0*atan( sqrt( (1.0 + _e)/(1.0 - _e) )*tan( E/2 ) );
666 double u0 = v + _omega;
667 double sin2u0 = sin(2*u0);
668 double cos2u0 = cos(2*u0);
669 double r = a0*(1 - _e*cos(E)) + _Crc*cos2u0 + _Crs*sin2u0;
670 double i = _i0 + _IDOT*tk + _Cic*cos2u0 + _Cis*sin2u0;
671 double u = u0 + _Cuc*cos2u0 + _Cus*sin2u0;
672 double xp = r*cos(u);
673 double yp = r*sin(u);
674 double OM = _OMEGA0 + (_OMEGADOT - omegaEarth)*tk -
675 omegaEarth*_TOE;
676
677 double sinom = sin(OM);
678 double cosom = cos(OM);
679 double sini = sin(i);
680 double cosi = cos(i);
681 xc[0] = xp*cosom - yp*cosi*sinom;
682 xc[1] = xp*sinom + yp*cosi*cosom;
683 xc[2] = yp*sini;
684
685 double tc = GPSweeks - _TOC;
686 if (GPSweek != _GPSweek) {
687 tc += (GPSweek - _GPSweek) * secPerWeek;
688 }
689 xc[3] = _clock_bias + _clock_drift*tc + _clock_driftrate*tc*tc;
690
691 // Velocity
692 // --------
693 double tanv2 = tan(v/2);
694 double dEdM = 1 / (1 - _e*cos(E));
695 double dotv = sqrt((1.0 + _e)/(1.0 - _e)) / cos(E/2)/cos(E/2) / (1 + tanv2*tanv2)
696 * dEdM * n;
697 double dotu = dotv + (-_Cuc*sin2u0 + _Cus*cos2u0)*2*dotv;
698 double dotom = _OMEGADOT - omegaEarth;
699 double doti = _IDOT + (-_Cic*sin2u0 + _Cis*cos2u0)*2*dotv;
700 double dotr = a0 * _e*sin(E) * dEdM * n
701 + (-_Crc*sin2u0 + _Crs*cos2u0)*2*dotv;
702 double dotx = dotr*cos(u) - r*sin(u)*dotu;
703 double doty = dotr*sin(u) + r*cos(u)*dotu;
704
705 vv[0] = cosom *dotx - cosi*sinom *doty // dX / dr
706 - xp*sinom*dotom - yp*cosi*cosom*dotom // dX / dOMEGA
707 + yp*sini*sinom*doti; // dX / di
708
709 vv[1] = sinom *dotx + cosi*cosom *doty
710 + xp*cosom*dotom - yp*cosi*sinom*dotom
711 - yp*sini*cosom*doti;
712
713 vv[2] = sini *doty + yp*cosi *doti;
714
715 // Relativistic Correction
716 // -----------------------
717 // xc(4) -= 4.442807633e-10 * _e * sqrt(a0) *sin(E);
718 xc[3] -= 2.0 * (xc[0]*vv[0] + xc[1]*vv[1] + xc[2]*vv[2]) / t_CST::c / t_CST::c;
719}
720
721// build up RTCM3 for Galileo
722////////////////////////////////////////////////////////////////////////////
723#define GALILEOTOINT(type, value) static_cast<type>(NearestInt(value, 0))
724
725#define GALILEOADDBITS(a, b) {bitbuffer = (bitbuffer<<(a)) \
726 |(GALILEOTOINT(long long,b)&((1LL<<a)-1)); \
727 numbits += (a); \
728 while(numbits >= 8) { \
729 buffer[size++] = bitbuffer>>(numbits-8);numbits -= 8;}}
730#define GALILEOADDBITSFLOAT(a,b,c) {long long i = GALILEOTOINT(long long,(b)/(c)); \
731 GALILEOADDBITS(a,i)};
732
733int t_ephGal::RTCM3(unsigned char *buffer) {
734 int size = 0;
735 int numbits = 0;
736 long long bitbuffer = 0;
737 unsigned char *startbuffer = buffer;
738 buffer= buffer+3;
739
740 GALILEOADDBITS(12, /*inav ? 1046 :*/ 1045)
741 GALILEOADDBITS(6, _prn.right((_prn.length()-1)).toInt())
742 GALILEOADDBITS(12, _GPSweek)
743 GALILEOADDBITS(10, _IODnav)
744 GALILEOADDBITS(8, _SISA)
745 GALILEOADDBITSFLOAT(14, _IDOT, PI/static_cast<double>(1<<30)
746 /static_cast<double>(1<<13))
747 GALILEOADDBITS(14, _TOC/60)
748 GALILEOADDBITSFLOAT(6, _clock_driftrate, 1.0/static_cast<double>(1<<30)
749 /static_cast<double>(1<<29))
750 GALILEOADDBITSFLOAT(21, _clock_drift, 1.0/static_cast<double>(1<<30)
751 /static_cast<double>(1<<16))
752 GALILEOADDBITSFLOAT(31, _clock_bias, 1.0/static_cast<double>(1<<30)
753 /static_cast<double>(1<<4))
754 GALILEOADDBITSFLOAT(16, _Crs, 1.0/static_cast<double>(1<<5))
755 GALILEOADDBITSFLOAT(16, _Delta_n, PI/static_cast<double>(1<<30)
756 /static_cast<double>(1<<13))
757 GALILEOADDBITSFLOAT(32, _M0, PI/static_cast<double>(1<<30)/static_cast<double>(1<<1))
758 GALILEOADDBITSFLOAT(16, _Cuc, 1.0/static_cast<double>(1<<29))
759 GALILEOADDBITSFLOAT(32, _e, 1.0/static_cast<double>(1<<30)/static_cast<double>(1<<3))
760 GALILEOADDBITSFLOAT(16, _Cus, 1.0/static_cast<double>(1<<29))
761 GALILEOADDBITSFLOAT(32, _sqrt_A, 1.0/static_cast<double>(1<<19))
762 GALILEOADDBITS(14, _TOE/60)
763 GALILEOADDBITSFLOAT(16, _Cic, 1.0/static_cast<double>(1<<29))
764 GALILEOADDBITSFLOAT(32, _OMEGA0, PI/static_cast<double>(1<<30)
765 /static_cast<double>(1<<1))
766 GALILEOADDBITSFLOAT(16, _Cis, 1.0/static_cast<double>(1<<29))
767 GALILEOADDBITSFLOAT(32, _i0, PI/static_cast<double>(1<<30)/static_cast<double>(1<<1))
768 GALILEOADDBITSFLOAT(16, _Crc, 1.0/static_cast<double>(1<<5))
769 GALILEOADDBITSFLOAT(32, _omega, PI/static_cast<double>(1<<30)
770 /static_cast<double>(1<<1))
771 GALILEOADDBITSFLOAT(24, _OMEGADOT, PI/static_cast<double>(1<<30)
772 /static_cast<double>(1<<13))
773 GALILEOADDBITSFLOAT(10, _BGD_1_5A, 1.0/static_cast<double>(1<<30)
774 /static_cast<double>(1<<2))
775 /*if(inav)
776 {
777 GALILEOADDBITSFLOAT(10, _BGD_1_5B, 1.0/static_cast<double>(1<<30)
778 /static_cast<double>(1<<2))
779 GALILEOADDBITS(2, _E5bHS)
780 GALILEOADDBITS(1, flags & MNFGALEPHF_E5BDINVALID)
781 }
782 else*/
783 {
784 GALILEOADDBITS(2, _E5aHS)
785 GALILEOADDBITS(1, /*flags & MNFGALEPHF_E5ADINVALID*/0)
786 }
787 _TOE = 0.9999E9;
788 GALILEOADDBITS(20, _TOE)
789
790 GALILEOADDBITS(/*inav ? 1 :*/ 3, 0) /* fill up */
791
792 startbuffer[0]=0xD3;
793 startbuffer[1]=(size >> 8);
794 startbuffer[2]=size;
795 unsigned long i = CRC24(size+3, startbuffer);
796 buffer[size++] = i >> 16;
797 buffer[size++] = i >> 8;
798 buffer[size++] = i;
799 size += 3;
800 return size;
801}
Note: See TracBrowser for help on using the repository browser.