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

Last change on this file since 6899 was 6812, checked in by stoecker, 10 years ago

integrate RTCM3 parsing into BNC and directly fill target structures, add doxygen documentation

File size: 24.4 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// Jacobian XYZ --> NEU
430////////////////////////////////////////////////////////////////////////////
431void jacobiXYZ_NEU(const double* Ell, Matrix& jacobi) {
432
433 Tracer tracer("jacobiXYZ_NEU");
434
435 double sinPhi = sin(Ell[0]);
436 double cosPhi = cos(Ell[0]);
437 double sinLam = sin(Ell[1]);
438 double cosLam = cos(Ell[1]);
439
440 jacobi(1,1) = - sinPhi * cosLam;
441 jacobi(1,2) = - sinPhi * sinLam;
442 jacobi(1,3) = cosPhi;
443
444 jacobi(2,1) = - sinLam;
445 jacobi(2,2) = cosLam;
446 jacobi(2,3) = 0.0;
447
448 jacobi(3,1) = cosPhi * cosLam;
449 jacobi(3,2) = cosPhi * sinLam;
450 jacobi(3,3) = sinPhi;
451}
452
453// Jacobian Ell --> XYZ
454////////////////////////////////////////////////////////////////////////////
455void jacobiEll_XYZ(const double* Ell, Matrix& jacobi) {
456
457 Tracer tracer("jacobiEll_XYZ");
458
459 double sinPhi = sin(Ell[0]);
460 double cosPhi = cos(Ell[0]);
461 double sinLam = sin(Ell[1]);
462 double cosLam = cos(Ell[1]);
463 double hh = Ell[2];
464
465 double bell = t_CST::aell*(1.0-1.0/t_CST::fInv);
466 double e2 = (t_CST::aell*t_CST::aell-bell*bell)/(t_CST::aell*t_CST::aell) ;
467 double nn = t_CST::aell/sqrt(1.0-e2*sinPhi*sinPhi) ;
468
469 jacobi(1,1) = -(nn+hh) * sinPhi * cosLam;
470 jacobi(1,2) = -(nn+hh) * cosPhi * sinLam;
471 jacobi(1,3) = cosPhi * cosLam;
472
473 jacobi(2,1) = -(nn+hh) * sinPhi * sinLam;
474 jacobi(2,2) = (nn+hh) * cosPhi * cosLam;
475 jacobi(2,3) = cosPhi * sinLam;
476
477 jacobi(3,1) = (nn*(1.0-e2)+hh) * cosPhi;
478 jacobi(3,2) = 0.0;
479 jacobi(3,3) = sinPhi;
480}
481
482// Covariance Matrix in NEU
483////////////////////////////////////////////////////////////////////////////
484void covariXYZ_NEU(const SymmetricMatrix& QQxyz, const double* Ell,
485 SymmetricMatrix& Qneu) {
486
487 Tracer tracer("covariXYZ_NEU");
488
489 Matrix CC(3,3);
490 jacobiXYZ_NEU(Ell, CC);
491 Qneu << CC * QQxyz * CC.t();
492}
493
494// Covariance Matrix in XYZ
495////////////////////////////////////////////////////////////////////////////
496void covariNEU_XYZ(const SymmetricMatrix& QQneu, const double* Ell,
497 SymmetricMatrix& Qxyz) {
498
499 Tracer tracer("covariNEU_XYZ");
500
501 Matrix CC(3,3);
502 jacobiXYZ_NEU(Ell, CC);
503 Qxyz << CC.t() * QQneu * CC;
504}
505
506// Fourth order Runge-Kutta numerical integrator for ODEs
507////////////////////////////////////////////////////////////////////////////
508ColumnVector rungeKutta4(
509 double xi, // the initial x-value
510 const ColumnVector& yi, // vector of the initial y-values
511 double dx, // the step size for the integration
512 double* acc, // aditional acceleration
513 ColumnVector (*der)(double x, const ColumnVector& y, double* acc)
514 // A pointer to a function that computes the
515 // derivative of a function at a point (x,y)
516 ) {
517
518 ColumnVector k1 = der(xi , yi , acc) * dx;
519 ColumnVector k2 = der(xi+dx/2.0, yi+k1/2.0, acc) * dx;
520 ColumnVector k3 = der(xi+dx/2.0, yi+k2/2.0, acc) * dx;
521 ColumnVector k4 = der(xi+dx , yi+k3 , acc) * dx;
522
523 ColumnVector yf = yi + k1/6.0 + k2/3.0 + k3/3.0 + k4/6.0;
524
525 return yf;
526}
527//
528////////////////////////////////////////////////////////////////////////////
529double djul(long jj, long mm, double tt) {
530 long ii, kk;
531 double djul ;
532 if( mm <= 2 ) {
533 jj = jj - 1;
534 mm = mm + 12;
535 }
536 ii = jj/100;
537 kk = 2 - ii + ii/4;
538 djul = (365.25*jj - fmod( 365.25*jj, 1.0 )) - 679006.0;
539 djul = djul + floor( 30.6001*(mm + 1) ) + tt + kk;
540 return djul;
541}
542
543//
544////////////////////////////////////////////////////////////////////////////
545double gpjd(double second, int nweek) {
546 double deltat;
547 deltat = nweek*7.0 + second/86400.0 ;
548 return( 44244.0 + deltat) ;
549}
550
551//
552////////////////////////////////////////////////////////////////////////////
553void jdgp(double tjul, double & second, long & nweek) {
554 double deltat;
555 deltat = tjul - 44244.0 ;
556 nweek = (long) floor(deltat/7.0);
557 second = (deltat - (nweek)*7.0)*86400.0;
558}
559
560//
561////////////////////////////////////////////////////////////////////////////
562void jmt(double djul, long& jj, long& mm, double& dd) {
563 long ih, ih1, ih2 ;
564 double t1, t2, t3, t4;
565 t1 = 1.0 + djul - fmod( djul, 1.0 ) + 2400000.0;
566 t4 = fmod( djul, 1.0 );
567 ih = long( (t1 - 1867216.25)/36524.25 );
568 t2 = t1 + 1 + ih - ih/4;
569 t3 = t2 - 1720995.0;
570 ih1 = long( (t3 - 122.1)/365.25 );
571 t1 = 365.25*ih1 - fmod( 365.25*ih1, 1.0 );
572 ih2 = long( (t3 - t1)/30.6001 );
573 dd = t3 - t1 - (int)( 30.6001*ih2 ) + t4;
574 mm = ih2 - 1;
575 if ( ih2 > 13 ) mm = ih2 - 13;
576 jj = ih1;
577 if ( mm <= 2 ) jj = jj + 1;
578}
579
580//
581////////////////////////////////////////////////////////////////////////////
582void GPSweekFromDateAndTime(const QDateTime& dateTime,
583 int& GPSWeek, double& GPSWeeks) {
584
585 static const QDateTime zeroEpoch(QDate(1980, 1, 6),QTime(),Qt::UTC);
586
587 GPSWeek = zeroEpoch.daysTo(dateTime) / 7;
588
589 int weekDay = dateTime.date().dayOfWeek() + 1; // Qt: Monday = 1
590 if (weekDay > 7) weekDay = 1;
591
592 GPSWeeks = (weekDay - 1) * 86400.0
593 - dateTime.time().msecsTo(QTime()) / 1e3;
594}
595
596//
597////////////////////////////////////////////////////////////////////////////
598void GPSweekFromYMDhms(int year, int month, int day, int hour, int min,
599 double sec, int& GPSWeek, double& GPSWeeks) {
600
601 double mjd = djul(year, month, day);
602
603 long GPSWeek_long;
604 jdgp(mjd, GPSWeeks, GPSWeek_long);
605 GPSWeek = GPSWeek_long;
606 GPSWeeks += hour * 3600.0 + min * 60.0 + sec;
607}
608
609//
610////////////////////////////////////////////////////////////////////////////
611void mjdFromDateAndTime(const QDateTime& dateTime, int& mjd, double& dayfrac) {
612
613 static const QDate zeroDate(1858, 11, 17);
614
615 mjd = zeroDate.daysTo(dateTime.date());
616
617 dayfrac = (dateTime.time().hour() +
618 (dateTime.time().minute() +
619 (dateTime.time().second() +
620 dateTime.time().msec() / 1000.0) / 60.0) / 60.0) / 24.0;
621}
622
623//
624////////////////////////////////////////////////////////////////////////////
625bool findInVector(const vector<QString>& vv, const QString& str) {
626 std::vector<QString>::const_iterator it;
627 for (it = vv.begin(); it != vv.end(); ++it) {
628 if ( (*it) == str) {
629 return true;
630 }
631 }
632 return false;
633}
634
635//
636////////////////////////////////////////////////////////////////////////////
637int readInt(const QString& str, int pos, int len, int& value) {
638 bool ok;
639 value = str.mid(pos, len).toInt(&ok);
640 return ok ? 0 : 1;
641}
642
643//
644////////////////////////////////////////////////////////////////////////////
645int readDbl(const QString& str, int pos, int len, double& value) {
646 QString hlp = str.mid(pos, len);
647 for (int ii = 0; ii < hlp.length(); ii++) {
648 if (hlp[ii]=='D' || hlp[ii]=='d' || hlp[ii] == 'E') {
649 hlp[ii]='e';
650 }
651 }
652 bool ok;
653 value = hlp.toDouble(&ok);
654 return ok ? 0 : 1;
655}
656
657// Topocentrical Distance and Elevation
658////////////////////////////////////////////////////////////////////////////
659void topos(double xRec, double yRec, double zRec,
660 double xSat, double ySat, double zSat,
661 double& rho, double& eleSat, double& azSat) {
662
663 double dx[3];
664 dx[0] = xSat-xRec;
665 dx[1] = ySat-yRec;
666 dx[2] = zSat-zRec;
667
668 rho = sqrt( dx[0]*dx[0] + dx[1]*dx[1] + dx[2]*dx[2] );
669
670 double xyzRec[3];
671 xyzRec[0] = xRec;
672 xyzRec[1] = yRec;
673 xyzRec[2] = zRec;
674
675 double Ell[3];
676 double neu[3];
677 xyz2ell(xyzRec, Ell);
678 xyz2neu(Ell, dx, neu);
679
680 eleSat = acos( sqrt(neu[0]*neu[0] + neu[1]*neu[1]) / rho );
681 if (neu[2] < 0) {
682 eleSat *= -1.0;
683 }
684
685 azSat = atan2(neu[1], neu[0]);
686}
687
688// Degrees -> degrees, minutes, seconds
689////////////////////////////////////////////////////////////////////////////
690void deg2DMS(double decDeg, int& deg, int& min, double& sec) {
691 int sgn = (decDeg < 0.0 ? -1 : 1);
692 deg = sgn * static_cast<int>(decDeg);
693 min = static_cast<int>((decDeg - deg)*60);
694 sec = (decDeg - deg - min/60.0) * 3600.0;
695}
696
697//
698////////////////////////////////////////////////////////////////////////////
699QString fortranFormat(double value, int width, int prec) {
700 int expo = value == 0.0 ? 0 : int(log10(fabs(value)));
701 double mant = value == 0.0 ? 0 : value / pow(10, expo);
702 if (fabs(mant) >= 1.0) {
703 mant /= 10.0;
704 expo += 1;
705 }
706 if (expo >= 0) {
707 return QString("%1e+%2").arg(mant, width-4, 'f', prec).arg(expo, 2, 10, QChar('0'));
708 }
709 else {
710 return QString("%1e-%2").arg(mant, width-4, 'f', prec).arg(-expo, 2, 10, QChar('0'));
711 }
712}
713
714//
715//////////////////////////////////////////////////////////////////////////////
716void kalman(const Matrix& AA, const ColumnVector& ll, const DiagonalMatrix& PP,
717 SymmetricMatrix& QQ, ColumnVector& xx) {
718
719 Tracer tracer("kalman");
720
721 int nPar = AA.Ncols();
722 int nObs = AA.Nrows();
723 UpperTriangularMatrix SS = Cholesky(QQ).t();
724
725 Matrix SA = SS*AA.t();
726 Matrix SRF(nObs+nPar, nObs+nPar); SRF = 0;
727 for (int ii = 1; ii <= nObs; ++ii) {
728 SRF(ii,ii) = 1.0 / sqrt(PP(ii,ii));
729 }
730
731 SRF.SubMatrix (nObs+1, nObs+nPar, 1, nObs) = SA;
732 SRF.SymSubMatrix(nObs+1, nObs+nPar) = SS;
733
734 UpperTriangularMatrix UU;
735 QRZ(SRF, UU);
736
737 SS = UU.SymSubMatrix(nObs+1, nObs+nPar);
738 UpperTriangularMatrix SH_rt = UU.SymSubMatrix(1, nObs);
739 Matrix YY = UU.SubMatrix(1, nObs, nObs+1, nObs+nPar);
740
741 UpperTriangularMatrix SHi = SH_rt.i();
742
743 Matrix KT = SHi * YY;
744 SymmetricMatrix Hi; Hi << SHi * SHi.t();
745
746 xx += KT.t() * (ll - AA * xx);
747 QQ << (SS.t() * SS);
748}
749
750double accuracyFromIndex(int index, t_eph::e_type type) {
751
752 if (type == t_eph::GPS || type == t_eph::BDS || type == t_eph::SBAS
753 || type == t_eph::QZSS) {
754
755 if ((index >= 0) && (index <= 6)) {
756 if (index == 3) {
757 return ceil(10.0 * pow(2.0, (double(index) / 2.0) + 1.0)) / 10.0;
758 }
759 else {
760 return floor(10.0 * pow(2.0, (double(index) / 2.0) + 1.0)) / 10.0;
761 }
762 }
763 else if ((index > 6) && (index <= 15)) {
764 return (10.0 * pow(2.0, (double(index) - 2.0))) / 10.0;
765 }
766 else {
767 return 8192.0;
768 }
769 }
770
771 if (type == t_eph::Galileo) {
772
773 if ((index >= 0) && (index <= 49)) {
774 return (double(index) / 100.0);
775 }
776 else if ((index > 49) && (index <= 74)) {
777 return (50.0 + (double(index) - 50.0) * 2.0) / 100.0;
778 }
779 else if ((index > 74) && (index <= 99)) {
780 return 1.0 + (double(index) - 75.0) * 0.04;
781 }
782 else if ((index > 99) && (index <= 125)) {
783 return 2.0 + (double(index) - 100.0) * 0.16;
784 }
785 else {
786 return -1.0;
787 }
788 }
789
790 return double(index);
791}
792
793int indexFromAccuracy(double accuracy, t_eph::e_type type) {
794
795 if (type == t_eph::GPS || type == t_eph::BDS || type == t_eph::SBAS
796 || type == t_eph::QZSS) {
797
798 if (accuracy <= 2.40) {
799 return 0;
800 }
801 else if (accuracy <= 3.40) {
802 return 1;
803 }
804 else if (accuracy <= 4.85) {
805 return 2;
806 }
807 else if (accuracy <= 6.85) {
808 return 3;
809 }
810 else if (accuracy <= 9.65) {
811 return 4;
812 }
813 else if (accuracy <= 13.65) {
814 return 5;
815 }
816 else if (accuracy <= 24.00) {
817 return 6;
818 }
819 else if (accuracy <= 48.00) {
820 return 7;
821 }
822 else if (accuracy <= 96.00) {
823 return 8;
824 }
825 else if (accuracy <= 192.00) {
826 return 9;
827 }
828 else if (accuracy <= 384.00) {
829 return 10;
830 }
831 else if (accuracy <= 768.00) {
832 return 11;
833 }
834 else if (accuracy <= 1536.00) {
835 return 12;
836 }
837 else if (accuracy <= 3072.00) {
838 return 13;
839 }
840 else if (accuracy <= 6144.00) {
841 return 14;
842 }
843 else {
844 return 15;
845 }
846 }
847
848 if (type == t_eph::Galileo) {
849
850 if (accuracy <= 0.49) {
851 return int(ceil(accuracy * 100.0));
852 }
853 else if (accuracy <= 0.98) {
854 return int(50.0 + (((accuracy * 100.0) - 50) / 2.0));
855 }
856 else if (accuracy <= 2.0) {
857 return int(75.0 + ((accuracy - 1.0) / 0.04));
858 }
859 else if (accuracy <= 6.0) {
860 return int(100.0 + ((accuracy - 2.0) / 0.16));
861 }
862 else {
863 return 255;
864 }
865 }
866
867 return (type == t_eph::Galileo) ? 255 : 15;
868}
Note: See TracBrowser for help on using the repository browser.