source: ntrip/trunk/BNC/src/bncutils.cpp@ 7223

Last change on this file since 7223 was 7183, checked in by stuerze, 10 years ago

methods are added for the determination of the factorial and the assosiated Legendre functions

File size: 25.5 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: bncutils
30 *
31 * Purpose: Auxiliary Functions
32 *
33 * Author: L. Mervart
34 *
35 * Created: 30-Aug-2006
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
42#include <ctime>
43#include <math.h>
44
45#include <QRegExp>
46#include <QStringList>
47#include <QDateTime>
48
49#include <newmatap.h>
50
51#include "bncutils.h"
52#include "bnccore.h"
53
54using namespace std;
55
56struct leapseconds { /* specify the day of leap second */
57 int day; /* this is the day, where 23:59:59 exists 2 times */
58 int month; /* not the next day! */
59 int year;
60 int taicount;
61};
62static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
63static const struct leapseconds leap[] = {
64/*{31, 12, 1971, 10},*/
65/*{30, 06, 1972, 11},*/
66/*{31, 12, 1972, 12},*/
67/*{31, 12, 1973, 13},*/
68/*{31, 12, 1974, 14},*/
69/*{31, 12, 1975, 15},*/
70/*{31, 12, 1976, 16},*/
71/*{31, 12, 1977, 17},*/
72/*{31, 12, 1978, 18},*/
73/*{31, 12, 1979, 19},*/
74{30, 06, 1981,20},
75{30, 06, 1982,21},
76{30, 06, 1983,22},
77{30, 06, 1985,23},
78{31, 12, 1987,24},
79{31, 12, 1989,25},
80{31, 12, 1990,26},
81{30, 06, 1992,27},
82{30, 06, 1993,28},
83{30, 06, 1994,29},
84{31, 12, 1995,30},
85{30, 06, 1997,31},
86{31, 12, 1998,32},
87{31, 12, 2005,33},
88{31, 12, 2008,34},
89{30, 06, 2012,35},
90{30, 06, 2015,36},
91{0,0,0,0} /* end marker */
92};
93
94#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
95
96static int longyear(int year, int month)
97{
98 if(!(year % 4) && (!(year % 400) || (year % 100)))
99 {
100 if(!month || month == 2)
101 return 1;
102 }
103 return 0;
104}
105
106int gnumleap(int year, int month, int day)
107{
108 int ls = 0;
109 const struct leapseconds *l;
110
111 for(l = leap; l->taicount && year >= l->year; ++l)
112 {
113 if(year > l->year || month > l->month || (month == l->month && day > l->day))
114 ls = l->taicount - GPSLEAPSTART;
115 }
116 return ls;
117}
118
119/* Convert Moscow time into UTC (fixnumleap == 1) or GPS (fixnumleap == 0) */
120void updatetime(int *week, int *secOfWeek, int mSecOfWeek, bool fixnumleap)
121{
122 int y,m,d,k,l, nul;
123 unsigned int j = *week*(7*24*60*60) + *secOfWeek + 5*24*60*60+3*60*60;
124 int glo_daynumber = 0, glo_timeofday;
125 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
126 + gnumleap(y+1,1,1); ++y)
127 {
128 j -= k; glo_daynumber += l;
129 }
130 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
131 + gnumleap(y, m+1, 1); ++m)
132 {
133 j -= k; glo_daynumber += l;
134 }
135 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
136 j -= 24*60*60;
137 glo_daynumber -= 16*365+4-d;
138 nul = gnumleap(y, m, d);
139 glo_timeofday = j-nul;
140
141 // original version
142 // if(mSecOfWeek < 5*60*1000 && glo_timeofday > 23*60*60)
143 // *secOfWeek += 24*60*60;
144 // else if(glo_timeofday < 5*60 && mSecOfWeek > 23*60*60*1000)
145 // *secOfWeek -= 24*60*60;
146
147 // new version
148 if(mSecOfWeek < 4*60*60*1000 && glo_timeofday > 20*60*60)
149 *secOfWeek += 24*60*60;
150 else if(glo_timeofday < 4*60*60 && mSecOfWeek > 20*60*60*1000)
151 *secOfWeek -= 24*60*60;
152
153 *secOfWeek += mSecOfWeek/1000-glo_timeofday;
154 if(fixnumleap)
155 *secOfWeek -= nul;
156 if(*secOfWeek < 0) {*secOfWeek += 24*60*60*7; --*week; }
157 if(*secOfWeek >= 24*60*60*7) {*secOfWeek -= 24*60*60*7; ++*week; }
158}
159
160//
161////////////////////////////////////////////////////////////////////////////
162void expandEnvVar(QString& str) {
163
164 QRegExp rx("(\\$\\{.+\\})");
165
166 if (rx.indexIn(str) != -1) {
167 QStringListIterator it(rx.capturedTexts());
168 if (it.hasNext()) {
169 QString rxStr = it.next();
170 QString envVar = rxStr.mid(2,rxStr.length()-3);
171 str.replace(rxStr, qgetenv(envVar.toAscii()));
172 }
173 }
174
175}
176
177// Strip White Space
178////////////////////////////////////////////////////////////////////////////
179void stripWhiteSpace(string& str) {
180 if (!str.empty()) {
181 string::size_type beg = str.find_first_not_of(" \t\f\n\r\v");
182 string::size_type end = str.find_last_not_of(" \t\f\n\r\v");
183 if (beg > str.max_size())
184 str.erase();
185 else
186 str = str.substr(beg, end-beg+1);
187 }
188}
189
190//
191////////////////////////////////////////////////////////////////////////////
192QDateTime dateAndTimeFromGPSweek(int GPSWeek, double GPSWeeks) {
193
194 static const QDate zeroEpoch(1980, 1, 6);
195
196 QDate date(zeroEpoch);
197 QTime time(0,0,0,0);
198
199 int weekDays = int(GPSWeeks) / 86400;
200 date = date.addDays( GPSWeek * 7 + weekDays );
201 time = time.addMSecs( int( (GPSWeeks - 86400 * weekDays) * 1e3 ) );
202
203 return QDateTime(date,time);
204}
205
206//
207////////////////////////////////////////////////////////////////////////////
208void currentGPSWeeks(int& week, double& sec) {
209
210 QDateTime currDateTimeGPS;
211
212 if ( BNC_CORE->dateAndTimeGPSSet() ) {
213 currDateTimeGPS = BNC_CORE->dateAndTimeGPS();
214 }
215 else {
216 currDateTimeGPS = QDateTime::currentDateTime().toUTC();
217 QDate hlp = currDateTimeGPS.date();
218 currDateTimeGPS = currDateTimeGPS.addSecs(gnumleap(hlp.year(),
219 hlp.month(), hlp.day()));
220 }
221
222 QDate currDateGPS = currDateTimeGPS.date();
223 QTime currTimeGPS = currDateTimeGPS.time();
224
225 week = int( (double(currDateGPS.toJulianDay()) - 2444244.5) / 7 );
226
227 sec = (currDateGPS.dayOfWeek() % 7) * 24.0 * 3600.0 +
228 currTimeGPS.hour() * 3600.0 +
229 currTimeGPS.minute() * 60.0 +
230 currTimeGPS.second() +
231 currTimeGPS.msec() / 1000.0;
232}
233
234//
235////////////////////////////////////////////////////////////////////////////
236QDateTime currentDateAndTimeGPS() {
237 if ( BNC_CORE->dateAndTimeGPSSet() ) {
238 return BNC_CORE->dateAndTimeGPS();
239 }
240 else {
241 int GPSWeek;
242 double GPSWeeks;
243 currentGPSWeeks(GPSWeek, GPSWeeks);
244 return dateAndTimeFromGPSweek(GPSWeek, GPSWeeks);
245 }
246}
247
248//
249////////////////////////////////////////////////////////////////////////////
250QByteArray ggaString(const QByteArray& latitude,
251 const QByteArray& longitude,
252 const QByteArray& height,
253 const QString& ggaType) {
254
255 double lat = strtod(latitude,NULL);
256 double lon = strtod(longitude,NULL);
257 double hei = strtod(height,NULL);
258 QString sentences = "GPGGA,";
259 if (ggaType.contains("GNGGA")) {
260 sentences = "GNGGA,";
261 }
262
263 const char* flagN="N";
264 const char* flagE="E";
265 if (lon >180.) {lon=(lon-360.)*(-1.); flagE="W";}
266 if ((lon < 0.) && (lon >= -180.)) {lon=lon*(-1.); flagE="W";}
267 if (lon < -180.) {lon=(lon+360.); flagE="E";}
268 if (lat < 0.) {lat=lat*(-1.); flagN="S";}
269 QTime ttime(QDateTime::currentDateTime().toUTC().time());
270 int lat_deg = (int)lat;
271 double lat_min=(lat-lat_deg)*60.;
272 int lon_deg = (int)lon;
273 double lon_min=(lon-lon_deg)*60.;
274 int hh = 0 , mm = 0;
275 double ss = 0.0;
276 hh=ttime.hour();
277 mm=ttime.minute();
278 ss=(double)ttime.second()+0.001*ttime.msec();
279 QString gga;
280 gga += sentences;
281 gga += QString("%1%2%3,").arg((int)hh, 2, 10, QLatin1Char('0')).arg((int)mm, 2, 10, QLatin1Char('0')).arg((int)ss, 2, 10, QLatin1Char('0'));
282 gga += QString("%1%2,").arg((int)lat_deg,2, 10, QLatin1Char('0')).arg(lat_min, 7, 'f', 4, QLatin1Char('0'));
283 gga += flagN;
284 gga += QString(",%1%2,").arg((int)lon_deg,3, 10, QLatin1Char('0')).arg(lon_min, 7, 'f', 4, QLatin1Char('0'));
285 gga += flagE + QString(",1,05,1.00");
286 gga += QString(",%1,").arg(hei, 2, 'f', 1);
287 gga += QString("M,10.000,M,,");
288 int xori;
289 char XOR = 0;
290 char *Buff =gga.toAscii().data();
291 int iLen = strlen(Buff);
292 for (xori = 0; xori < iLen; xori++) {
293 XOR ^= (char)Buff[xori];
294 }
295 gga = "$" + gga + QString("*%1").arg(XOR, 2, 16, QLatin1Char('0'));
296
297 return gga.toAscii();
298}
299
300//
301////////////////////////////////////////////////////////////////////////////
302void RSW_to_XYZ(const ColumnVector& rr, const ColumnVector& vv,
303 const ColumnVector& rsw, ColumnVector& xyz) {
304
305 ColumnVector along = vv / vv.norm_Frobenius();
306 ColumnVector cross = crossproduct(rr, vv); cross /= cross.norm_Frobenius();
307 ColumnVector radial = crossproduct(along, cross);
308
309 Matrix RR(3,3);
310 RR.Column(1) = radial;
311 RR.Column(2) = along;
312 RR.Column(3) = cross;
313
314 xyz = RR * rsw;
315}
316
317// Transformation xyz --> radial, along track, out-of-plane
318////////////////////////////////////////////////////////////////////////////
319void XYZ_to_RSW(const ColumnVector& rr, const ColumnVector& vv,
320 const ColumnVector& xyz, ColumnVector& rsw) {
321
322 ColumnVector along = vv / vv.norm_Frobenius();
323 ColumnVector cross = crossproduct(rr, vv); cross /= cross.norm_Frobenius();
324 ColumnVector radial = crossproduct(along, cross);
325
326 rsw.ReSize(3);
327 rsw(1) = DotProduct(xyz, radial);
328 rsw(2) = DotProduct(xyz, along);
329 rsw(3) = DotProduct(xyz, cross);
330}
331
332// Rectangular Coordinates -> Ellipsoidal Coordinates
333////////////////////////////////////////////////////////////////////////////
334t_irc xyz2ell(const double* XYZ, double* Ell) {
335
336 const double bell = t_CST::aell*(1.0-1.0/t_CST::fInv) ;
337 const double e2 = (t_CST::aell*t_CST::aell-bell*bell)/(t_CST::aell*t_CST::aell) ;
338 const double e2c = (t_CST::aell*t_CST::aell-bell*bell)/(bell*bell) ;
339
340 double nn, ss, zps, hOld, phiOld, theta, sin3, cos3;
341
342 ss = sqrt(XYZ[0]*XYZ[0]+XYZ[1]*XYZ[1]) ;
343 zps = XYZ[2]/ss ;
344 theta = atan( (XYZ[2]*t_CST::aell) / (ss*bell) );
345 sin3 = sin(theta) * sin(theta) * sin(theta);
346 cos3 = cos(theta) * cos(theta) * cos(theta);
347
348 // Closed formula
349 Ell[0] = atan( (XYZ[2] + e2c * bell * sin3) / (ss - e2 * t_CST::aell * cos3) );
350 Ell[1] = atan2(XYZ[1],XYZ[0]) ;
351 nn = t_CST::aell/sqrt(1.0-e2*sin(Ell[0])*sin(Ell[0])) ;
352 Ell[2] = ss / cos(Ell[0]) - nn;
353
354 const int MAXITER = 100;
355 for (int ii = 1; ii <= MAXITER; ii++) {
356 nn = t_CST::aell/sqrt(1.0-e2*sin(Ell[0])*sin(Ell[0])) ;
357 hOld = Ell[2] ;
358 phiOld = Ell[0] ;
359 Ell[2] = ss/cos(Ell[0])-nn ;
360 Ell[0] = atan(zps/(1.0-e2*nn/(nn+Ell[2]))) ;
361 if ( fabs(phiOld-Ell[0]) <= 1.0e-11 && fabs(hOld-Ell[2]) <= 1.0e-5 ) {
362 return success;
363 }
364 }
365
366 return failure;
367}
368
369// Rectangular Coordinates -> North, East, Up Components
370////////////////////////////////////////////////////////////////////////////
371void xyz2neu(const double* Ell, const double* xyz, double* neu) {
372
373 double sinPhi = sin(Ell[0]);
374 double cosPhi = cos(Ell[0]);
375 double sinLam = sin(Ell[1]);
376 double cosLam = cos(Ell[1]);
377
378 neu[0] = - sinPhi*cosLam * xyz[0]
379 - sinPhi*sinLam * xyz[1]
380 + cosPhi * xyz[2];
381
382 neu[1] = - sinLam * xyz[0]
383 + cosLam * xyz[1];
384
385 neu[2] = + cosPhi*cosLam * xyz[0]
386 + cosPhi*sinLam * xyz[1]
387 + sinPhi * xyz[2];
388}
389
390// North, East, Up Components -> Rectangular Coordinates
391////////////////////////////////////////////////////////////////////////////
392void neu2xyz(const double* Ell, const double* neu, double* xyz) {
393
394 double sinPhi = sin(Ell[0]);
395 double cosPhi = cos(Ell[0]);
396 double sinLam = sin(Ell[1]);
397 double cosLam = cos(Ell[1]);
398
399 xyz[0] = - sinPhi*cosLam * neu[0]
400 - sinLam * neu[1]
401 + cosPhi*cosLam * neu[2];
402
403 xyz[1] = - sinPhi*sinLam * neu[0]
404 + cosLam * neu[1]
405 + cosPhi*sinLam * neu[2];
406
407 xyz[2] = + cosPhi * neu[0]
408 + sinPhi * neu[2];
409}
410
411//
412////////////////////////////////////////////////////////////////////////////
413double Frac (double x) {
414 return x-floor(x);
415}
416
417//
418////////////////////////////////////////////////////////////////////////////
419double Modulo (double x, double y) {
420 return y*Frac(x/y);
421}
422
423// Round to nearest integer
424////////////////////////////////////////////////////////////////////////////
425double nint(double val) {
426 return ((val < 0.0) ? -floor(fabs(val)+0.5) : floor(val+0.5));
427}
428
429//
430////////////////////////////////////////////////////////////////////////////
431int factorial(int n) {
432 if (n == 0) {
433 return 1;
434 }
435 else {
436 return (n * factorial(n - 1));
437 }
438}
439
440//
441////////////////////////////////////////////////////////////////////////////
442double associatedLegendreFunction(int n, int m, double t) {
443 double sum = 0.0;
444 int r = (int) floor((n - m) / 2);
445 for (int k = 0; k <= r; k++) {
446 sum += (pow(-1.0, (double)k) * factorial(2*n - 2*k)
447 / (factorial(k) * factorial(n-k) * factorial(n-m-2*k))
448 * pow(t, (double)n-m-2*k));
449 }
450 double fac = pow(2.0,(double) -n) * pow((1 - t*t), (double)m/2);
451 return sum *= fac;
452}
453
454
455// Jacobian XYZ --> NEU
456////////////////////////////////////////////////////////////////////////////
457void jacobiXYZ_NEU(const double* Ell, Matrix& jacobi) {
458
459 Tracer tracer("jacobiXYZ_NEU");
460
461 double sinPhi = sin(Ell[0]);
462 double cosPhi = cos(Ell[0]);
463 double sinLam = sin(Ell[1]);
464 double cosLam = cos(Ell[1]);
465
466 jacobi(1,1) = - sinPhi * cosLam;
467 jacobi(1,2) = - sinPhi * sinLam;
468 jacobi(1,3) = cosPhi;
469
470 jacobi(2,1) = - sinLam;
471 jacobi(2,2) = cosLam;
472 jacobi(2,3) = 0.0;
473
474 jacobi(3,1) = cosPhi * cosLam;
475 jacobi(3,2) = cosPhi * sinLam;
476 jacobi(3,3) = sinPhi;
477}
478
479// Jacobian Ell --> XYZ
480////////////////////////////////////////////////////////////////////////////
481void jacobiEll_XYZ(const double* Ell, Matrix& jacobi) {
482
483 Tracer tracer("jacobiEll_XYZ");
484
485 double sinPhi = sin(Ell[0]);
486 double cosPhi = cos(Ell[0]);
487 double sinLam = sin(Ell[1]);
488 double cosLam = cos(Ell[1]);
489 double hh = Ell[2];
490
491 double bell = t_CST::aell*(1.0-1.0/t_CST::fInv);
492 double e2 = (t_CST::aell*t_CST::aell-bell*bell)/(t_CST::aell*t_CST::aell) ;
493 double nn = t_CST::aell/sqrt(1.0-e2*sinPhi*sinPhi) ;
494
495 jacobi(1,1) = -(nn+hh) * sinPhi * cosLam;
496 jacobi(1,2) = -(nn+hh) * cosPhi * sinLam;
497 jacobi(1,3) = cosPhi * cosLam;
498
499 jacobi(2,1) = -(nn+hh) * sinPhi * sinLam;
500 jacobi(2,2) = (nn+hh) * cosPhi * cosLam;
501 jacobi(2,3) = cosPhi * sinLam;
502
503 jacobi(3,1) = (nn*(1.0-e2)+hh) * cosPhi;
504 jacobi(3,2) = 0.0;
505 jacobi(3,3) = sinPhi;
506}
507
508// Covariance Matrix in NEU
509////////////////////////////////////////////////////////////////////////////
510void covariXYZ_NEU(const SymmetricMatrix& QQxyz, const double* Ell,
511 SymmetricMatrix& Qneu) {
512
513 Tracer tracer("covariXYZ_NEU");
514
515 Matrix CC(3,3);
516 jacobiXYZ_NEU(Ell, CC);
517 Qneu << CC * QQxyz * CC.t();
518}
519
520// Covariance Matrix in XYZ
521////////////////////////////////////////////////////////////////////////////
522void covariNEU_XYZ(const SymmetricMatrix& QQneu, const double* Ell,
523 SymmetricMatrix& Qxyz) {
524
525 Tracer tracer("covariNEU_XYZ");
526
527 Matrix CC(3,3);
528 jacobiXYZ_NEU(Ell, CC);
529 Qxyz << CC.t() * QQneu * CC;
530}
531
532// Fourth order Runge-Kutta numerical integrator for ODEs
533////////////////////////////////////////////////////////////////////////////
534ColumnVector rungeKutta4(
535 double xi, // the initial x-value
536 const ColumnVector& yi, // vector of the initial y-values
537 double dx, // the step size for the integration
538 double* acc, // aditional acceleration
539 ColumnVector (*der)(double x, const ColumnVector& y, double* acc)
540 // A pointer to a function that computes the
541 // derivative of a function at a point (x,y)
542 ) {
543
544 ColumnVector k1 = der(xi , yi , acc) * dx;
545 ColumnVector k2 = der(xi+dx/2.0, yi+k1/2.0, acc) * dx;
546 ColumnVector k3 = der(xi+dx/2.0, yi+k2/2.0, acc) * dx;
547 ColumnVector k4 = der(xi+dx , yi+k3 , acc) * dx;
548
549 ColumnVector yf = yi + k1/6.0 + k2/3.0 + k3/3.0 + k4/6.0;
550
551 return yf;
552}
553//
554////////////////////////////////////////////////////////////////////////////
555double djul(long jj, long mm, double tt) {
556 long ii, kk;
557 double djul ;
558 if( mm <= 2 ) {
559 jj = jj - 1;
560 mm = mm + 12;
561 }
562 ii = jj/100;
563 kk = 2 - ii + ii/4;
564 djul = (365.25*jj - fmod( 365.25*jj, 1.0 )) - 679006.0;
565 djul = djul + floor( 30.6001*(mm + 1) ) + tt + kk;
566 return djul;
567}
568
569//
570////////////////////////////////////////////////////////////////////////////
571double gpjd(double second, int nweek) {
572 double deltat;
573 deltat = nweek*7.0 + second/86400.0 ;
574 return( 44244.0 + deltat) ;
575}
576
577//
578////////////////////////////////////////////////////////////////////////////
579void jdgp(double tjul, double & second, long & nweek) {
580 double deltat;
581 deltat = tjul - 44244.0 ;
582 nweek = (long) floor(deltat/7.0);
583 second = (deltat - (nweek)*7.0)*86400.0;
584}
585
586//
587////////////////////////////////////////////////////////////////////////////
588void jmt(double djul, long& jj, long& mm, double& dd) {
589 long ih, ih1, ih2 ;
590 double t1, t2, t3, t4;
591 t1 = 1.0 + djul - fmod( djul, 1.0 ) + 2400000.0;
592 t4 = fmod( djul, 1.0 );
593 ih = long( (t1 - 1867216.25)/36524.25 );
594 t2 = t1 + 1 + ih - ih/4;
595 t3 = t2 - 1720995.0;
596 ih1 = long( (t3 - 122.1)/365.25 );
597 t1 = 365.25*ih1 - fmod( 365.25*ih1, 1.0 );
598 ih2 = long( (t3 - t1)/30.6001 );
599 dd = t3 - t1 - (int)( 30.6001*ih2 ) + t4;
600 mm = ih2 - 1;
601 if ( ih2 > 13 ) mm = ih2 - 13;
602 jj = ih1;
603 if ( mm <= 2 ) jj = jj + 1;
604}
605
606//
607////////////////////////////////////////////////////////////////////////////
608void GPSweekFromDateAndTime(const QDateTime& dateTime,
609 int& GPSWeek, double& GPSWeeks) {
610
611 static const QDateTime zeroEpoch(QDate(1980, 1, 6),QTime(),Qt::UTC);
612
613 GPSWeek = zeroEpoch.daysTo(dateTime) / 7;
614
615 int weekDay = dateTime.date().dayOfWeek() + 1; // Qt: Monday = 1
616 if (weekDay > 7) weekDay = 1;
617
618 GPSWeeks = (weekDay - 1) * 86400.0
619 - dateTime.time().msecsTo(QTime()) / 1e3;
620}
621
622//
623////////////////////////////////////////////////////////////////////////////
624void GPSweekFromYMDhms(int year, int month, int day, int hour, int min,
625 double sec, int& GPSWeek, double& GPSWeeks) {
626
627 double mjd = djul(year, month, day);
628
629 long GPSWeek_long;
630 jdgp(mjd, GPSWeeks, GPSWeek_long);
631 GPSWeek = GPSWeek_long;
632 GPSWeeks += hour * 3600.0 + min * 60.0 + sec;
633}
634
635//
636////////////////////////////////////////////////////////////////////////////
637void mjdFromDateAndTime(const QDateTime& dateTime, int& mjd, double& dayfrac) {
638
639 static const QDate zeroDate(1858, 11, 17);
640
641 mjd = zeroDate.daysTo(dateTime.date());
642
643 dayfrac = (dateTime.time().hour() +
644 (dateTime.time().minute() +
645 (dateTime.time().second() +
646 dateTime.time().msec() / 1000.0) / 60.0) / 60.0) / 24.0;
647}
648
649//
650////////////////////////////////////////////////////////////////////////////
651bool findInVector(const vector<QString>& vv, const QString& str) {
652 std::vector<QString>::const_iterator it;
653 for (it = vv.begin(); it != vv.end(); ++it) {
654 if ( (*it) == str) {
655 return true;
656 }
657 }
658 return false;
659}
660
661//
662////////////////////////////////////////////////////////////////////////////
663int readInt(const QString& str, int pos, int len, int& value) {
664 bool ok;
665 value = str.mid(pos, len).toInt(&ok);
666 return ok ? 0 : 1;
667}
668
669//
670////////////////////////////////////////////////////////////////////////////
671int readDbl(const QString& str, int pos, int len, double& value) {
672 QString hlp = str.mid(pos, len);
673 for (int ii = 0; ii < hlp.length(); ii++) {
674 if (hlp[ii]=='D' || hlp[ii]=='d' || hlp[ii] == 'E') {
675 hlp[ii]='e';
676 }
677 }
678 bool ok;
679 value = hlp.toDouble(&ok);
680 return ok ? 0 : 1;
681}
682
683// Topocentrical Distance and Elevation
684////////////////////////////////////////////////////////////////////////////
685void topos(double xRec, double yRec, double zRec,
686 double xSat, double ySat, double zSat,
687 double& rho, double& eleSat, double& azSat) {
688
689 double dx[3];
690 dx[0] = xSat-xRec;
691 dx[1] = ySat-yRec;
692 dx[2] = zSat-zRec;
693
694 rho = sqrt( dx[0]*dx[0] + dx[1]*dx[1] + dx[2]*dx[2] );
695
696 double xyzRec[3];
697 xyzRec[0] = xRec;
698 xyzRec[1] = yRec;
699 xyzRec[2] = zRec;
700
701 double Ell[3];
702 double neu[3];
703 xyz2ell(xyzRec, Ell);
704 xyz2neu(Ell, dx, neu);
705
706 eleSat = acos( sqrt(neu[0]*neu[0] + neu[1]*neu[1]) / rho );
707 if (neu[2] < 0) {
708 eleSat *= -1.0;
709 }
710
711 azSat = atan2(neu[1], neu[0]);
712}
713
714// Degrees -> degrees, minutes, seconds
715////////////////////////////////////////////////////////////////////////////
716void deg2DMS(double decDeg, int& deg, int& min, double& sec) {
717 int sgn = (decDeg < 0.0 ? -1 : 1);
718 deg = sgn * static_cast<int>(decDeg);
719 min = static_cast<int>((decDeg - deg)*60);
720 sec = (decDeg - deg - min/60.0) * 3600.0;
721}
722
723//
724////////////////////////////////////////////////////////////////////////////
725QString fortranFormat(double value, int width, int prec) {
726 int expo = value == 0.0 ? 0 : int(log10(fabs(value)));
727 double mant = value == 0.0 ? 0 : value / pow(10, expo);
728 if (fabs(mant) >= 1.0) {
729 mant /= 10.0;
730 expo += 1;
731 }
732 if (expo >= 0) {
733 return QString("%1e+%2").arg(mant, width-4, 'f', prec).arg(expo, 2, 10, QChar('0'));
734 }
735 else {
736 return QString("%1e-%2").arg(mant, width-4, 'f', prec).arg(-expo, 2, 10, QChar('0'));
737 }
738}
739
740//
741//////////////////////////////////////////////////////////////////////////////
742void kalman(const Matrix& AA, const ColumnVector& ll, const DiagonalMatrix& PP,
743 SymmetricMatrix& QQ, ColumnVector& xx) {
744
745 Tracer tracer("kalman");
746
747 int nPar = AA.Ncols();
748 int nObs = AA.Nrows();
749 UpperTriangularMatrix SS = Cholesky(QQ).t();
750
751 Matrix SA = SS*AA.t();
752 Matrix SRF(nObs+nPar, nObs+nPar); SRF = 0;
753 for (int ii = 1; ii <= nObs; ++ii) {
754 SRF(ii,ii) = 1.0 / sqrt(PP(ii,ii));
755 }
756
757 SRF.SubMatrix (nObs+1, nObs+nPar, 1, nObs) = SA;
758 SRF.SymSubMatrix(nObs+1, nObs+nPar) = SS;
759
760 UpperTriangularMatrix UU;
761 QRZ(SRF, UU);
762
763 SS = UU.SymSubMatrix(nObs+1, nObs+nPar);
764 UpperTriangularMatrix SH_rt = UU.SymSubMatrix(1, nObs);
765 Matrix YY = UU.SubMatrix(1, nObs, nObs+1, nObs+nPar);
766
767 UpperTriangularMatrix SHi = SH_rt.i();
768
769 Matrix KT = SHi * YY;
770 SymmetricMatrix Hi; Hi << SHi * SHi.t();
771
772 xx += KT.t() * (ll - AA * xx);
773 QQ << (SS.t() * SS);
774}
775
776double accuracyFromIndex(int index, t_eph::e_type type) {
777
778 if (type == t_eph::GPS || type == t_eph::BDS || type == t_eph::SBAS
779 || type == t_eph::QZSS) {
780
781 if ((index >= 0) && (index <= 6)) {
782 if (index == 3) {
783 return ceil(10.0 * pow(2.0, (double(index) / 2.0) + 1.0)) / 10.0;
784 }
785 else {
786 return floor(10.0 * pow(2.0, (double(index) / 2.0) + 1.0)) / 10.0;
787 }
788 }
789 else if ((index > 6) && (index <= 15)) {
790 return (10.0 * pow(2.0, (double(index) - 2.0))) / 10.0;
791 }
792 else {
793 return 8192.0;
794 }
795 }
796
797 if (type == t_eph::Galileo) {
798
799 if ((index >= 0) && (index <= 49)) {
800 return (double(index) / 100.0);
801 }
802 else if ((index > 49) && (index <= 74)) {
803 return (50.0 + (double(index) - 50.0) * 2.0) / 100.0;
804 }
805 else if ((index > 74) && (index <= 99)) {
806 return 1.0 + (double(index) - 75.0) * 0.04;
807 }
808 else if ((index > 99) && (index <= 125)) {
809 return 2.0 + (double(index) - 100.0) * 0.16;
810 }
811 else {
812 return -1.0;
813 }
814 }
815
816 return double(index);
817}
818
819int indexFromAccuracy(double accuracy, t_eph::e_type type) {
820
821 if (type == t_eph::GPS || type == t_eph::BDS || type == t_eph::SBAS
822 || type == t_eph::QZSS) {
823
824 if (accuracy <= 2.40) {
825 return 0;
826 }
827 else if (accuracy <= 3.40) {
828 return 1;
829 }
830 else if (accuracy <= 4.85) {
831 return 2;
832 }
833 else if (accuracy <= 6.85) {
834 return 3;
835 }
836 else if (accuracy <= 9.65) {
837 return 4;
838 }
839 else if (accuracy <= 13.65) {
840 return 5;
841 }
842 else if (accuracy <= 24.00) {
843 return 6;
844 }
845 else if (accuracy <= 48.00) {
846 return 7;
847 }
848 else if (accuracy <= 96.00) {
849 return 8;
850 }
851 else if (accuracy <= 192.00) {
852 return 9;
853 }
854 else if (accuracy <= 384.00) {
855 return 10;
856 }
857 else if (accuracy <= 768.00) {
858 return 11;
859 }
860 else if (accuracy <= 1536.00) {
861 return 12;
862 }
863 else if (accuracy <= 3072.00) {
864 return 13;
865 }
866 else if (accuracy <= 6144.00) {
867 return 14;
868 }
869 else {
870 return 15;
871 }
872 }
873
874 if (type == t_eph::Galileo) {
875
876 if (accuracy <= 0.49) {
877 return int(ceil(accuracy * 100.0));
878 }
879 else if (accuracy <= 0.98) {
880 return int(50.0 + (((accuracy * 100.0) - 50) / 2.0));
881 }
882 else if (accuracy <= 2.0) {
883 return int(75.0 + ((accuracy - 1.0) / 0.04));
884 }
885 else if (accuracy <= 6.0) {
886 return int(100.0 + ((accuracy - 2.0) / 0.16));
887 }
888 else {
889 return 255;
890 }
891 }
892
893 return (type == t_eph::Galileo) ? 255 : 15;
894}
895
896// Returns CRC24
897////////////////////////////////////////////////////////////////////////////
898unsigned long CRC24(long size, const unsigned char *buf) {
899 unsigned long crc = 0;
900 int ii;
901 while (size--) {
902 crc ^= (*buf++) << (16);
903 for(ii = 0; ii < 8; ii++) {
904 crc <<= 1;
905 if (crc & 0x1000000) {
906 crc ^= 0x01864cfb;
907 }
908 }
909 }
910 return crc;
911}
912
Note: See TracBrowser for help on using the repository browser.