GPSParser.h

Go to the documentation of this file.
00001 /* ========================================================================
00002  * Copyright (c) 2006,
00003  * Institute for Computer Graphics and Vision
00004  * Graz University of Technology
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are
00009  * met:
00010  *
00011  * Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the following disclaimer.
00013  *
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the distribution.
00017  *
00018  * Neither the name of the Graz University of Technology nor the names of
00019  * its contributors may be used to endorse or promote products derived from
00020  * this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00023  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00024  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00025  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00026  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00027  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00028  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  * ========================================================================
00034  * PROJECT: OpenTracker
00035  * ======================================================================== */
00043 /* ======================================================================= */
00044 
00045 #ifndef _GPSPARSER_H_
00046 #define _GPSPARSER_H_
00047 
00048 #include <cmath>
00049 
00050 #include "../OpenTracker.h"
00051 
00064 /***************************************************************************/
00065 /*
00066  *                              DEFINES
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 /*                               DEFINES 
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 /* PI     */
00101 #define PI_OVER         (PI/2.0e0)            /* PI over 2 */
00102 #define MAX_LAT         ((PI * 89.99)/180.0)    /* 90 degrees in radians */
00103 #define MAX_DELTA_LONG  ((PI * 90)/180.0)    /* 90 degrees in radians */
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 ) /* -80.5 degrees in radians    */
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 /*                               GLOBAL DECLARATIONS
00131  *
00132  */
00133 
00134 
00135 static double UTM_a = 6378137.0;         /* Semi-major axis of ellipsoid in meters  */
00136 static double UTM_f = 1 / 298.257223563; /* Flattening of ellipsoid                 */
00137 static long   UTM_Override = 0;          /* Zone override flag                      */
00138 
00139 /* Ellipsoid Parameters, default to WGS 84  */
00140 static double TranMerc_a = 6378137.0;              /* Semi-major axis of ellipsoid i meters */
00141 static double TranMerc_f = 1 / 298.257223563;      /* Flattening of ellipsoid  */
00142 static double TranMerc_es = 0.0066943799901413800; /* Eccentricity (0.08181919084262188000) squared */
00143 static double TranMerc_ebs = 0.0067394967565869;   /* Second Eccentricity squared */
00144 
00145 /* Transverse_Mercator projection Parameters */
00146 static double TranMerc_Origin_Lat = 0.0;           /* Latitude of origin in radians */
00147 static double TranMerc_Origin_Long = 0.285070444;  /* Longitude of origin in radians */
00148                                                                                                    /* 16 Grad 20 Minuten == 16,333333 Grad */   
00149 static double TranMerc_False_Northing = -5000000.0;/* False northing in meters */
00150 static double TranMerc_False_Easting = 0.0;        /* False easting in meters */
00151 static double TranMerc_Scale_Factor = 1.0;         /* Scale factor  */
00152 
00153 
00154 
00155 /* Isometeric to geodetic latitude parameters, default to WGS 84 */
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 /* Maximum variance for easting and northing values for WGS 84. */
00163 static double TranMerc_Delta_Easting = 40000000.0;
00164 static double TranMerc_Delta_Northing = 40000000.0;
00165 
00166 /* These state variables are for optimization purposes. The only function
00167  * that should modify them is Set_Tranverse_Mercator_Parameters.         */
00168 
00169 
00170 
00171 #ifndef OT_NO_GPS_SUPPORT
00172 
00173 // defines the model used for ECEF transformation
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         // add additional XYZ coordinate (ECEF format)
00208         // see
00209         // http://www.colorado.edu/geography/gcraft/notes/datum/gif/llhxyz.gif
00210         double xECEF;
00211         double yECEF;
00212         double zECEF;
00213         
00214         // add additional coordinates, that hold the Gauss-Krüger Projection for Styria (M34)
00215         // or in BMN (Bundesmeldeamt) format or in UTM format
00216         // these values are delivered after a transversal Mercator transformation has been 
00217         // applied to lat and lon
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         // coordinates in Bundesmeldeamt format
00227         double lat_bmn_34;      
00228         double lon_bmn_34;
00229 
00230 
00231         static const GPResult * parse( const char * );
00232 
00234         // see
00235         // http://www.colorado.edu/geography/gcraft/notes/datum/gif/llhxyz.gif
00236 
00237         void convert2ECEF(GeoidModel *geoid)
00238         {
00239             double rad_cur, gdlat, gdlon;
00240             double gdalt = altitude;
00241             
00242             // convert angles to radians
00243             gdlat = MathUtils::GradToRad * lat;
00244             gdlon = MathUtils::GradToRad * lon;
00245             
00246             // radius of curvature in the prime vertical
00247             rad_cur  = geoid->a() /
00248                 sqrt(1.0-geoid->eccSquared()*pow((sin(gdlat)),2.0));
00249             
00250                         //printf("lat = %2.24f\n", lat);
00251              //printf("lon = %2.24f\n", lon);
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               //printf("xECEF = %08.2f\n", xECEF);
00257               //printf("yECEF = %f08.2\n", yECEF);
00258                           //printf("zECEF = %f08.2\n", zECEF);
00259                           //getchar();
00260             
00261         }
00262 
00263 
00264                 /*long Set_Transverse_Mercator_Parameters(double a,double f, double Origin_Latitude, double Central_Meridian,double False_Easting, double False_Northing, double Scale_Factor){};
00265 
00266                 void Convert_Geodetic_To_Transverse_Mercator (double gdlat,double gdlon,double *Easting,double *Northing){};
00267         
00268                 long Set_UTM_Parameters(double a,   double f, long oride){};
00269 
00270                 long Convert_Geodetic_To_UTM (double Latitude, double Longitude,long *Zone, char *Hemisphere,double *Easting,double *Northing){};
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   /* BEGIN Set_Tranverse_Mercator_Parameters */
00285   /*
00286    * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid
00287    * parameters and Tranverse Mercator projection parameters as inputs, and
00288    * sets the corresponding state variables. If any errors occur, the error
00289    * code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is
00290    * returned.
00291    *
00292    *    a                 : Semi-major axis of ellipsoid, in meters    (input)
00293    *    f                 : Flattening of ellipsoid                                        (input)
00294    *    Origin_Latitude   : Latitude in radians at the origin of the   (input)
00295    *                         projection
00296    *    Central_Meridian  : Longitude in radians at the center of the  (input)
00297    *                         projection
00298    *    False_Easting     : Easting/X at the center of the projection  (input)
00299    *    False_Northing    : Northing/Y at the center of the projection (input)
00300    *    Scale_Factor      : Projection scale factor                    (input) 
00301    */
00302 
00303   double tn;        /* True Meridianal distance constant  */
00304   double tn2;
00305   double tn3;
00306   double tn4;
00307   double tn5;
00308   double dummy_northing;
00309   double TranMerc_b; /* Semi-minor axis of ellipsoid, in meters */
00310   double inv_f = 1 / f;
00311   long Error_Code = TRANMERC_NO_ERROR;
00312 
00313   if (a <= 0.0)
00314   { /* Semi-major axis must be greater than zero */
00315     Error_Code |= TRANMERC_A_ERROR;
00316   }
00317   if ((inv_f < 250) || (inv_f > 350))
00318   { /* Inverse flattening must be between 250 and 350 */
00319     Error_Code |= TRANMERC_INV_F_ERROR;
00320   }
00321   if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT))
00322   { /* origin latitude out of range */
00323     Error_Code |= TRANMERC_ORIGIN_LAT_ERROR;
00324   }
00325   if ((Central_Meridian < -PI) || (Central_Meridian > (2*PI)))
00326   { /* origin longitude out of range */
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   { /* no errors */
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     /* Eccentricity Squared */
00344     TranMerc_es = 2 * TranMerc_f - TranMerc_f * TranMerc_f;
00345     /* Second Eccentricity Squared */
00346     TranMerc_ebs = (1 / (1 - TranMerc_es)) - 1;
00347 
00348     TranMerc_b = TranMerc_a * (1 - TranMerc_f);    
00349     /*True meridianal constants  */
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   } /* END OF if(!Error_Code) */
00379   return (Error_Code);
00380 }  /* END of Set_Transverse_Mercator_Parameters  */
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            /* BEGIN Convert_Geodetic_To_Transverse_Mercator 
00392            see: http://earth-info.nga.mil/GandG/geotrans/
00393   
00394            * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic
00395            * (latitude and longitude) coordinates to Transverse Mercator projection
00396            * (easting and northing) coordinates, according to the current ellipsoid
00397            * and Transverse Mercator projection coordinates. 
00398            *
00399            *    Latitude      : lat in radians                         (input)
00400        *    Longitude     : lon in radians                         (input)
00401        *    Easting       : lon_gk_m34 Easting/X in meters                         (output)
00402        *    Northing      : lat_gk_m34 Northing/Y in meters                        (output)
00403                 
00404                 A particular ellipsoid is specified in terms of the following parameters:
00405                 Semi-Major Axis (a):    Radius (in meters) at the equator, and
00406                 Flattening (f): Ratio of the difference between the semi-major axis 
00407                 and polar radius of the Earth to its semi-major axis.
00408                    
00409                 A particular variation of the Transverse Mercator projection is 
00410                 specified in terms of the following parameters:
00411                         
00412                 Central Meridian – Longitude (in radians) at the origin of the projection,
00413                 Origin Latitude – Latitude (in radians) at the origin of the projection,
00414                 False Easting – A coordinate value (in meters) assigned to the 
00415                                                 central meridian of the projection to avoid the 
00416                                                 inconvenience of using negative coordinates, and
00417                 False Northing – A coordinate value (in meters) assigned to the 
00418                                                  origin latitude of the projection to avoid the 
00419                                                  inconvenience of using negative coordinates.
00420                 Scale Factor – a multiplier for reducing a distance in projected 
00421                                            coordinates to the actual distance along the central meridian.
00422    
00423    */
00424    
00425   double c;       /* Cosine of latitude                          */
00426   double c2;
00427   double c3;
00428   double c5;
00429   double c7;
00430   double dlam;    /* Delta longitude - Difference in Longitude       */
00431   double eta;     /* constant - TranMerc_ebs *c *c                   */
00432   double eta2;
00433   double eta3;
00434   double eta4;
00435   double s;       /* Sine of latitude                        */
00436   double sn;      /* Radius of curvature in the prime vertical       */
00437   double t;       /* Tangent of latitude                             */
00438   double tan2;
00439   double tan3;
00440   double tan4;
00441   double tan5;
00442   double tan6;
00443   double t1;      /* Term in coordinate conversion formula - GP to Y */
00444   double t2;      /* Term in coordinate conversion formula - GP to Y */
00445   double t3;      /* Term in coordinate conversion formula - GP to Y */
00446   double t4;      /* Term in coordinate conversion formula - GP to Y */
00447   double t5;      /* Term in coordinate conversion formula - GP to Y */
00448   double t6;      /* Term in coordinate conversion formula - GP to Y */
00449   double t7;      /* Term in coordinate conversion formula - GP to Y */
00450   double t8;      /* Term in coordinate conversion formula - GP to Y */
00451   double t9;      /* Term in coordinate conversion formula - GP to Y */
00452   double tmd;     /* True Meridional distance                        */
00453   double tmdo;    /* True Meridional distance for latitude of origin */
00454   long    Error_Code = TRANMERC_NO_ERROR;
00455   double temp_Origin;
00456   double temp_Long;
00457 
00458   //double gdlat, gdlon;
00459 
00460   // convert angles to radians
00461   //gdlat = MathUtils::GradToRad * lat;
00462   //gdlon = MathUtils::GradToRad * lon;
00463 
00464   if ((gdlat < -MAX_LAT) || (gdlat > MAX_LAT))
00465   {  /* Latitude out of range */
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   { /* no errors */
00487 
00488     /* 
00489      *  Delta Longitude
00490      */
00491     dlam = gdlon - TranMerc_Origin_Long;
00492 
00493     if (fabs(dlam) > (9.0 * PI / 180))
00494     { /* Distortion will result if lon is more than 9 degrees from the Central Meridian */
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     /* radius of curvature in prime vertical */
00523     sn = SPHSN(gdlat);
00524 
00525     /* True Meridianal Distances */
00526     tmd = SPHTMD(gdlat);
00527 
00528     /*  Origin  */
00529     tmdo = SPHTMD (TranMerc_Origin_Lat);
00530 
00531     /* northing */
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     /* Easting */
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          /*printf("lat = %2.24f\n", gdlat);
00564      printf("lon = %2.24f\n", gdlon);    
00565      printf("lon_gk_m34 = %08.2f\n", lon_gk_m34);
00566      printf("lat_gk_m34 = %f08.2\n", lat_gk_m34);
00567          getchar();
00568          */
00569         
00570   }
00571   
00572 } /* END OF Convert_Geodetic_To_Transverse_Mercator */
00573 
00574                 
00575 
00576 
00577  long Set_UTM_Parameters(double a,      
00578                         double f,
00579                         long oride)
00580 {
00581 /*
00582  * The function Set_UTM_Parameters receives the ellipsoid parameters and
00583  * UTM zone override parameter as inputs, and sets the corresponding state
00584  * variables.  If any errors occur, the error code(s) are returned by the 
00585  * function, otherwise UTM_NO_ERROR is returned.
00586  *
00587  *    a                 : Semi-major axis of ellipsoid, in meters       (input)
00588  *    f                 : Flattening of ellipsoid                                                           (input)
00589  *    oride          : UTM override zone, zero indicates no override (input)
00590  */
00591 
00592   double inv_f = 1 / f;
00593   long Error_Code = UTM_NO_ERROR;
00594 
00595   if (a <= 0.0)
00596   { /* Semi-major axis must be greater than zero */
00597     Error_Code |= UTM_A_ERROR;
00598   }
00599   if ((inv_f < 250) || (inv_f > 350))
00600   { /* Inverse flattening must be between 250 and 350 */
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   { /* no errors */
00609     UTM_a = a;
00610     UTM_f = f;
00611     UTM_Override = oride;
00612   }
00613   return (Error_Code);
00614 } /* END OF Set_UTM_Parameters */
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  * The function Convert_Geodetic_To_UTM converts geodetic (latitude and
00628  * longitude) coordinates to UTM projection (zone, hemisphere, easting and
00629  * northing) coordinates according to the current ellipsoid and UTM zone
00630  * override parameters.  If any errors occur, the error code(s) are returned
00631  * by the function, otherwise UTM_NO_ERROR is returned.
00632  *
00633  *    Latitude          : Latitude in radians                 (input)
00634  *    Longitude         : Longitude in radians                (input)
00635  *    Zone              : UTM zone                            (output)
00636  *    Hemisphere        : North or South hemisphere           (output)
00637  *    Easting           : Easting (X) in meters               (output)
00638  *    Northing          : Northing (Y) in meters              (output)
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   { /* Latitude out of range */
00653     Error_Code |= UTM_LAT_ERROR;
00654   }
00655   if ((Longitude < -PI) || (Longitude > (2*PI)))
00656   { /* Longitude out of range */
00657     Error_Code |= UTM_LON_ERROR;
00658   }
00659   if (!Error_Code)
00660   { /* no errors */
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     /* UTM special cases */
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           /*printf("%08.2f %08.2f\n", UTM_a, UTM_f);
00715           getchar();
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   } /* END OF if (!Error_Code) */
00728 
00729         /*
00730      printf("lon_utm = %08.2f\n", lon_utm_33n);
00731      printf("lat_utm = %f08.2\n", lat_utm_33n);
00732          printf("zone_utm = %i\n", zone_utm_33n);
00733          printf("hem_utm = %c\n", hem_utm_33n);
00734          getchar();
00735          */
00736          
00737 
00738   return (Error_Code);
00739 } /* END OF Convert_Geodetic_To_UTM */
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 } // namespace ot
00813 
00814 
00815 #endif // OT_NO_GPS_SUPPORT
00816 
00817 
00818 #endif // !defined(_GPSPARSER_H_)
00819 
00820 /* 
00821  * ------------------------------------------------------------
00822  *   End of GPSParser.h
00823  * ------------------------------------------------------------
00824  *   Automatic Emacs configuration follows.
00825  *   Local Variables:
00826  *   mode:c++
00827  *   c-basic-offset: 4
00828  *   eval: (c-set-offset 'substatement-open 0)
00829  *   eval: (c-set-offset 'case-label '+)
00830  *   eval: (c-set-offset 'statement 'c-lineup-runin-statements)
00831  *   eval: (setq indent-tabs-mode nil)
00832  *   End:
00833  * ------------------------------------------------------------ 
00834  */

Generated on Wed Feb 28 15:18:49 2007 for NaviTrack by  doxygen 1.4.6