00001
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <mavros/mavros_plugin.h>
00019 #include <mavros/setpoint_mixin.h>
00020 #include <pluginlib/class_list_macros.h>
00021 #include <eigen_conversions/eigen_msg.h>
00022
00023 #include <geometry_msgs/PoseStamped.h>
00024 #include <geometry_msgs/PoseWithCovarianceStamped.h>
00025
00026 namespace mavplugin {
00034 class VisionPoseEstimatePlugin : public MavRosPlugin,
00035 private TF2ListenerMixin<VisionPoseEstimatePlugin> {
00036 public:
00037 VisionPoseEstimatePlugin() :
00038 sp_nh("~vision_pose"),
00039 uas(nullptr),
00040 tf_rate(10.0)
00041 { };
00042
00043 void initialize(UAS &uas_)
00044 {
00045 bool tf_listen;
00046
00047 uas = &uas_;
00048
00049
00050 sp_nh.param("tf/listen", tf_listen, false);
00051 sp_nh.param<std::string>("tf/frame_id", tf_frame_id, "map");
00052 sp_nh.param<std::string>("tf/child_frame_id", tf_child_frame_id, "vision");
00053 sp_nh.param("tf/rate_limit", tf_rate, 50.0);
00054
00055 if (tf_listen) {
00056 ROS_INFO_STREAM_NAMED("vision_pose", "Listen to vision transform " << tf_frame_id
00057 << " -> " << tf_child_frame_id);
00058 tf2_start("VisionPoseTF", &VisionPoseEstimatePlugin::transform_cb);
00059 }
00060 else {
00061 vision_sub = sp_nh.subscribe("pose", 10, &VisionPoseEstimatePlugin::vision_cb, this);
00062 vision_cov_sub = sp_nh.subscribe("pose_cov", 10, &VisionPoseEstimatePlugin::vision_cov_cb, this);
00063 }
00064 }
00065
00066 const message_map get_rx_handlers() {
00067 return { };
00068 }
00069
00070 private:
00071 friend class TF2ListenerMixin;
00072 ros::NodeHandle sp_nh;
00073 UAS *uas;
00074
00075 ros::Subscriber vision_sub;
00076 ros::Subscriber vision_cov_sub;
00077
00078 std::string tf_frame_id;
00079 std::string tf_child_frame_id;
00080 double tf_rate;
00081 ros::Time last_transform_stamp;
00082
00083
00084
00085 void vision_position_estimate(uint64_t usec,
00086 float x, float y, float z,
00087 float roll, float pitch, float yaw) {
00088 mavlink_message_t msg;
00089 mavlink_msg_vision_position_estimate_pack_chan(UAS_PACK_CHAN(uas), &msg,
00090 usec,
00091 x,
00092 y,
00093 z,
00094 roll,
00095 pitch,
00096 yaw);
00097 UAS_FCU(uas)->send_message(&msg);
00098 }
00099
00100
00101
00105 void send_vision_estimate(const ros::Time &stamp, const Eigen::Affine3d &tr) {
00110 if (last_transform_stamp == stamp) {
00111 ROS_DEBUG_THROTTLE_NAMED(10, "vision_pose", "Vision: Same transform as last one, dropped.");
00112 return;
00113 }
00114 last_transform_stamp = stamp;
00115
00116 auto position = UAS::transform_frame_enu_ned(Eigen::Vector3d(tr.translation()));
00117 auto rpy = UAS::quaternion_to_rpy(
00118 UAS::transform_orientation_enu_ned(Eigen::Quaterniond(tr.rotation())));
00119
00120 vision_position_estimate(stamp.toNSec() / 1000,
00121 position.x(), position.y(), position.z(),
00122 rpy.x(), rpy.y(), rpy.z());
00123 }
00124
00125
00126
00127
00128
00129 void transform_cb(const geometry_msgs::TransformStamped &transform) {
00130 Eigen::Affine3d tr;
00131 tf::transformMsgToEigen(transform.transform, tr);
00132
00133 send_vision_estimate(transform.header.stamp, tr);
00134 }
00135
00136 void vision_cb(const geometry_msgs::PoseStamped::ConstPtr &req) {
00137 Eigen::Affine3d tr;
00138 tf::poseMsgToEigen(req->pose, tr);
00139
00140 send_vision_estimate(req->header.stamp, tr);
00141 }
00142
00143 void vision_cov_cb(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr &req) {
00144 Eigen::Affine3d tr;
00145 tf::poseMsgToEigen(req->pose.pose, tr);
00146
00147 send_vision_estimate(req->header.stamp, tr);
00148 }
00149 };
00150 };
00151
00152 PLUGINLIB_EXPORT_CLASS(mavplugin::VisionPoseEstimatePlugin, mavplugin::MavRosPlugin)