|
GPS packets come in many different forms, you can get the details on all the different types in the Reference Section. The following functions are to decode the following data type:
$GPGLL,3354.4970,N,11759.5354,W,025604,V,S*52
which will give you the current latitude and longitude in decimal notation. Decimal notation makes GPS calculations a lot easier, for example: 120o27'W converts to -120.45o. It also converts the time to standard Unix format instead of a packed string.
using namespace std; #include <iostream> #include <stdio.h> #include <time.h> // mktime, struct tm
typedef struct s_gps { double lon; // - = south, in metric double lat; // - = west, in metric double time; // time of fix, seconds since 1970 }; s_gps DecodeGPS(char *val); // decode the gps packet off the serial line int GPSGoodData(char *val, char *checksum); // check the checksum
s_gps DecodeGPS(char *val) { // decode the GPS packet and return the struct s_gps data; // gps packet
if (GPSGoodData(val, "")) { // error messages are handled inside gpsgooddata if (strncmp(val, "", 6) == 0) { // ,3354.4970,N,11759.5354,W,025604,V,S*52 lat/lon; V(a=valid, v=invalid) // 0 1 2 3 4 5 6 7 double lat_deg_nmea, lon_deg_nmea; char lat_dir, lon_dir; int hms; char valid; struct tm tm; sscanf(val, ",%lf,%c,%lf,%c,%d,%c,", &lat_deg_nmea, &lat_dir, &lon_deg_nmea, &lon_dir, &hms, &valid); tm.tm_sec = hms % 100; hms = hms / 100; tm.tm_min = hms % 100; hms = hms / 100; tm.tm_hour = hms % 100; data.time = mktime(&tm) + time(0);
// lat_deg is in the format ddmm.mmmm double grades, frac; frac = modf(lat_deg_nmea / 100.0, &grades); data.lat = (double)(grades + frac * 100.0 / 60.0) * (lat_dir == 'S' ? -1.0 : 1.0); frac = modf(lon_deg_nmea/ 100.0, &grades); data.lon = (double)(grades + frac * 100.0 / 60.0) * (lon_dir == 'W' ? -1.0 : 1.0); } } return data; }
int GPSGoodData(char *val, char *checksum) { // NMEA 0183 sentences begin with $ and and with CR LF if (val[0] != '$') { // Does not start with $ return false; } // ending must be CRLF (\n\r) if (val[strlen(val)-2] != '\n') { // Does not end-1 with \n return false; } if (val[strlen(val)-1] != '
') { // Does not end with \r return false; } return true; }
|