00001
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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 { };
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
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
00135
00141 void send_attitude_transform(const tf::Transform &transform, const ros::Time &stamp) {
00142
00143 const uint8_t ignore_all_except_q = (1<<6)|(7<<0);
00144 float q[4];
00145
00146
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
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
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
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
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 };
00241
00242 PLUGINLIB_EXPORT_CLASS(mavplugin::SetpointAttitudePlugin, mavplugin::MavRosPlugin)