global_position.cpp
Go to the documentation of this file.
00001 
00010 /*
00011  * Copyright 2014 Nuno Marques.
00012  *
00013  * This program is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 3 of the License, or
00016  * (at your option) any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful, but
00019  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00021  * for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License along
00024  * with this program; if not, write to the Free Software Foundation, Inc.,
00025  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00026  */
00027 
00028 #include <mavros/mavros_plugin.h>
00029 #include <mavros/gps_conversions.h>
00030 #include <pluginlib/class_list_macros.h>
00031 
00032 #include <tf/transform_broadcaster.h>
00033 #include <tf/transform_datatypes.h>
00034 #include <geometry_msgs/PoseWithCovarianceStamped.h>
00035 #include <sensor_msgs/NavSatFix.h>
00036 #include <sensor_msgs/NavSatStatus.h>
00037 #include <geometry_msgs/Vector3Stamped.h>
00038 #include <geometry_msgs/Quaternion.h>
00039 #include <std_msgs/Float64.h>
00040 #include <std_msgs/Header.h>
00041 
00042 namespace mavplugin {
00043 
00051 class GlobalPositionPlugin : public MavRosPlugin {
00052 public:
00053         GlobalPositionPlugin() :
00054                 uas(nullptr),
00055                 send_tf(false),
00056                 rot_cov(99999.0)
00057         { };
00058 
00059         void initialize(UAS &uas_,
00060                         ros::NodeHandle &nh,
00061                         diagnostic_updater::Updater &diag_updater)
00062         {
00063                 uas = &uas_;
00064 
00065                 gp_nh = ros::NodeHandle(nh, "global_position");
00066 
00067                 gp_nh.param("send_tf", send_tf, true);
00068                 gp_nh.param<std::string>("frame_id", frame_id, "local_origin");
00069                 gp_nh.param<std::string>("child_frame_id", child_frame_id, "fcu");
00070                 gp_nh.param<double>("rot_covariance", rot_cov, 99999.0);
00071 
00072                 fix_pub = gp_nh.advertise<sensor_msgs::NavSatFix>("global", 10);
00073                 pos_pub = gp_nh.advertise<geometry_msgs::PoseWithCovarianceStamped>("local", 10);
00074                 vel_pub = gp_nh.advertise<geometry_msgs::Vector3Stamped>("gps_vel", 10);
00075                 rel_alt_pub = gp_nh.advertise<std_msgs::Float64>("rel_alt", 10);
00076                 hdg_pub = gp_nh.advertise<std_msgs::Float64>("compass_hdg", 10);
00077         }
00078 
00079         std::string const get_name() const {
00080                 return "GlobalPosition";
00081         }
00082 
00083         const message_map get_rx_handlers() {
00084                 return {
00085                         MESSAGE_HANDLER(MAVLINK_MSG_ID_GLOBAL_POSITION_INT, &GlobalPositionPlugin::handle_global_position_int)
00086                 };
00087         }
00088 
00089 private:
00090         UAS *uas;
00091 
00092         ros::NodeHandle gp_nh;
00093         ros::Publisher fix_pub;
00094         ros::Publisher pos_pub;
00095         ros::Publisher vel_pub;
00096         ros::Publisher hdg_pub;
00097         ros::Publisher rel_alt_pub;
00098 
00099         tf::TransformBroadcaster tf_broadcaster;
00100 
00101         std::string frame_id;           
00102         std::string child_frame_id;     
00103         bool send_tf;
00104         double rot_cov;
00105 
00110         void handle_global_position_int(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {
00111                 mavlink_global_position_int_t gp_pos;
00112                 mavlink_msg_global_position_int_decode(msg, &gp_pos);
00113 
00114                 ROS_DEBUG_THROTTLE_NAMED(10, "global", "Global position: boot_ms:%06d "
00115                                 "lat/lon/alt:(%d %d %d) relative_alt: (%d) gps_vel:(%d %d %d) compass_heading: (%d)",
00116                                 gp_pos.time_boot_ms,
00117                                 gp_pos.lat, gp_pos.lon, gp_pos.alt, gp_pos.relative_alt,
00118                                 gp_pos.vx, gp_pos.vy, gp_pos.vz, gp_pos.hdg);
00119 
00120                 geometry_msgs::PoseWithCovarianceStampedPtr pose_cov =
00121                         boost::make_shared<geometry_msgs::PoseWithCovarianceStamped>();
00122 
00123                 std_msgs::Header header;
00124                 header.frame_id = frame_id;
00125                 header.stamp = ros::Time::now();
00126 
00127                 sensor_msgs::NavSatFixPtr gps_cord =
00128                         boost::make_shared<sensor_msgs::NavSatFix>();
00129                 geometry_msgs::Vector3StampedPtr gps_vel =
00130                         boost::make_shared<geometry_msgs::Vector3Stamped>();
00131                 std_msgs::Float64Ptr relative_alt = boost::make_shared<std_msgs::Float64>();
00132                 std_msgs::Float64Ptr compass_heading = boost::make_shared<std_msgs::Float64>();
00133 
00134                 gps_cord->header = header;
00135                 gps_cord->latitude = gp_pos.lat / 1E7;
00136                 gps_cord->longitude = gp_pos.lon / 1E7;
00137                 gps_cord->altitude = gp_pos.alt / 1E3; // in meters
00138 
00139                 // fill GPS status fields
00140                 gps_cord->status.service = sensor_msgs::NavSatStatus::SERVICE_GPS;
00141                 if (uas->get_gps_status())
00142                         gps_cord->status.status = sensor_msgs::NavSatStatus::STATUS_FIX;
00143                 else
00144                         gps_cord->status.status = sensor_msgs::NavSatStatus::STATUS_NO_FIX;
00145 
00146                 // try compute LLA covariance from GPS_RAW_INT data
00147                 double hdop = uas->get_gps_eph();
00148                 if (!isnan(hdop)) {
00149                         double hdop2 = std::pow(hdop, 2);
00150 
00151                         // From nmea_navsat_driver
00152                         gps_cord->position_covariance[0] = hdop2;
00153                         gps_cord->position_covariance[4] = hdop2;
00154                         gps_cord->position_covariance[8] = std::pow(2 * hdop, 2);
00155                         gps_cord->position_covariance_type =
00156                                 sensor_msgs::NavSatFix::COVARIANCE_TYPE_APPROXIMATED;
00157                 }
00158                 else {
00159                         gps_cord->position_covariance_type =
00160                                 sensor_msgs::NavSatFix::COVARIANCE_TYPE_UNKNOWN;
00161                 }
00162 
00163                 gps_vel->header = header;
00164                 gps_vel->vector.x = gp_pos.vx / 1E2; // in m/s
00165                 gps_vel->vector.y = gp_pos.vy / 1E2;
00166                 gps_vel->vector.z = gp_pos.vz / 1E2;
00167 
00168                 relative_alt->data = gp_pos.relative_alt / 1E3; // in meters
00169                 if (gp_pos.hdg != UINT16_MAX)
00170                         compass_heading->data = gp_pos.hdg / 1E2; // in degrees
00171 
00172                 double northing, easting;
00173                 std::string zone;
00174 
00178                 UTM::LLtoUTM(gps_cord->latitude, gps_cord->longitude, northing, easting, zone);
00179 
00180                 pose_cov->header = header;
00181                 pose_cov->pose.pose.position.x = easting;
00182                 pose_cov->pose.pose.position.y = northing;
00183                 pose_cov->pose.pose.position.z = gp_pos.relative_alt / 1E3;
00184 
00185                 geometry_msgs::Quaternion q_aux;
00186                 tf::Quaternion q(uas->get_attitude_orientation());
00187                 tf::quaternionTFToMsg(q, q_aux);
00188                 pose_cov->pose.pose.orientation = q_aux;
00189 
00190                 // Use ENU covariance to build XYZRPY covariance
00191                 boost::array<double, 36> covariance = {
00192                         gps_cord->position_covariance[0],
00193                         gps_cord->position_covariance[1],
00194                         gps_cord->position_covariance[2],
00195                         0, 0, 0,
00196                         gps_cord->position_covariance[3],
00197                         gps_cord->position_covariance[4],
00198                         gps_cord->position_covariance[5],
00199                         0, 0, 0,
00200                         gps_cord->position_covariance[6],
00201                         gps_cord->position_covariance[7],
00202                         gps_cord->position_covariance[8],
00203                         0, 0, 0,
00204                         0, 0, 0, rot_cov, 0, 0,
00205                         0, 0, 0, 0, rot_cov, 0,
00206                         0, 0, 0, 0, 0, rot_cov
00207                 };
00208 
00209                 pose_cov->pose.covariance = covariance;
00210 
00211                 fix_pub.publish(gps_cord);
00212                 pos_pub.publish(pose_cov);
00213                 vel_pub.publish(gps_vel);
00214                 rel_alt_pub.publish(relative_alt);
00215                 if (gp_pos.hdg != UINT16_MAX)
00216                         hdg_pub.publish(compass_heading);
00217 
00218                 if (send_tf) {
00219                         tf::Transform transform;
00220                         // XXX: we realy need change frame?
00221                         transform.setOrigin(tf::Vector3(pose_cov->pose.pose.position.y,
00222                                                 pose_cov->pose.pose.position.x,
00223                                                 -pose_cov->pose.pose.position.z));
00224 
00225                         transform.setRotation(uas->get_attitude_orientation());
00226 
00227                         tf_broadcaster.sendTransform(
00228                                         tf::StampedTransform(
00229                                                 transform,
00230                                                 pose_cov->header.stamp,
00231                                                 frame_id, child_frame_id));
00232                 }
00233         }
00234 };
00235 
00236 }; // namespace mavplugin
00237 
00238 PLUGINLIB_EXPORT_CLASS(mavplugin::GlobalPositionPlugin, mavplugin::MavRosPlugin)


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