00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00075 if (eph_ != UINT16_MAX)
00076 stat.addf("EPH (m)", "%.2f", eph_ / 1E2F);
00077 else
00078 stat.add("EPH (m)", "Unknown");
00079
00080
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;
00165 fix->longitude = raw_gps.lon / 1E7;
00166 fix->altitude = raw_gps.alt / 1E3;
00167
00168 if (raw_gps.eph != UINT16_MAX) {
00169 double hdop = raw_gps.eph / 1E2;
00170 double hdop2 = std::pow(hdop, 2);
00171
00172
00173
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
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;
00199 double course = angles::from_degrees(raw_gps.cog / 1E2);
00200
00201
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
00214
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 };
00224
00225 PLUGINLIB_EXPORT_CLASS(mavplugin::GPSPlugin, mavplugin::MavRosPlugin)
00226