nmea gps library - without any serial
Dependents: HARP2 HARP3 20180621_FT813
Fork of GPS_parser by
NMEA GPS Serial Output parser.
Routine taken from NMEA Software Standard (NMEA 0183) http://www.winsystems.com/software/nmea.pdf
Only handles GGA and RMC Messages
Revision 5:94daced1e61a, committed 2012-12-12
- Comitter:
- tylerjw
- Date:
- Wed Dec 12 17:32:31 2012 +0000
- Parent:
- 4:6e2d98b5cb86
- Child:
- 6:4ed12067a314
- Commit message:
- bug fix
Changed in this revision
--- a/GPS.cpp Wed Dec 12 17:22:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,243 +0,0 @@ -#include "GPS.h" - -GPS::GPS() -{ - nmea_longitude = 0.0; - nmea_latitude = 0.0; - utc_time = 0; - ns = ' '; - ew = ' '; - lock = 0; - satelites = 0; - hdop = 0.0; - msl_altitude = 0.0; - msl_units = ' '; - - rmc_status = ' '; - speed_k = 0.0; - course_d = 0.0; - date = 0; - - dec_longitude = 0.0; - dec_latitude = 0.0; - - gll_status = ' '; - - course_t = 0.0; // ground speed true - course_t_unit = ' '; - course_m = 0.0; // magnetic - course_m_unit = ' '; - speed_k_unit = ' '; - speed_km = 0.0; // speek km/hr - speed_km_unit = ' '; - - altitude_ft = 0.0; -} - -float GPS::nmea_to_dec(float deg_coord, char nsew) -{ - int degree = (int)(deg_coord/100); - float minutes = deg_coord - degree*100; - float dec_deg = minutes / 60; - float decimal = degree + dec_deg; - if (nsew == 'S' || nsew == 'W') { // return negative - decimal *= -1; - } - return decimal; -} - -int GPS::sample(char *msg) -{ - int line_parsed = 0; - - // Check if it is a GPGGA msg (matches both locked and non-locked msg) - if (sscanf(msg, "$GPGGA,%f,%f,%c,%f,%c,%d,%d,%f,%f,%c", &utc_time, &nmea_latitude, &ns, &nmea_longitude, &ew, &lock, &satelites, &hdop, &msl_altitude, &msl_units) >= 1) { - line_parsed = GGA; - } - // Check if it is a GPRMC msg - else if (sscanf(msg, "$GPRMC,%f,%f,%c,%f,%c,%f,%f,%d", &utc_time, &nmea_latitude, &ns, &nmea_longitude, &ew, &speed_k, &course_d, &date) >= 1) { - line_parsed = RMC; - } - - if(satelites == 0) { - lock = 0; - } - if (!lock) { - return NO_LOCK; - } else if (line_parsed) { - return line_parsed; - } else { - return NOT_PARSED; - } -} - - -// INTERNAL FUNCTINS //////////////////////////////////////////////////////////// -float GPS::trunc(float v) -{ - if (v < 0.0) { - v*= -1.0; - v = floor(v); - v*=-1.0; - } else { - v = floor(v); - } - return v; -} - -// GET FUNCTIONS ///////////////////////////////////////////////////////////////// -float GPS::get_msl_altitude() -{ - if (!lock) - return 0.0; - else - return msl_altitude; -} - -int GPS::get_satelites() -{ - if (!lock) - return 0; - else - return satelites; -} - -float GPS::get_nmea_longitude() -{ - if (!lock) - return 0.0; - else - return nmea_longitude; -} - -float GPS::get_dec_longitude() -{ - dec_longitude = nmea_to_dec(nmea_longitude, ew); - if (!lock) - return 0.0; - else - return dec_longitude; -} - -float GPS::get_nmea_latitude() -{ - if (!lock) - return 0.0; - else - return nmea_latitude; -} - -float GPS::get_dec_latitude() -{ - dec_latitude = nmea_to_dec(nmea_latitude, ns); - if (!lock) - return 0.0; - else - return dec_latitude; -} - -float GPS::get_course_t() -{ - if (!lock) - return 0.0; - else - return course_t; -} - -float GPS::get_course_m() -{ - if (!lock) - return 0.0; - else - return course_m; -} - -float GPS::get_speed_k() -{ - if (!lock) - return 0.0; - else - return speed_k; -} - -float GPS::get_speed_km() -{ - if (!lock) - return 0.0; - else - return speed_km; -} - -float GPS::get_altitude_ft() -{ - if (!lock) - return 0.0; - else - return 3.280839895*msl_altitude; -} - -// NAVIGATION FUNCTIONS //////////////////////////////////////////////////////////// -float GPS::calc_course_to(float pointLat, float pontLong) -{ - const double d2r = PI / 180.0; - const double r2d = 180.0 / PI; - double dlat = abs(pointLat - get_dec_latitude()) * d2r; - double dlong = abs(pontLong - get_dec_longitude()) * d2r; - double y = sin(dlong) * cos(pointLat * d2r); - double x = cos(get_dec_latitude()*d2r)*sin(pointLat*d2r) - sin(get_dec_latitude()*d2r)*cos(pointLat*d2r)*cos(dlong); - return 360.0-(atan2(y,x)*r2d); -} - -/* -var y = Math.sin(dLon) * Math.cos(lat2); -var x = Math.cos(lat1)*Math.sin(lat2) - - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); -var brng = Math.atan2(y, x).toDeg(); -*/ - -/* - The Haversine formula according to Dr. Math. - http://mathforum.org/library/drmath/view/51879.html - - dlon = lon2 - lon1 - dlat = lat2 - lat1 - a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2 - c = 2 * atan2(sqrt(a), sqrt(1-a)) - d = R * c - - Where - * dlon is the change in longitude - * dlat is the change in latitude - * c is the great circle distance in Radians. - * R is the radius of a spherical Earth. - * The locations of the two points in - spherical coordinates (longitude and - latitude) are lon1,lat1 and lon2, lat2. -*/ -double GPS::calc_dist_to_mi(float pointLat, float pontLong) -{ - const double d2r = PI / 180.0; - double dlat = pointLat - get_dec_latitude(); - double dlong = pontLong - get_dec_longitude(); - double a = pow(sin(dlat/2.0),2.0) + cos(get_dec_latitude()*d2r) * cos(pointLat*d2r) * pow(sin(dlong/2.0),2.0); - double c = 2.0 * asin(sqrt(abs(a))); - double d = 63.765 * c; - - return d; -} - -double GPS::calc_dist_to_ft(float pointLat, float pontLong) -{ - return calc_dist_to_mi(pointLat, pontLong)*5280.0; -} - -double GPS::calc_dist_to_km(float pointLat, float pontLong) -{ - return calc_dist_to_mi(pointLat, pontLong)*1.609344; -} - -double GPS::calc_dist_to_m(float pointLat, float pontLong) -{ - return calc_dist_to_mi(pointLat, pontLong)*1609.344; -} -
--- a/GPS.h Wed Dec 12 17:22:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -#include "mbed.h" - -#ifndef MBED_GPS_H -#define MBED_GPS_H - -#define NO_LOCK 1 -#define NOT_PARSED 2 -#define GGA 3 -#define GLL 4 -#define RMC 5 -#define VTG 6 - -#define PI (3.141592653589793) - -/** A GPS interface for reading from a Globalsat EM-406 GPS Module */ -class GPS { -public: - - /** Create the GPS interface, connected to the specified serial port - */ - GPS(); - - /** Sample the incoming GPS data, returning whether there is a lock - * - * @return 1 if there was a lock when the sample was taken (and therefore .longitude and .latitude are valid), else 0 - */ - int sample(char *); - float get_nmea_longitude(); - float get_nmea_latitude(); - float get_dec_longitude(); - float get_dec_latitude(); - float get_msl_altitude(); - float get_course_t(); - float get_course_m(); - float get_speed_k(); - float get_speed_km(); - int get_satelites(); - float get_altitude_ft(); - - // navigational functions - float calc_course_to(float, float); - double calc_dist_to_mi(float, float); - double calc_dist_to_ft(float, float); - double calc_dist_to_km(float, float); - double calc_dist_to_m(float, float); - -private: - float nmea_to_dec(float, char); - float trunc(float v); - - // calculated values - float dec_longitude; - float dec_latitude; - float altitude_ft; - - // GGA - Global Positioning System Fixed Data - float nmea_longitude; - float nmea_latitude; - float utc_time; - char ns, ew; - int lock; - int satelites; - float hdop; - float msl_altitude; - char msl_units; - - // RMC - Recommended Minimmum Specific GNS Data - char rmc_status; - float speed_k; - float course_d; - int date; - - // GLL - char gll_status; - - // VTG - Course over ground, ground speed - float course_t; // ground speed true - char course_t_unit; - float course_m; // magnetic - char course_m_unit; - char speed_k_unit; - float speed_km; // speek km/hr - char speed_km_unit; -}; - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GPS_parser.cpp Wed Dec 12 17:32:31 2012 +0000 @@ -0,0 +1,243 @@ +#include "GPS_parser.h" + +GPS_Parser::GPS_Parser() +{ + nmea_longitude = 0.0; + nmea_latitude = 0.0; + utc_time = 0; + ns = ' '; + ew = ' '; + lock = 0; + satelites = 0; + hdop = 0.0; + msl_altitude = 0.0; + msl_units = ' '; + + rmc_status = ' '; + speed_k = 0.0; + course_d = 0.0; + date = 0; + + dec_longitude = 0.0; + dec_latitude = 0.0; + + gll_status = ' '; + + course_t = 0.0; // ground speed true + course_t_unit = ' '; + course_m = 0.0; // magnetic + course_m_unit = ' '; + speed_k_unit = ' '; + speed_km = 0.0; // speek km/hr + speed_km_unit = ' '; + + altitude_ft = 0.0; +} + +float GPS_Parser::nmea_to_dec(float deg_coord, char nsew) +{ + int degree = (int)(deg_coord/100); + float minutes = deg_coord - degree*100; + float dec_deg = minutes / 60; + float decimal = degree + dec_deg; + if (nsew == 'S' || nsew == 'W') { // return negative + decimal *= -1; + } + return decimal; +} + +int GPS_Parser::sample(char *msg) +{ + int line_parsed = 0; + + // Check if it is a GPGGA msg (matches both locked and non-locked msg) + if (sscanf(msg, "$GPGGA,%f,%f,%c,%f,%c,%d,%d,%f,%f,%c", &utc_time, &nmea_latitude, &ns, &nmea_longitude, &ew, &lock, &satelites, &hdop, &msl_altitude, &msl_units) >= 1) { + line_parsed = GGA; + } + // Check if it is a GPRMC msg + else if (sscanf(msg, "$GPRMC,%f,%f,%c,%f,%c,%f,%f,%d", &utc_time, &nmea_latitude, &ns, &nmea_longitude, &ew, &speed_k, &course_d, &date) >= 1) { + line_parsed = RMC; + } + + if(satelites == 0) { + lock = 0; + } + if (!lock) { + return NO_LOCK; + } else if (line_parsed) { + return line_parsed; + } else { + return NOT_PARSED; + } +} + + +// INTERNAL FUNCTINS //////////////////////////////////////////////////////////// +float GPS_Parser::trunc(float v) +{ + if (v < 0.0) { + v*= -1.0; + v = floor(v); + v*=-1.0; + } else { + v = floor(v); + } + return v; +} + +// GET FUNCTIONS ///////////////////////////////////////////////////////////////// +float GPS_Parser::get_msl_altitude() +{ + if (!lock) + return 0.0; + else + return msl_altitude; +} + +int GPS_Parser::get_satelites() +{ + if (!lock) + return 0; + else + return satelites; +} + +float GPS_Parser::get_nmea_longitude() +{ + if (!lock) + return 0.0; + else + return nmea_longitude; +} + +float GPS_Parser::get_dec_longitude() +{ + dec_longitude = nmea_to_dec(nmea_longitude, ew); + if (!lock) + return 0.0; + else + return dec_longitude; +} + +float GPS_Parser::get_nmea_latitude() +{ + if (!lock) + return 0.0; + else + return nmea_latitude; +} + +float GPS_Parser::get_dec_latitude() +{ + dec_latitude = nmea_to_dec(nmea_latitude, ns); + if (!lock) + return 0.0; + else + return dec_latitude; +} + +float GPS_Parser::get_course_t() +{ + if (!lock) + return 0.0; + else + return course_t; +} + +float GPS_Parser::get_course_m() +{ + if (!lock) + return 0.0; + else + return course_m; +} + +float GPS_Parser::get_speed_k() +{ + if (!lock) + return 0.0; + else + return speed_k; +} + +float GPS_Parser::get_speed_km() +{ + if (!lock) + return 0.0; + else + return speed_km; +} + +float GPS_Parser::get_altitude_ft() +{ + if (!lock) + return 0.0; + else + return 3.280839895*msl_altitude; +} + +// NAVIGATION FUNCTIONS //////////////////////////////////////////////////////////// +float GPS_Parser::calc_course_to(float pointLat, float pontLong) +{ + const double d2r = PI / 180.0; + const double r2d = 180.0 / PI; + double dlat = abs(pointLat - get_dec_latitude()) * d2r; + double dlong = abs(pontLong - get_dec_longitude()) * d2r; + double y = sin(dlong) * cos(pointLat * d2r); + double x = cos(get_dec_latitude()*d2r)*sin(pointLat*d2r) - sin(get_dec_latitude()*d2r)*cos(pointLat*d2r)*cos(dlong); + return 360.0-(atan2(y,x)*r2d); +} + +/* +var y = Math.sin(dLon) * Math.cos(lat2); +var x = Math.cos(lat1)*Math.sin(lat2) - + Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); +var brng = Math.atan2(y, x).toDeg(); +*/ + +/* + The Haversine formula according to Dr. Math. + http://mathforum.org/library/drmath/view/51879.html + + dlon = lon2 - lon1 + dlat = lat2 - lat1 + a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2 + c = 2 * atan2(sqrt(a), sqrt(1-a)) + d = R * c + + Where + * dlon is the change in longitude + * dlat is the change in latitude + * c is the great circle distance in Radians. + * R is the radius of a spherical Earth. + * The locations of the two points in + spherical coordinates (longitude and + latitude) are lon1,lat1 and lon2, lat2. +*/ +double GPS_Parser::calc_dist_to_mi(float pointLat, float pontLong) +{ + const double d2r = PI / 180.0; + double dlat = pointLat - get_dec_latitude(); + double dlong = pontLong - get_dec_longitude(); + double a = pow(sin(dlat/2.0),2.0) + cos(get_dec_latitude()*d2r) * cos(pointLat*d2r) * pow(sin(dlong/2.0),2.0); + double c = 2.0 * asin(sqrt(abs(a))); + double d = 63.765 * c; + + return d; +} + +double GPS_Parser::calc_dist_to_ft(float pointLat, float pontLong) +{ + return calc_dist_to_mi(pointLat, pontLong)*5280.0; +} + +double GPS_Parser::calc_dist_to_km(float pointLat, float pontLong) +{ + return calc_dist_to_mi(pointLat, pontLong)*1.609344; +} + +double GPS_Parser::calc_dist_to_m(float pointLat, float pontLong) +{ + return calc_dist_to_mi(pointLat, pontLong)*1609.344; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GPS_parser.h Wed Dec 12 17:32:31 2012 +0000 @@ -0,0 +1,84 @@ +#include "mbed.h" + +#ifndef MBED_GPS_PARSER_H +#define MBED_GPS_PARSER_H + +#define NO_LOCK 1 +#define NOT_PARSED 2 +#define GGA 3 +#define GLL 4 +#define RMC 5 +#define VTG 6 + +#define PI (3.141592653589793) + +/** A GPS_parser interface for reading from a Globalsat EM-406 GPS Module */ +class GPS_Parser { +public: + + GPS_Parser(); + + /** Sample the incoming GPS data, returning whether there is a lock + * + * @return 1 if there was a lock when the sample was taken (and therefore .longitude and .latitude are valid), else 0 + */ + int sample(char *); + float get_nmea_longitude(); + float get_nmea_latitude(); + float get_dec_longitude(); + float get_dec_latitude(); + float get_msl_altitude(); + float get_course_t(); + float get_course_m(); + float get_speed_k(); + float get_speed_km(); + int get_satelites(); + float get_altitude_ft(); + + // navigational functions + float calc_course_to(float, float); + double calc_dist_to_mi(float, float); + double calc_dist_to_ft(float, float); + double calc_dist_to_km(float, float); + double calc_dist_to_m(float, float); + +private: + float nmea_to_dec(float, char); + float trunc(float v); + + // calculated values + volatile float dec_longitude; + volatile float dec_latitude; + volatile float altitude_ft; + + // GGA - Global Positioning System Fixed Data + volatile float nmea_longitude; + volatile float nmea_latitude; + volatile float utc_time; + volatile char ns, ew; + volatile int lock; + volatile int satelites; + volatile float hdop; + volatile float msl_altitude; + volatile char msl_units; + + // RMC - Recommended Minimmum Specific GNS Data + volatile char rmc_status; + volatile float speed_k; + volatile float course_d; + volatile int date; + + // GLL + volatile char gll_status; + + // VTG - Course over ground, ground speed + volatile float course_t; // ground speed true + volatile char course_t_unit; + volatile float course_m; // magnetic + volatile char course_m_unit; + volatile char speed_k_unit; + volatile float speed_km; // speek km/hr + volatile char speed_km_unit; +}; + +#endif