Go to the documentation of this file.00001 #include <ros/ros.h>
00002 #include <gps_common/GPSFix.h>
00003 #include <gps_common/GPSStatus.h>
00004 #include <sensor_msgs/NavSatFix.h>
00005 #include <sensor_msgs/NavSatStatus.h>
00006 #include <libgpsmm.h>
00007
00008 using namespace gps_common;
00009 using namespace sensor_msgs;
00010
00011 class GPSDClient {
00012 public:
00013 GPSDClient() : privnode("~"), gps(NULL), use_gps_time(true), check_fix_by_variance(true) {}
00014
00015 bool start() {
00016 gps_fix_pub = node.advertise<GPSFix>("extended_fix", 1);
00017 navsat_fix_pub = node.advertise<NavSatFix>("fix", 1);
00018
00019 privnode.getParam("use_gps_time", use_gps_time);
00020 privnode.getParam("check_fix_by_variance", check_fix_by_variance);
00021
00022 std::string host = "localhost";
00023 int port = 2947;
00024 privnode.getParam("host", host);
00025 privnode.getParam("port", port);
00026
00027 char port_s[12];
00028 snprintf(port_s, 12, "%d", port);
00029
00030 gps_data_t *resp = NULL;
00031
00032 #if GPSD_API_MAJOR_VERSION >= 5
00033 gps = new gpsmm(host.c_str(), port_s);
00034 resp = gps->stream(WATCH_ENABLE);
00035 #elif GPSD_API_MAJOR_VERSION == 4
00036 gps = new gpsmm();
00037 gps->open(host.c_str(), port_s);
00038 resp = gps->stream(WATCH_ENABLE);
00039 #else
00040 gps = new gpsmm();
00041 resp = gps->open(host.c_str(), port_s);
00042 gps->query("w\n");
00043 #endif
00044
00045 if (resp == NULL) {
00046 ROS_ERROR("Failed to open GPSd");
00047 return false;
00048 }
00049
00050 ROS_INFO("GPSd opened");
00051 return true;
00052 }
00053
00054 void step() {
00055 #if GPSD_API_MAJOR_VERSION >= 5
00056 if (!gps->waiting(1e6))
00057 return;
00058
00059 gps_data_t *p = gps->read();
00060 #else
00061 gps_data_t *p = gps->poll();
00062 #endif
00063 process_data(p);
00064 }
00065
00066 void stop() {
00067
00068 }
00069
00070 private:
00071 ros::NodeHandle node;
00072 ros::NodeHandle privnode;
00073 ros::Publisher gps_fix_pub;
00074 ros::Publisher navsat_fix_pub;
00075 gpsmm *gps;
00076
00077 bool use_gps_time;
00078 bool check_fix_by_variance;
00079
00080 void process_data(struct gps_data_t* p) {
00081 if (p == NULL)
00082 return;
00083
00084 if (!p->online)
00085 return;
00086
00087 process_data_gps(p);
00088 process_data_navsat(p);
00089 }
00090
00091
00092 #if GPSD_API_MAJOR_VERSION >= 4
00093 #define SATS_VISIBLE p->satellites_visible
00094 #elif GPSD_API_MAJOR_VERSION == 3
00095 #define SATS_VISIBLE p->satellites
00096 #else
00097 #error "gpsd_client only supports gpsd API versions 3+"
00098 #endif
00099
00100 void process_data_gps(struct gps_data_t* p) {
00101 ros::Time time = ros::Time::now();
00102
00103 GPSFix fix;
00104 GPSStatus status;
00105
00106 status.header.stamp = time;
00107 fix.header.stamp = time;
00108
00109 status.satellites_used = p->satellites_used;
00110
00111 status.satellite_used_prn.resize(status.satellites_used);
00112 for (int i = 0; i < status.satellites_used; ++i) {
00113 #if GPSD_API_MAJOR_VERSION > 5
00114 status.satellite_used_prn[i] = p->skyview[i].used;
00115 #else
00116 status.satellite_used_prn[i] = p->used[i];
00117 #endif
00118 }
00119
00120 status.satellites_visible = SATS_VISIBLE;
00121
00122 status.satellite_visible_prn.resize(status.satellites_visible);
00123 status.satellite_visible_z.resize(status.satellites_visible);
00124 status.satellite_visible_azimuth.resize(status.satellites_visible);
00125 status.satellite_visible_snr.resize(status.satellites_visible);
00126
00127 for (int i = 0; i < SATS_VISIBLE; ++i) {
00128 #if GPSD_API_MAJOR_VERSION > 5
00129 status.satellite_visible_prn[i] = p->skyview[i].PRN;
00130 status.satellite_visible_z[i] = p->skyview[i].elevation;
00131 status.satellite_visible_azimuth[i] = p->skyview[i].azimuth;
00132 status.satellite_visible_snr[i] = p->skyview[i].ss;
00133 #else
00134 status.satellite_visible_prn[i] = p->PRN[i];
00135 status.satellite_visible_z[i] = p->elevation[i];
00136 status.satellite_visible_azimuth[i] = p->azimuth[i];
00137 status.satellite_visible_snr[i] = p->ss[i];
00138 #endif
00139 }
00140
00141 if ((p->status & STATUS_FIX) && !(check_fix_by_variance && isnan(p->fix.epx))) {
00142 status.status = 0;
00143
00144
00145
00146 #if GPSD_API_MAJOR_VERSION != 6
00147 if (p->status & STATUS_DGPS_FIX)
00148 status.status |= 18;
00149 #endif
00150
00151 fix.time = p->fix.time;
00152 fix.latitude = p->fix.latitude;
00153 fix.longitude = p->fix.longitude;
00154 fix.altitude = p->fix.altitude;
00155 fix.track = p->fix.track;
00156 fix.speed = p->fix.speed;
00157 fix.climb = p->fix.climb;
00158
00159 #if GPSD_API_MAJOR_VERSION > 3
00160 fix.pdop = p->dop.pdop;
00161 fix.hdop = p->dop.hdop;
00162 fix.vdop = p->dop.vdop;
00163 fix.tdop = p->dop.tdop;
00164 fix.gdop = p->dop.gdop;
00165 #else
00166 fix.pdop = p->pdop;
00167 fix.hdop = p->hdop;
00168 fix.vdop = p->vdop;
00169 fix.tdop = p->tdop;
00170 fix.gdop = p->gdop;
00171 #endif
00172
00173 fix.err = p->epe;
00174 fix.err_vert = p->fix.epv;
00175 fix.err_track = p->fix.epd;
00176 fix.err_speed = p->fix.eps;
00177 fix.err_climb = p->fix.epc;
00178 fix.err_time = p->fix.ept;
00179
00180
00181 } else {
00182 status.status = -1;
00183 }
00184
00185 fix.status = status;
00186
00187 gps_fix_pub.publish(fix);
00188 }
00189
00190 void process_data_navsat(struct gps_data_t* p) {
00191 NavSatFixPtr fix(new NavSatFix);
00192
00193
00194
00195 if (use_gps_time && !isnan(p->fix.time))
00196 fix->header.stamp = ros::Time(p->fix.time);
00197 else
00198 fix->header.stamp = ros::Time::now();
00199
00200
00201
00202
00203
00204 switch (p->status) {
00205 case STATUS_NO_FIX:
00206 fix->status.status = -1;
00207 break;
00208 case STATUS_FIX:
00209 fix->status.status = 0;
00210 break;
00211
00212 #if GPSD_API_MAJOR_VERSION != 6
00213 case STATUS_DGPS_FIX:
00214 fix->status.status = 2;
00215 break;
00216 #endif
00217 }
00218
00219 fix->status.service = NavSatStatus::SERVICE_GPS;
00220
00221 fix->latitude = p->fix.latitude;
00222 fix->longitude = p->fix.longitude;
00223 fix->altitude = p->fix.altitude;
00224
00225
00226
00227
00228
00229 if (isnan(p->fix.epx) && check_fix_by_variance) {
00230 return;
00231 }
00232
00233 fix->position_covariance[0] = p->fix.epx;
00234 fix->position_covariance[4] = p->fix.epy;
00235 fix->position_covariance[8] = p->fix.epv;
00236
00237 fix->position_covariance_type = NavSatFix::COVARIANCE_TYPE_DIAGONAL_KNOWN;
00238
00239 navsat_fix_pub.publish(fix);
00240 }
00241 };
00242
00243 int main(int argc, char ** argv) {
00244 ros::init(argc, argv, "gpsd_client");
00245
00246 GPSDClient client;
00247
00248 if (!client.start())
00249 return -1;
00250
00251
00252 while(ros::ok()) {
00253 ros::spinOnce();
00254 client.step();
00255 }
00256
00257 client.stop();
00258 }