00001 /*!@file Devices/GPS.H Serial interface to an NMEA 0183 GPS unit (Garmin Geko 301) */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2002 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/GPS.H $ 00035 // $Id: GPS.H 6990 2006-08-11 18:13:51Z rjpeters $ 00036 // 00037 00038 #ifndef GPS_H_DEFINED 00039 #define GPS_H_DEFINED 00040 00041 #include "Component/ModelComponent.H" 00042 #include "Devices/Serial.H" 00043 #include "Util/Types.H" // for byte 00044 00045 //! Data received from the GPS unit 00046 class GPSdata { 00047 public: 00048 //! Constructor with empty data (indicated by fix type 0) 00049 GPSdata(); 00050 00051 byte fixtype; //!< fix type (0=none/invalid data, 1=2D, 2=3D) 00052 00053 byte nsat; //!< Number of satellites in use (0..12) 00054 00055 byte fixho; //!< UTC time of fix, hours 00056 byte fixmi; //!< UTC time of fix, minutes 00057 byte fixse; //!< UTC time of fix, seconds 00058 byte fixda; //!< UTC date of fix, day 00059 byte fixmo; //!< UTC date of fix, month 00060 int fixye; //!< UTC date of fix, year 00061 00062 double latitude; //!< latitude (>=0 for North) 00063 double longitude; //!< longitude (>=0 for East) 00064 float galtitude; //!< GPS-derived altitude, in meters 00065 float altitude; //!< pressure-sensor derived altitude, in meters 00066 float speed; //!< course speed, in km/h 00067 float heading; //!< heading, true, in deg 00068 float magvar; //!< magnetic variation, deg (add to true for mag heading) 00069 00070 float pdil; //!< Precision dilution on position (smaller is better) 00071 float hdil; //!< Horiz precision dilution (smaller is better) 00072 float vdil; //!< Vertic precision dilution (smaller is better) 00073 00074 float epe; //!< Estimated position error, in meters 00075 float hpe; //!< Estimated horiz position error, in meters 00076 float vpe; //!< Estimated vertic position error, in meters 00077 00078 //! Convert to string 00079 /*! At least siz bytes should have been pre-allocated to str */ 00080 void toString(char *str, const int siz) const; 00081 00082 //! Convert from string 00083 /*! Returns true on success */ 00084 bool fromString(const char *str); 00085 }; 00086 00087 //! GPS event listener 00088 /*! The GPSlistener is called each time a new GPS fix data block is 00089 received. This is a virtual base class and users should define their 00090 own derived classes that will do something when a frame is 00091 received. */ 00092 class GPSlistener { 00093 public: 00094 //! Destructor 00095 virtual ~GPSlistener(); 00096 00097 //! New GPS data available 00098 virtual void newData(const GPSdata& data) = 0; 00099 }; 00100 00101 //! Interface with a GPS unit (tested with Garmin Geko 301) using NMEA 0183 00102 /*! This is a multi-threaded class which continuously polls the unit 00103 for data and updates an internal copy of a GPSdata struct. Users can 00104 get the most up-to-date data at any time using getData(), or can 00105 setup a GPSlistener that will be called each time new data is 00106 available. Note that communication with the GPS unit operates at 00107 4800 bauds, so the actual rate of data refresh is quite low (2s) and 00108 querying for data more often than once every two seconds is useless. 00109 00110 The Geko 301 has a true compass and altimeter/barometer. These need 00111 to be queried separately from the standard GPS summary query. This 00112 driver achieves that. 00113 00114 The Geko 301 is stated to support the following NMEA 0183 sentences: 00115 GPGGA, GPGLL, GPGSA, GPGSV, GPRMB, GPRMC, GPTRE, GPVTG, GPWPL, 00116 GPBOD, PGRME, PGRMM, PGRMZ, PSLIB. Not all of the sentences may be 00117 used by this driver, however (in particular, waypoint functionality 00118 can be more easily achieved in the main C++ code than in the GPS 00119 unit). 00120 00121 Here is a typical sequence emitted by the Geko 301 when set in NMEA 00122 output mode: 00123 00124 $GPRMC,082158,A,3403.4155,N,11815.0936,W,0.0,13.9,211104,13.5,E,A*05 00125 $GPRMB,A,,,,,,,,,,,,A,A*0B 00126 $GPGGA,082158,3403.4155,N,11815.0936,W,1,08,1.1,127.6,M,-31.8,M,,*7A 00127 $GPGSA,A,3,01,03,,14,15,18,19,21,22,,,,2.2,1.1,1.9*3B 00128 $GPGSV,3,1,10,01,27,216,36,03,40,254,41,09,19,058,00,14,75,207,39*7B 00129 $GPGSV,3,2,10,15,74,090,42,18,35,058,42,19,34,296,37,21,27,123,43*72 00130 $GPGSV,3,3,10,22,60,020,35,25,02,184,00*72 00131 $GPGLL,3403.4155,N,11815.0936,W,082158,A,A*52 00132 $GPBOD,,T,,M,,*47 00133 $PGRME,4.5,M,6.7,M,8.0,M*26 00134 $PGRMZ,424,f*06 00135 $HCHDG,92.6,,,13.5,E*23 00136 $GPRTE,1,1,c,*37 00137 */ 00138 class GPS : public ModelComponent { 00139 public: 00140 //! Constructor 00141 /*! You can set which serial device to use by setting the 00142 ModelParameter GPSDevName */ 00143 GPS(OptionManager& mgr, const std::string& descrName = "GPS", 00144 const std::string& tagName = "GPS"); 00145 00146 //! setup a listener that will be called each time new data is received 00147 void setListener(rutz::shared_ptr<GPSlistener>& listener); 00148 00149 //! destructor 00150 virtual ~GPS(); 00151 00152 //! Get current data from the GPS unit 00153 /*! returns true if returned data comes from a completed new GPS fix 00154 compared to last time we were called. Note that some of the data 00155 may still differ even if the return value is false, if we have 00156 partially received and parsed new data from a new fix. */ 00157 bool getData(GPSdata& data); 00158 00159 //! Running thread 00160 /*! Do not call directly, this is called by our GPS polling thread */ 00161 void run(); 00162 00163 protected: 00164 void start2(); //!< get started 00165 void stop1(); //! get stopped 00166 nub::soft_ref<Serial> itsSerial; //!< our serial port 00167 00168 private: 00169 double str2d(const char *s, const int nchar) const; 00170 00171 GPSdata itsData; // our internal copy of the data 00172 bool itsKeepgoing; // regulates our running thread 00173 bool itsGotnew; // true if new data since last getData() 00174 rutz::shared_ptr<GPSlistener> itsListener; // our listener 00175 pthread_t itsRunner; // our GPS polling thread 00176 pthread_mutex_t itsLock; // mutex to access our data 00177 }; 00178 00179 #endif 00180 00181 // ###################################################################### 00182 /* So things look consistent in everyone's emacs... */ 00183 /* Local Variables: */ 00184 /* indent-tabs-mode: nil */ 00185 /* End: */