gps.cpp
Go to the documentation of this file.
00001 
00009 /*
00010  * Copyright 2013 Vladimir Ermakov.
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 3 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful, but
00018  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00019  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00020  * for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License along
00023  * with this program; if not, write to the Free Software Foundation, Inc.,
00024  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00025  */
00026 
00027 #include <angles/angles.h>
00028 #include <mavros/mavros_plugin.h>
00029 #include <pluginlib/class_list_macros.h>
00030 
00031 #include <sensor_msgs/NavSatFix.h>
00032 #include <sensor_msgs/NavSatStatus.h>
00033 #include <sensor_msgs/TimeReference.h>
00034 #include <geometry_msgs/TwistStamped.h>
00035 
00036 namespace mavplugin {
00037 
00038 class GPSInfo : public diagnostic_updater::DiagnosticTask
00039 {
00040 public:
00041         explicit GPSInfo(const std::string name) :
00042                 diagnostic_updater::DiagnosticTask(name),
00043                 satellites_visible(-1),
00044                 fix_type(0),
00045                 eph(UINT16_MAX),
00046                 epv(UINT16_MAX)
00047         { };
00048 
00049         void set_gps_raw(mavlink_gps_raw_int_t &gps) {
00050                 satellites_visible = gps.satellites_visible;
00051                 fix_type = gps.fix_type;
00052                 eph = gps.eph;
00053                 epv = gps.epv;
00054         }
00055 
00056         void run(diagnostic_updater::DiagnosticStatusWrapper &stat) {
00057                 const int satellites_visible_ = satellites_visible;
00058                 const int fix_type_ = fix_type;
00059                 const uint16_t eph_ = eph;
00060                 const uint16_t epv_ = epv;
00061 
00062                 if (satellites_visible_ < 0)
00063                         stat.summary(2, "No satellites");
00064                 else if (fix_type_ < 2 || fix_type_ > 3)
00065                         stat.summary(1, "No fix");
00066                 else if (fix_type_ == 2)
00067                         stat.summary(0, "2D fix");
00068                 else if (fix_type_ == 3)
00069                         stat.summary(0, "3D fix");
00070 
00071                 stat.addf("Satellites visible", "%zd", satellites_visible_);
00072                 stat.addf("Fix type", "%d", fix_type_);
00073 
00074                 // EPH in centimeters
00075                 if (eph_ != UINT16_MAX)
00076                         stat.addf("EPH (m)", "%.2f", eph_ / 1E2F);
00077                 else
00078                         stat.add("EPH (m)", "Unknown");
00079 
00080                 // EPV in centimeters
00081                 if (epv_ != UINT16_MAX)
00082                         stat.addf("EPV (m)", "%.2f", epv_ / 1E2F);
00083                 else
00084                         stat.add("EPV (m)", "Unknown");
00085         }
00086 
00087 private:
00088         std::atomic<int> satellites_visible;
00089         std::atomic<int> fix_type;
00090         std::atomic<uint16_t> eph;
00091         std::atomic<uint16_t> epv;
00092 };
00093 
00094 
00100 class GPSPlugin : public MavRosPlugin {
00101 public:
00102         GPSPlugin() :
00103                 uas(nullptr),
00104                 gps_diag("GPS")
00105         { };
00106 
00107         void initialize(UAS &uas_,
00108                         ros::NodeHandle &nh,
00109                         diagnostic_updater::Updater &diag_updater)
00110         {
00111                 uas = &uas_;
00112 
00113                 nh.param<std::string>("gps/frame_id", frame_id, "gps");
00114                 nh.param<std::string>("gps/time_ref_source", time_ref_source, frame_id);
00115 
00116                 diag_updater.add(gps_diag);
00117 
00118                 fix_pub = nh.advertise<sensor_msgs::NavSatFix>("fix", 10);
00119                 time_ref_pub = nh.advertise<sensor_msgs::TimeReference>("time_reference", 10);
00120                 vel_pub = nh.advertise<geometry_msgs::TwistStamped>("gps_vel", 10);
00121         }
00122 
00123         std::string const get_name() const {
00124                 return "GPS";
00125         }
00126 
00127         const message_map get_rx_handlers() {
00128                 return {
00129                         MESSAGE_HANDLER(MAVLINK_MSG_ID_GPS_RAW_INT, &GPSPlugin::handle_gps_raw_int),
00130                         MESSAGE_HANDLER(MAVLINK_MSG_ID_GPS_STATUS, &GPSPlugin::handle_gps_status),
00131                 };
00132         }
00133 
00134 private:
00135         UAS *uas;
00136         std::string frame_id;
00137         std::string time_ref_source;
00138 
00139         GPSInfo gps_diag;
00140 
00141         ros::Publisher fix_pub;
00142         ros::Publisher time_ref_pub;
00143         ros::Publisher vel_pub;
00144 
00145         void handle_gps_raw_int(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {
00146                 mavlink_gps_raw_int_t raw_gps;
00147                 mavlink_msg_gps_raw_int_decode(msg, &raw_gps);
00148 
00149                 sensor_msgs::NavSatFixPtr fix = boost::make_shared<sensor_msgs::NavSatFix>();
00150                 geometry_msgs::TwistStampedPtr vel = boost::make_shared<geometry_msgs::TwistStamped>();
00151 
00152                 gps_diag.set_gps_raw(raw_gps);
00153                 if (raw_gps.fix_type < 2) {
00154                         ROS_WARN_THROTTLE_NAMED(60, "gps", "GPS: no fix");
00155                         return;
00156                 }
00157 
00158                 fix->status.service = sensor_msgs::NavSatStatus::SERVICE_GPS;
00159                 if (raw_gps.fix_type == 2 || raw_gps.fix_type == 3)
00160                         fix->status.status = sensor_msgs::NavSatStatus::STATUS_FIX;
00161                 else
00162                         fix->status.status = sensor_msgs::NavSatStatus::STATUS_NO_FIX;
00163 
00164                 fix->latitude = raw_gps.lat / 1E7; // deg
00165                 fix->longitude = raw_gps.lon / 1E7; // deg
00166                 fix->altitude = raw_gps.alt / 1E3; // m
00167 
00168                 if (raw_gps.eph != UINT16_MAX) {
00169                         double hdop = raw_gps.eph / 1E2;
00170                         double hdop2 = std::pow(hdop, 2);
00171 
00172                         // TODO: Check
00173                         // From nmea_navsat_driver
00174                         fix->position_covariance[0] = hdop2;
00175                         fix->position_covariance[4] = hdop2;
00176                         fix->position_covariance[8] = std::pow(2 * hdop, 2);
00177                         fix->position_covariance_type =
00178                                 sensor_msgs::NavSatFix::COVARIANCE_TYPE_APPROXIMATED;
00179                 }
00180                 else {
00181                         fix->position_covariance_type =
00182                                 sensor_msgs::NavSatFix::COVARIANCE_TYPE_UNKNOWN;
00183                 }
00184 
00185                 fix->header.frame_id = frame_id;
00186                 fix->header.stamp = ros::Time::now();
00187 
00188                 // store GPS data in UAS
00189                 double eph = (raw_gps.eph != UINT16_MAX)? raw_gps.eph / 1E2 : NAN;
00190                 double epv = (raw_gps.epv != UINT16_MAX)? raw_gps.epv / 1E2 : NAN;
00191                 uas->set_gps_llae(fix->latitude, fix->longitude, fix->altitude, eph, epv);
00192                 uas->set_gps_status(fix->status.status == sensor_msgs::NavSatStatus::STATUS_FIX);
00193 
00194                 fix_pub.publish(fix);
00195 
00196                 if (raw_gps.vel != UINT16_MAX &&
00197                                 raw_gps.cog != UINT16_MAX) {
00198                         double speed = raw_gps.vel / 1E2; // m/s
00199                         double course = angles::from_degrees(raw_gps.cog / 1E2); // rad
00200 
00201                         // From nmea_navsat_driver
00202                         vel->twist.linear.x = speed * std::sin(course);
00203                         vel->twist.linear.y = speed * std::cos(course);
00204 
00205                         vel->header.frame_id = frame_id;
00206                         vel->header.stamp = fix->header.stamp;
00207 
00208                         vel_pub.publish(vel);
00209                 }
00210         }
00211 
00212         void handle_gps_status(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {
00213                 // TODO: not supported by APM:Plane,
00214                 //       no standard ROS messages
00215                 mavlink_gps_status_t gps_stat;
00216                 mavlink_msg_gps_status_decode(msg, &gps_stat);
00217 
00218                 ROS_INFO_THROTTLE_NAMED(30, "gps", "GPS stat sat visible: %d", gps_stat.satellites_visible);
00219         }
00220 
00221 };
00222 
00223 }; // namespace mavplugin
00224 
00225 PLUGINLIB_EXPORT_CLASS(mavplugin::GPSPlugin, mavplugin::MavRosPlugin)
00226 


mavros
Author(s): Vladimir Ermakov
autogenerated on Wed Aug 26 2015 12:29:13