Go to the documentation of this file.00001 #include <ros/ros.h>
00002 #include <corobot_msgs/GPSFix.h>
00003 #include <corobot_msgs/GPSStatus.h>
00004 #include <sensor_msgs/NavSatFix.h>
00005 #include <sensor_msgs/NavSatStatus.h>
00006 #include <libgpsmm.h>
00007 #include <diagnostic_updater/diagnostic_updater.h>
00008 #include <diagnostic_updater/publisher.h>
00009
00010 using namespace corobot_msgs;
00011 using namespace sensor_msgs;
00012
00013 class GPSDClient {
00014 public:
00015 GPSDClient() : privnode("~"), use_gps_time(true) {
00016 #if GPSD_API_MAJOR_VERSION < 5
00017 gps = new gpsmm();
00018 gps_state = 0;
00019 #endif
00020 }
00021
00022 ~GPSDClient()
00023 {
00024 delete gps;
00025 }
00026
00027 bool start() {
00028 gps_fix_pub = node.advertise<GPSFix>("extended_fix", 1);
00029 navsat_fix_pub = node.advertise<NavSatFix>("fix", 1);
00030
00031 privnode.getParam("use_gps_time", use_gps_time);
00032
00033 std::string host = "localhost";
00034 int port = 2947;
00035 privnode.getParam("host", host);
00036 privnode.getParam("port", port);
00037
00038 char port_s[12];
00039 snprintf(port_s, 12, "%d", port);
00040
00041 gps_data_t *resp;
00042 #if GPSD_API_MAJOR_VERSION >= 5
00043 gps = new gpsmm(host.c_str(), port_s);
00044 #elif GPSD_API_MAJOR_VERSION < 5
00045 resp = gps->open(host.c_str(), port_s);
00046 if (resp == NULL) {
00047 ROS_ERROR("Failed to open GPSd");
00048 gps_state = 1;
00049 return false;
00050 }
00051 #endif
00052
00053 #if GPSD_API_MAJOR_VERSION >= 5
00054 resp = gps->stream(WATCH_ENABLE);
00055 if (resp == NULL) {
00056 ROS_ERROR("Failed to intialize the gps");
00057 gps_state = 1;
00058 return false;
00059 }
00060
00061 #elif GPSD_API_MAJOR_VERSION == 4
00062 resp = gps->stream(WATCH_ENABLE);
00063 if (resp == NULL) {
00064 ROS_ERROR("Failed to intialize the gps");
00065 gps_state = 1;
00066 return false;
00067 }
00068 #elif GPSD_API_MAJOR_VERSION == 3
00069 gps->query("w\n");
00070 #else
00071 #error "gpsd_client only supports gpsd API versions 3, 4 and 5"
00072 gps_state = 2;
00073 #endif
00074
00075
00076 ROS_INFO("GPSd opened");
00077 return true;
00078 }
00079
00080 void step() {
00081
00082 gps_data_t *p;
00083 #if GPSD_API_MAJOR_VERSION >= 5
00084 p = gps->read();
00085 #elif GPSD_API_MAJOR_VERSION < 5
00086 p = gps->poll();
00087 #endif
00088 process_data(p);
00089 }
00090
00091 void stop() {
00092
00093 }
00094
00095 void gps_diagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
00099 {
00100 if (gps_state == 0)
00101 stat.summaryf(diagnostic_msgs::DiagnosticStatus::OK, "The gps is working");
00102 else if (gps_state == 1)
00103 {
00104 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "Can't intialize");
00105 stat.addf("Recommendation", "The gps could not be initialized. Please make sure the gps is connected to the motherboard and is configured. You can follow points 1.3 and after in the following tutorial for the configuration: http://ros.org/wiki/gpsd_client/Tutorials/Getting started with gpsd_client");
00106 }
00107 else if (gps_state == 2)
00108 {
00109 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "wrong lib gpsd version");
00110 stat.addf("Recommendation", "Please make sure that gpsd is installed and that you have at least the api major version 3 or after installed.");
00111 }
00112 }
00113
00114 private:
00115 ros::NodeHandle node;
00116 ros::NodeHandle privnode;
00117 ros::Publisher gps_fix_pub;
00118 ros::Publisher navsat_fix_pub;
00119 gpsmm *gps;
00120 int gps_state;
00121
00122 bool use_gps_time;
00123
00124 void process_data(struct gps_data_t* p) {
00125 if (p == NULL)
00126 return;
00127
00128 if (!p->online)
00129 return;
00130
00131 process_data_gps(p);
00132 process_data_navsat(p);
00133 }
00134
00135 #if GPSD_API_MAJOR_VERSION == 5
00136 #define SATS_VISIBLE p->satellites_visible
00137 #elif GPSD_API_MAJOR_VERSION == 4
00138 #define SATS_VISIBLE p->satellites_visible
00139 #elif GPSD_API_MAJOR_VERSION == 3
00140 #define SATS_VISIBLE p->satellites
00141 #endif
00142
00143 void process_data_gps(struct gps_data_t* p) {
00144 ros::Time time = ros::Time::now();
00145
00146 GPSFix fix;
00147 GPSStatus status;
00148
00149 status.header.stamp = time;
00150 fix.header.stamp = time;
00151
00152 status.satellites_used = p->satellites_used;
00153
00154 status.satellite_used_prn.resize(status.satellites_used);
00155 for (int i = 0; i < status.satellites_used; ++i) {
00156 status.satellite_used_prn[i] = p->used[i];
00157 }
00158
00159 status.satellites_visible = SATS_VISIBLE;
00160
00161 status.satellite_visible_prn.resize(status.satellites_visible);
00162 status.satellite_visible_z.resize(status.satellites_visible);
00163 status.satellite_visible_azimuth.resize(status.satellites_visible);
00164 status.satellite_visible_snr.resize(status.satellites_visible);
00165
00166 for (int i = 0; i < SATS_VISIBLE; ++i) {
00167 status.satellite_visible_prn[i] = p->PRN[i];
00168 status.satellite_visible_z[i] = p->elevation[i];
00169 status.satellite_visible_azimuth[i] = p->azimuth[i];
00170
00171 }
00172
00173 if ((p->status & STATUS_FIX) && !isnan(p->fix.epx)) {
00174 status.status = 0;
00175
00176
00177 if (p->status & STATUS_DGPS_FIX)
00178 status.status |= 18;
00179
00180 fix.time = p->fix.time;
00181 fix.latitude = p->fix.latitude;
00182 fix.longitude = p->fix.longitude;
00183 fix.altitude = p->fix.altitude;
00184 fix.track = p->fix.track;
00185 fix.speed = p->fix.speed;
00186 fix.climb = p->fix.climb;
00187
00188 #if GPSD_API_MAJOR_VERSION > 3
00189 fix.pdop = p->dop.pdop;
00190 fix.hdop = p->dop.hdop;
00191 fix.vdop = p->dop.vdop;
00192 fix.tdop = p->dop.tdop;
00193 fix.gdop = p->dop.gdop;
00194 #else
00195 fix.pdop = p->pdop;
00196 fix.hdop = p->hdop;
00197 fix.vdop = p->vdop;
00198 fix.tdop = p->tdop;
00199 fix.gdop = p->gdop;
00200 #endif
00201
00202 fix.err = p->epe;
00203 fix.err_vert = p->fix.epv;
00204 fix.err_track = p->fix.epd;
00205 fix.err_speed = p->fix.eps;
00206 fix.err_climb = p->fix.epc;
00207 fix.err_time = p->fix.ept;
00208
00209
00210 } else {
00211 status.status = -1;
00212 }
00213
00214 fix.status = status;
00215
00216 gps_fix_pub.publish(fix);
00217 }
00218
00219 void process_data_navsat(struct gps_data_t* p) {
00220 NavSatFixPtr fix(new NavSatFix);
00221
00222
00223
00224 if (use_gps_time)
00225 fix->header.stamp = ros::Time(p->fix.time);
00226 else
00227 fix->header.stamp = ros::Time::now();
00228
00229
00230
00231
00232
00233 switch (p->status) {
00234 case STATUS_NO_FIX:
00235 fix->status.status = -1;
00236 break;
00237 case STATUS_FIX:
00238 fix->status.status = 0;
00239 break;
00240 case STATUS_DGPS_FIX:
00241 fix->status.status = 2;
00242 break;
00243 }
00244
00245 fix->status.service = NavSatStatus::SERVICE_GPS;
00246
00247 fix->latitude = p->fix.latitude;
00248 fix->longitude = p->fix.longitude;
00249 fix->altitude = p->fix.altitude;
00250
00251
00252
00253
00254
00255 if (isnan(p->fix.epx)) {
00256
00257 }
00258
00259 fix->position_covariance[0] = p->fix.epx;
00260 fix->position_covariance[4] = p->fix.epy;
00261 fix->position_covariance[8] = p->fix.epv;
00262
00263 fix->position_covariance_type = NavSatFix::COVARIANCE_TYPE_DIAGONAL_KNOWN;
00264
00265 navsat_fix_pub.publish(fix);
00266 }
00267 };
00268
00269 int main(int argc, char ** argv) {
00270 ros::init(argc, argv, "corobot_gps");
00271
00272 GPSDClient client;
00273
00274
00275
00276 diagnostic_updater::Updater updater;
00277 updater.setHardwareIDf("GPS");
00278 updater.add("gps", &client, &GPSDClient::gps_diagnostic);
00279
00280 if (!client.start())
00281 {
00282 updater.force_update();
00283 return -1;
00284 }
00285
00286
00287 while(ros::ok()) {
00288 ros::spinOnce();
00289 updater.update();
00290 client.step();
00291 }
00292
00293 client.stop();
00294 }