00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00043
00044
00045 #ifndef _GPSPARSER_H_
00046 #define _GPSPARSER_H_
00047
00048 #include <cmath>
00049
00050 #include "../OpenTracker.h"
00051
00064
00065
00066
00067
00068
00069 #define UTM_NO_ERROR 0x0000
00070 #define UTM_LAT_ERROR 0x0001
00071 #define UTM_LON_ERROR 0x0002
00072 #define UTM_EASTING_ERROR 0x0004
00073 #define UTM_NORTHING_ERROR 0x0008
00074 #define UTM_ZONE_ERROR 0x0010
00075 #define UTM_HEMISPHERE_ERROR 0x0020
00076 #define UTM_ZONE_OVERRIDE_ERROR 0x0040
00077 #define UTM_A_ERROR 0x0080
00078 #define UTM_INV_F_ERROR 0x0100
00079
00080
00081
00082
00083
00084
00085
00086
00087 #define TRANMERC_NO_ERROR 0x0000
00088 #define TRANMERC_LAT_ERROR 0x0001
00089 #define TRANMERC_LON_ERROR 0x0002
00090 #define TRANMERC_EASTING_ERROR 0x0004
00091 #define TRANMERC_NORTHING_ERROR 0x0008
00092 #define TRANMERC_ORIGIN_LAT_ERROR 0x0010
00093 #define TRANMERC_CENT_MER_ERROR 0x0020
00094 #define TRANMERC_A_ERROR 0x0040
00095 #define TRANMERC_INV_F_ERROR 0x0080
00096 #define TRANMERC_SCALE_FACTOR_ERROR 0x0100
00097 #define TRANMERC_LON_WARNING 0x0200
00098
00099
00100 #define PI 3.14159265358979323e0
00101 #define PI_OVER (PI/2.0e0)
00102 #define MAX_LAT ((PI * 89.99)/180.0)
00103 #define MAX_DELTA_LONG ((PI * 90)/180.0)
00104 #define MIN_SCALE_FACTOR 0.3
00105 #define MAX_SCALE_FACTOR 3.0
00106
00107
00108 #define MIN_LAT ( (-80.5 * PI) / 180.0 )
00109 #define MIN_EASTING 100000
00110 #define MAX_EASTING 900000
00111 #define MIN_NORTHING 0
00112 #define MAX_NORTHING 10000000
00113
00114
00115
00116 #define SPHTMD(lat) ((double) (TranMerc_ap * lat \
00117 - TranMerc_bp * sin(2.e0 * lat) + TranMerc_cp * sin(4.e0 * lat) \
00118 - TranMerc_dp * sin(6.e0 * lat) + TranMerc_ep * sin(8.e0 * lat) ) )
00119
00120 #define SPHSN(lat) ((double) (TranMerc_a / sqrt( 1.e0 - TranMerc_es * \
00121 pow(sin(lat), 2))))
00122
00123 #define SPHSR(lat) ((double) (TranMerc_a * (1.e0 - TranMerc_es) / \
00124 pow(DENOM(lat), 3)))
00125
00126 #define DENOM(lat) ((double) (sqrt(1.e0 - TranMerc_es * pow(sin(lat),2))))
00127
00128
00129
00130
00131
00132
00133
00134
00135 static double UTM_a = 6378137.0;
00136 static double UTM_f = 1 / 298.257223563;
00137 static long UTM_Override = 0;
00138
00139
00140 static double TranMerc_a = 6378137.0;
00141 static double TranMerc_f = 1 / 298.257223563;
00142 static double TranMerc_es = 0.0066943799901413800;
00143 static double TranMerc_ebs = 0.0067394967565869;
00144
00145
00146 static double TranMerc_Origin_Lat = 0.0;
00147 static double TranMerc_Origin_Long = 0.285070444;
00148
00149 static double TranMerc_False_Northing = -5000000.0;
00150 static double TranMerc_False_Easting = 0.0;
00151 static double TranMerc_Scale_Factor = 1.0;
00152
00153
00154
00155
00156 static double TranMerc_ap = 6367449.1458008;
00157 static double TranMerc_bp = 16038.508696861;
00158 static double TranMerc_cp = 16.832613334334;
00159 static double TranMerc_dp = 0.021984404273757;
00160 static double TranMerc_ep = 3.1148371319283e-005;
00161
00162
00163 static double TranMerc_Delta_Easting = 40000000.0;
00164 static double TranMerc_Delta_Northing = 40000000.0;
00165
00166
00167
00168
00169
00170
00171 #ifndef OT_NO_GPS_SUPPORT
00172
00173
00174
00175 #include "../misc/GeoidModel.h"
00176
00177 namespace ot {
00178
00179 class GPResult {
00180 public :
00181 enum Type {
00182 GPGGA,
00183 GPVTG,
00184 HCHDG,
00185 PGRMZ,
00186 INVALID
00187 } type;
00188
00189 GPResult() {
00190 type = GPResult::INVALID;
00191 }
00192 };
00193
00194 class GPGGA : public GPResult {
00195 public :
00196 double time;
00197 double lat;
00198 double lon;
00199 int fix;
00200 int numsats;
00201 double hdop;
00202 double altitude;
00203 double height;
00204 double diffdelay;
00205 int statid;
00206
00207
00208
00209
00210 double xECEF;
00211 double yECEF;
00212 double zECEF;
00213
00214
00215
00216
00217
00218 double lat_gk_m34;
00219 double lon_gk_m34;
00220
00221 double lat_utm_33n;
00222 double lon_utm_33n;
00223 long zone_utm_33n;
00224 char hem_utm_33n;
00225
00226
00227 double lat_bmn_34;
00228 double lon_bmn_34;
00229
00230
00231 static const GPResult * parse( const char * );
00232
00234
00235
00236
00237 void convert2ECEF(GeoidModel *geoid)
00238 {
00239 double rad_cur, gdlat, gdlon;
00240 double gdalt = altitude;
00241
00242
00243 gdlat = MathUtils::GradToRad * lat;
00244 gdlon = MathUtils::GradToRad * lon;
00245
00246
00247 rad_cur = geoid->a() /
00248 sqrt(1.0-geoid->eccSquared()*pow((sin(gdlat)),2.0));
00249
00250
00251
00252
00253 xECEF = static_cast<float>((rad_cur + gdalt) * ::cos(gdlat) * ::cos(gdlon));
00254 yECEF = static_cast<float>((rad_cur + gdalt) * ::cos(gdlat) * ::sin(gdlon));
00255 zECEF = static_cast<float>(((1.0 - geoid->eccSquared()) * rad_cur + gdalt) * ::sin(gdlat));
00256
00257
00258
00259
00260
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 long Set_Transverse_Mercator_Parameters(double a,
00275 double f,
00276 double Origin_Latitude,
00277 double Central_Meridian,
00278 double False_Easting,
00279 double False_Northing,
00280 double Scale_Factor)
00281
00282 {
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 double tn;
00304 double tn2;
00305 double tn3;
00306 double tn4;
00307 double tn5;
00308 double dummy_northing;
00309 double TranMerc_b;
00310 double inv_f = 1 / f;
00311 long Error_Code = TRANMERC_NO_ERROR;
00312
00313 if (a <= 0.0)
00314 {
00315 Error_Code |= TRANMERC_A_ERROR;
00316 }
00317 if ((inv_f < 250) || (inv_f > 350))
00318 {
00319 Error_Code |= TRANMERC_INV_F_ERROR;
00320 }
00321 if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT))
00322 {
00323 Error_Code |= TRANMERC_ORIGIN_LAT_ERROR;
00324 }
00325 if ((Central_Meridian < -PI) || (Central_Meridian > (2*PI)))
00326 {
00327 Error_Code |= TRANMERC_CENT_MER_ERROR;
00328 }
00329 if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR))
00330 {
00331 Error_Code |= TRANMERC_SCALE_FACTOR_ERROR;
00332 }
00333 if (!Error_Code)
00334 {
00335 TranMerc_a = a;
00336 TranMerc_f = f;
00337 TranMerc_Origin_Lat = 0;
00338 TranMerc_Origin_Long = 0;
00339 TranMerc_False_Northing = 0;
00340 TranMerc_False_Easting = 0;
00341 TranMerc_Scale_Factor = 1;
00342
00343
00344 TranMerc_es = 2 * TranMerc_f - TranMerc_f * TranMerc_f;
00345
00346 TranMerc_ebs = (1 / (1 - TranMerc_es)) - 1;
00347
00348 TranMerc_b = TranMerc_a * (1 - TranMerc_f);
00349
00350 tn = (TranMerc_a - TranMerc_b) / (TranMerc_a + TranMerc_b);
00351 tn2 = tn * tn;
00352 tn3 = tn2 * tn;
00353 tn4 = tn3 * tn;
00354 tn5 = tn4 * tn;
00355
00356 TranMerc_ap = TranMerc_a * (1.e0 - tn + 5.e0 * (tn2 - tn3)/4.e0
00357 + 81.e0 * (tn4 - tn5)/64.e0 );
00358 TranMerc_bp = 3.e0 * TranMerc_a * (tn - tn2 + 7.e0 * (tn3 - tn4)
00359 /8.e0 + 55.e0 * tn5/64.e0 )/2.e0;
00360 TranMerc_cp = 15.e0 * TranMerc_a * (tn2 - tn3 + 3.e0 * (tn4 - tn5 )/4.e0) /16.0;
00361 TranMerc_dp = 35.e0 * TranMerc_a * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0;
00362 TranMerc_ep = 315.e0 * TranMerc_a * (tn4 - tn5) / 512.e0;
00363 Convert_Geodetic_To_Transverse_Mercator(MAX_LAT,
00364 MAX_DELTA_LONG,
00365 &TranMerc_Delta_Easting,
00366 &TranMerc_Delta_Northing);
00367 Convert_Geodetic_To_Transverse_Mercator(0,
00368 MAX_DELTA_LONG,
00369 &TranMerc_Delta_Easting,
00370 &dummy_northing);
00371 TranMerc_Origin_Lat = Origin_Latitude;
00372 if (Central_Meridian > PI)
00373 Central_Meridian -= (2*PI);
00374 TranMerc_Origin_Long = Central_Meridian;
00375 TranMerc_False_Northing = False_Northing;
00376 TranMerc_False_Easting = False_Easting;
00377 TranMerc_Scale_Factor = Scale_Factor;
00378 }
00379 return (Error_Code);
00380 }
00381
00382
00383
00384
00385
00386 void Convert_Geodetic_To_Transverse_Mercator (double gdlat,
00387 double gdlon,
00388 double *Easting,
00389 double *Northing)
00390 {
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 double c;
00426 double c2;
00427 double c3;
00428 double c5;
00429 double c7;
00430 double dlam;
00431 double eta;
00432 double eta2;
00433 double eta3;
00434 double eta4;
00435 double s;
00436 double sn;
00437 double t;
00438 double tan2;
00439 double tan3;
00440 double tan4;
00441 double tan5;
00442 double tan6;
00443 double t1;
00444 double t2;
00445 double t3;
00446 double t4;
00447 double t5;
00448 double t6;
00449 double t7;
00450 double t8;
00451 double t9;
00452 double tmd;
00453 double tmdo;
00454 long Error_Code = TRANMERC_NO_ERROR;
00455 double temp_Origin;
00456 double temp_Long;
00457
00458
00459
00460
00461
00462
00463
00464 if ((gdlat < -MAX_LAT) || (gdlat > MAX_LAT))
00465 {
00466 Error_Code|= TRANMERC_LAT_ERROR;
00467 }
00468 if (gdlon > PI)
00469 gdlon -= (2 * PI);
00470 if ((gdlon < (TranMerc_Origin_Long - MAX_DELTA_LONG))
00471 || (gdlon > (TranMerc_Origin_Long + MAX_DELTA_LONG)))
00472 {
00473 if (gdlon < 0)
00474 temp_Long = gdlon + 2 * PI;
00475 else
00476 temp_Long = gdlon;
00477 if (TranMerc_Origin_Long < 0)
00478 temp_Origin = TranMerc_Origin_Long + 2 * PI;
00479 else
00480 temp_Origin = TranMerc_Origin_Long;
00481 if ((temp_Long < (temp_Origin - MAX_DELTA_LONG))
00482 || (temp_Long > (temp_Origin + MAX_DELTA_LONG)))
00483 Error_Code|= TRANMERC_LON_ERROR;
00484 }
00485 if (!Error_Code)
00486 {
00487
00488
00489
00490
00491 dlam = gdlon - TranMerc_Origin_Long;
00492
00493 if (fabs(dlam) > (9.0 * PI / 180))
00494 {
00495 Error_Code |= TRANMERC_LON_WARNING;
00496 }
00497
00498 if (dlam > PI)
00499 dlam -= (2 * PI);
00500 if (dlam < -PI)
00501 dlam += (2 * PI);
00502 if (fabs(dlam) < 2.e-10)
00503 dlam = 0.0;
00504
00505 s = sin(gdlat);
00506 c = cos(gdlat);
00507 c2 = c * c;
00508 c3 = c2 * c;
00509 c5 = c3 * c2;
00510 c7 = c5 * c2;
00511 t = tan (gdlat);
00512 tan2 = t * t;
00513 tan3 = tan2 * t;
00514 tan4 = tan3 * t;
00515 tan5 = tan4 * t;
00516 tan6 = tan5 * t;
00517 eta = TranMerc_ebs * c2;
00518 eta2 = eta * eta;
00519 eta3 = eta2 * eta;
00520 eta4 = eta3 * eta;
00521
00522
00523 sn = SPHSN(gdlat);
00524
00525
00526 tmd = SPHTMD(gdlat);
00527
00528
00529 tmdo = SPHTMD (TranMerc_Origin_Lat);
00530
00531
00532 t1 = (tmd - tmdo) * TranMerc_Scale_Factor;
00533 t2 = sn * s * c * TranMerc_Scale_Factor/ 2.e0;
00534 t3 = sn * s * c3 * TranMerc_Scale_Factor * (5.e0 - tan2 + 9.e0 * eta
00535 + 4.e0 * eta2) /24.e0;
00536
00537 t4 = sn * s * c5 * TranMerc_Scale_Factor * (61.e0 - 58.e0 * tan2
00538 + tan4 + 270.e0 * eta - 330.e0 * tan2 * eta + 445.e0 * eta2
00539 + 324.e0 * eta3 -680.e0 * tan2 * eta2 + 88.e0 * eta4
00540 -600.e0 * tan2 * eta3 - 192.e0 * tan2 * eta4) / 720.e0;
00541
00542 t5 = sn * s * c7 * TranMerc_Scale_Factor * (1385.e0 - 3111.e0 *
00543 tan2 + 543.e0 * tan4 - tan6) / 40320.e0;
00544
00545 *Northing = TranMerc_False_Northing + t1 + pow(dlam,2.e0) * t2
00546 + pow(dlam,4.e0) * t3 + pow(dlam,6.e0) * t4
00547 + pow(dlam,8.e0) * t5;
00548
00549
00550 t6 = sn * c * TranMerc_Scale_Factor;
00551 t7 = sn * c3 * TranMerc_Scale_Factor * (1.e0 - tan2 + eta ) /6.e0;
00552 t8 = sn * c5 * TranMerc_Scale_Factor * (5.e0 - 18.e0 * tan2 + tan4
00553 + 14.e0 * eta - 58.e0 * tan2 * eta + 13.e0 * eta2 + 4.e0 * eta3
00554 - 64.e0 * tan2 * eta2 - 24.e0 * tan2 * eta3 )/ 120.e0;
00555 t9 = sn * c7 * TranMerc_Scale_Factor * ( 61.e0 - 479.e0 * tan2
00556 + 179.e0 * tan4 - tan6 ) /5040.e0;
00557
00558 *Easting = TranMerc_False_Easting + dlam * t6 + pow(dlam,3.e0) * t7
00559 + pow(dlam,5.e0) * t8 + pow(dlam,7.e0) * t9;
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 }
00571
00572 }
00573
00574
00575
00576
00577 long Set_UTM_Parameters(double a,
00578 double f,
00579 long oride)
00580 {
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592 double inv_f = 1 / f;
00593 long Error_Code = UTM_NO_ERROR;
00594
00595 if (a <= 0.0)
00596 {
00597 Error_Code |= UTM_A_ERROR;
00598 }
00599 if ((inv_f < 250) || (inv_f > 350))
00600 {
00601 Error_Code |= UTM_INV_F_ERROR;
00602 }
00603 if ((oride < 0) || (oride > 60))
00604 {
00605 Error_Code |= UTM_ZONE_OVERRIDE_ERROR;
00606 }
00607 if (!Error_Code)
00608 {
00609 UTM_a = a;
00610 UTM_f = f;
00611 UTM_Override = oride;
00612 }
00613 return (Error_Code);
00614 }
00615
00616
00617
00618
00619 long Convert_Geodetic_To_UTM (double Latitude,
00620 double Longitude,
00621 long *Zone,
00622 char *Hemisphere,
00623 double *Easting,
00624 double *Northing)
00625 {
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 long Lat_Degrees;
00642 long Long_Degrees;
00643 long temp_zone;
00644 long Error_Code = UTM_NO_ERROR;
00645 double Origin_Latitude = 0;
00646 double Central_Meridian = 0;
00647 double False_Easting = 500000;
00648 double False_Northing = 0;
00649 double Scale = 0.9996;
00650
00651 if ((Latitude < MIN_LAT) || (Latitude > MAX_LAT))
00652 {
00653 Error_Code |= UTM_LAT_ERROR;
00654 }
00655 if ((Longitude < -PI) || (Longitude > (2*PI)))
00656 {
00657 Error_Code |= UTM_LON_ERROR;
00658 }
00659 if (!Error_Code)
00660 {
00661 if (Longitude < 0)
00662 Longitude += (2*PI) + 1.0e-10;
00663 Lat_Degrees = (long)(Latitude * 180.0 / PI);
00664 Long_Degrees = (long)(Longitude * 180.0 / PI);
00665
00666 if (Longitude < PI)
00667 temp_zone = (long)(31 + ((Longitude * 180.0 / PI) / 6.0));
00668 else
00669 temp_zone = (long)(((Longitude * 180.0 / PI) / 6.0) - 29);
00670 if (temp_zone > 60)
00671 temp_zone = 1;
00672
00673 if ((Lat_Degrees > 55) && (Lat_Degrees < 64) && (Long_Degrees > -1)
00674 && (Long_Degrees < 3))
00675 temp_zone = 31;
00676 if ((Lat_Degrees > 55) && (Lat_Degrees < 64) && (Long_Degrees > 2)
00677 && (Long_Degrees < 12))
00678 temp_zone = 32;
00679 if ((Lat_Degrees > 71) && (Long_Degrees > -1) && (Long_Degrees < 9))
00680 temp_zone = 31;
00681 if ((Lat_Degrees > 71) && (Long_Degrees > 8) && (Long_Degrees < 21))
00682 temp_zone = 33;
00683 if ((Lat_Degrees > 71) && (Long_Degrees > 20) && (Long_Degrees < 33))
00684 temp_zone = 35;
00685 if ((Lat_Degrees > 71) && (Long_Degrees > 32) && (Long_Degrees < 42))
00686 temp_zone = 37;
00687
00688 if (UTM_Override)
00689 {
00690 if ((temp_zone == 1) && (UTM_Override == 60))
00691 temp_zone = UTM_Override;
00692 else if ((temp_zone == 60) && (UTM_Override == 1))
00693 temp_zone = UTM_Override;
00694 else if (((temp_zone-1) <= UTM_Override) && (UTM_Override <= (temp_zone+1)))
00695 temp_zone = UTM_Override;
00696 else
00697 Error_Code = UTM_ZONE_OVERRIDE_ERROR;
00698 }
00699 if (!Error_Code)
00700 {
00701 if (temp_zone >= 31)
00702 Central_Meridian = (6 * temp_zone - 183) * PI / 180.0;
00703 else
00704 Central_Meridian = (6 * temp_zone + 177) * PI / 180.0;
00705 *Zone = temp_zone;
00706 if (Latitude < 0)
00707 {
00708 False_Northing = 10000000;
00709 *Hemisphere = 'S';
00710 }
00711 else
00712 *Hemisphere = 'N';
00713
00714
00715
00716
00717
00718 Set_Transverse_Mercator_Parameters(UTM_a, UTM_f, Origin_Latitude,
00719 Central_Meridian, False_Easting, False_Northing, Scale);
00720 Convert_Geodetic_To_Transverse_Mercator(Latitude, Longitude, Easting,
00721 Northing);
00722 if ((*Easting < MIN_EASTING) || (*Easting > MAX_EASTING))
00723 Error_Code = UTM_EASTING_ERROR;
00724 if ((*Northing < MIN_NORTHING) || (*Northing > MAX_NORTHING))
00725 Error_Code |= UTM_NORTHING_ERROR;
00726 }
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 return (Error_Code);
00739 }
00740
00741
00742
00743
00744
00745 protected:
00746 GPGGA(){
00747 type = GPResult::GPGGA;
00748 }
00749
00750
00751 };
00752
00753 class GPVTG : public GPResult {
00754 public :
00755 double trueCourse;
00756 double magneticCourse;
00757 double speedKnots;
00758 double speedKlm;
00759
00760 static const GPResult * parse( const char * );
00761
00762 protected:
00763 GPVTG(){
00764 type = GPResult::GPVTG;
00765 }
00766 };
00767
00768 class HCHDG : public GPResult {
00769 public :
00770 double heading;
00771 double variation;
00772
00773 static const GPResult * parse( const char * );
00774
00775 protected:
00776 HCHDG(){
00777 type = GPResult::HCHDG;
00778 }
00779 };
00780
00781 class PGRMZ: public GPResult {
00782 public :
00783 double altitude;
00784
00785 static const GPResult * parse( const char * );
00786
00787 protected:
00788 PGRMZ(){
00789 type = GPResult::PGRMZ;
00790 }
00791 };
00792
00802 class GPSParser
00803 {
00804 public :
00805 static const GPResult * parse( const char * line );
00806 static bool checkSum( const char * line );
00807 private:
00808 GPSParser(){};
00809 static const GPResult * (*parsers[])(const char *);
00810 };
00811
00812 }
00813
00814
00815 #endif // OT_NO_GPS_SUPPORT
00816
00817
00818 #endif // !defined(_GPSPARSER_H_)
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834