setpoint_attitude.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/setpoint_mixin.h>
00030 #include <pluginlib/class_list_macros.h>
00031 
00032 #include <geometry_msgs/PoseStamped.h>
00033 #include <geometry_msgs/PoseWithCovarianceStamped.h>
00034 #include <geometry_msgs/TwistStamped.h>
00035 #include <std_msgs/Float64.h>
00036 
00037 namespace mavplugin {
00038 
00044 class SetpointAttitudePlugin : public MavRosPlugin,
00045         private TFListenerMixin<SetpointAttitudePlugin> {
00046 public:
00047         SetpointAttitudePlugin() :
00048                 uas(nullptr),
00049                 tf_rate(10.0),
00050                 reverse_throttle(false)
00051         { };
00052 
00053         void initialize(UAS &uas_,
00054                         ros::NodeHandle &nh,
00055                         diagnostic_updater::Updater &diag_updater)
00056         {
00057                 bool pose_with_covariance;
00058                 bool listen_tf;
00059                 bool listen_twist;
00060 
00061                 uas = &uas_;
00062                 sp_nh = ros::NodeHandle(nh, "setpoint");
00063 
00064                 sp_nh.param("attitude/listen_twist", listen_twist, true);
00065                 sp_nh.param("attitude/pose_with_covariance", pose_with_covariance, false);
00066                 // may be used to mimic attitude of an object, a gesture, etc.
00067                 sp_nh.param("attitude/listen_tf", listen_tf, false);
00068                 sp_nh.param<std::string>("attitude/frame_id", frame_id, "local_origin");
00069                 sp_nh.param<std::string>("attitude/child_frame_id", child_frame_id, "attitude");
00070                 sp_nh.param("attitude/tf_rate_limit", tf_rate, 10.0);
00071                 sp_nh.param("attitude/reverse_throttle", reverse_throttle, false);
00072 
00073                 if (listen_tf) {
00074                         ROS_INFO_STREAM_NAMED("attitude", "Listen to desired attitude transform " << frame_id
00075                                         << " -> " << child_frame_id);
00076                         tf_start("AttitudeSpTF", &SetpointAttitudePlugin::send_attitude_transform);
00077                 }
00078                 else if (listen_twist) {
00079                         ROS_DEBUG_NAMED("attitude", "Setpoint attitude topic type: Twist");
00080                         att_sub = sp_nh.subscribe("cmd_vel", 10, &SetpointAttitudePlugin::twist_cb, this);
00081                 }
00082                 else if (pose_with_covariance) {
00083                         ROS_DEBUG_NAMED("attitude", "Setpoint attitude topic type: PoseWithCovarianceStamped");
00084                         att_sub = sp_nh.subscribe("attitude", 10, &SetpointAttitudePlugin::pose_cov_cb, this);
00085                 }
00086                 else {
00087                         ROS_DEBUG_NAMED("attitude", "Setpoint attitude topic type: PoseStamped");
00088                         att_sub = sp_nh.subscribe("attitude", 10, &SetpointAttitudePlugin::pose_cb, this);
00089                 }
00090 
00091                 throttle_sub = sp_nh.subscribe("att_throttle", 10, &SetpointAttitudePlugin::throttle_cb, this);
00092         }
00093 
00094         const std::string get_name() const {
00095                 return "SetpointAttitude";
00096         }
00097 
00098         const message_map get_rx_handlers() {
00099                 return { /* Rx disabled */ };
00100         }
00101 
00102 private:
00103         friend class TFListenerMixin;
00104         UAS *uas;
00105 
00106         ros::NodeHandle sp_nh;
00107         ros::Subscriber att_sub;
00108         ros::Subscriber throttle_sub;
00109 
00110         std::string frame_id;
00111         std::string child_frame_id;
00112 
00113         double tf_rate;
00114         bool reverse_throttle;
00115 
00116         /* -*- low-level send -*- */
00117 
00118         void set_attitude_target(uint32_t time_boot_ms,
00119                         uint8_t type_mask,
00120                         float q[4],
00121                         float roll_rate, float pitch_rate, float yaw_rate,
00122                         float thrust) {
00123                 mavlink_message_t msg;
00124                 mavlink_msg_set_attitude_target_pack_chan(UAS_PACK_CHAN(uas), &msg,
00125                                 time_boot_ms,
00126                                 UAS_PACK_TGT(uas),
00127                                 type_mask,
00128                                 q,
00129                                 roll_rate, pitch_rate, yaw_rate,
00130                                 thrust);
00131                 UAS_FCU(uas)->send_message(&msg);
00132         }
00133 
00134         /* -*- mid-level helpers -*- */
00135 
00141         void send_attitude_transform(const tf::Transform &transform, const ros::Time &stamp) {
00142                 // Thrust + RPY, also bits noumbering started from 1 in docs
00143                 const uint8_t ignore_all_except_q = (1<<6)|(7<<0);
00144                 float q[4];
00145 
00146                 // ENU->NED, description in #49.
00147                 tf::Quaternion tf_q = transform.getRotation();
00148                 q[0] = tf_q.w();
00149                 q[1] = tf_q.y();
00150                 q[2] = tf_q.x();
00151                 q[3] = -tf_q.z();
00152 
00153                 set_attitude_target(stamp.toNSec() / 1000000,
00154                                 ignore_all_except_q,
00155                                 q,
00156                                 0.0, 0.0, 0.0,
00157                                 0.0);
00158         }
00159 
00165         void send_attitude_ang_velocity(const ros::Time &stamp, const float vx, const float vy, const float vz) {
00166                 // Q + Thrust, also bits noumbering started from 1 in docs
00167                 const uint8_t ignore_all_except_rpy = (1<<7)|(1<<6);
00168                 float q[4] = { 1.0, 0.0, 0.0, 0.0 };
00169 
00170                 set_attitude_target(stamp.toNSec() / 1000000,
00171                                 ignore_all_except_rpy,
00172                                 q,
00173                                 vy, vx, -vz,
00174                                 0.0);
00175         }
00176 
00180         void send_attitude_throttle(const float throttle) {
00181                 // Q + RPY
00182                 const uint8_t ignore_all_except_throttle = (1<<7)|(7<<0);
00183                 float q[4] = { 1.0, 0.0, 0.0, 0.0 };
00184 
00185                 set_attitude_target(ros::Time::now().toNSec() / 1000000,
00186                                 ignore_all_except_throttle,
00187                                 q,
00188                                 0.0, 0.0, 0.0,
00189                                 throttle);
00190         }
00191 
00192         /* -*- callbacks -*- */
00193 
00194         void pose_cov_cb(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr &req) {
00195                 tf::Transform transform;
00196                 poseMsgToTF(req->pose.pose, transform);
00197                 send_attitude_transform(transform, req->header.stamp);
00198         }
00199 
00200         void pose_cb(const geometry_msgs::PoseStamped::ConstPtr &req) {
00201                 tf::Transform transform;
00202                 poseMsgToTF(req->pose, transform);
00203                 send_attitude_transform(transform, req->header.stamp);
00204         }
00205 
00206         void twist_cb(const geometry_msgs::TwistStamped::ConstPtr &req) {
00207                 send_attitude_ang_velocity(
00208                                 req->header.stamp,
00209                                 req->twist.angular.x,
00210                                 req->twist.angular.y,
00211                                 req->twist.angular.z);
00212         }
00213 
00214         inline bool is_normalized(float throttle, const float min, const float max) {
00215                 if (throttle < min) {
00216                         ROS_WARN_NAMED("attitude", "Not normalized throttle! Thd(%f) < Min(%f)", throttle, min);
00217                         return false;
00218                 }
00219                 else if (throttle > max) {
00220                         ROS_WARN_NAMED("attitude", "Not normalized throttle! Thd(%f) > Max(%f)", throttle, max);
00221                         return false;
00222                 }
00223 
00224                 return true;
00225         }
00226 
00227         void throttle_cb(const std_msgs::Float64::ConstPtr &req) {
00228                 float throttle_normalized = req->data;
00229 
00230                 // note: && are lazy, is_normalized() should be called only if reverse_throttle are true.
00231                 if (reverse_throttle && !is_normalized(throttle_normalized, -1.0, 1.0))
00232                         return;
00233                 else if (!is_normalized(throttle_normalized, 0.0, 1.0))
00234                         return;
00235 
00236                 send_attitude_throttle(throttle_normalized);
00237         }
00238 };
00239 
00240 }; // namespace mavplugin
00241 
00242 PLUGINLIB_EXPORT_CLASS(mavplugin::SetpointAttitudePlugin, mavplugin::MavRosPlugin)


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