odom.cpp
Go to the documentation of this file.
1 
10 /*
11  * Copyright 2017 James Goppert
12  * Copyright 2017,2018 Nuno Marques
13  *
14  * This file is part of the mavros package and subject to the license terms
15  * in the top-level LICENSE file of the mavros repository.
16  * https://github.com/mavlink/mavros/tree/master/LICENSE.md
17  */
18 
19 #include <mavros/mavros_plugin.h>
20 #include <tf2_eigen/tf2_eigen.h>
21 #include <boost/algorithm/string.hpp>
22 
23 #include <nav_msgs/Odometry.h>
24 #include <geometry_msgs/TransformStamped.h>
25 
26 namespace mavros {
27 namespace extra_plugins {
28 using mavlink::common::MAV_FRAME;
29 using mavlink::common::MAV_ESTIMATOR_TYPE;
30 using Matrix6d = Eigen::Matrix<double, 6, 6, Eigen::RowMajor>;
31 
45 public:
46  EIGEN_MAKE_ALIGNED_OPERATOR_NEW // XXX(vooon): added to try to fix #1223. Not sure that it is needed because class do not have Eigen:: fields.
47 
49  odom_nh("~odometry"),
51  fcu_odom_child_id_des("base_link")
52  { }
53 
54  void initialize(UAS &uas_) override
55  {
57 
58  // frame params:
59  odom_nh.param<std::string>("fcu/odom_parent_id_des", fcu_odom_parent_id_des, "map");
60  odom_nh.param<std::string>("fcu/odom_child_id_des", fcu_odom_child_id_des, "base_link");
61 
62  // publishers
63  odom_pub = odom_nh.advertise<nav_msgs::Odometry>("in", 10);
64 
65  // subscribers
67  }
68 
70  {
71  return {
73  };
74  }
75 
76 private:
80 
81  std::string fcu_odom_parent_id_des;
82  std::string fcu_odom_child_id_des;
83 
90  void lookup_static_transform(const std::string &target, const std::string &source,
91  Eigen::Affine3d &tf_source2target)
92  {
93  try {
94  // transform lookup at current time.
96  target, source, ros::Time(0)));
97  } catch (tf2::TransformException &ex) {
98  ROS_ERROR_THROTTLE_NAMED(1, "odom", "ODOM: Ex: %s", ex.what());
99  return;
100  }
101  }
102 
117  void handle_odom(const mavlink::mavlink_message_t *msg, mavlink::common::msg::ODOMETRY &odom_msg)
118  {
122  Eigen::Affine3d tf_parent2parent_des;
123  Eigen::Affine3d tf_child2child_des;
124 
125  lookup_static_transform(fcu_odom_parent_id_des, "map_ned", tf_parent2parent_des);
126  lookup_static_transform( fcu_odom_child_id_des, "base_link_frd", tf_child2child_des);
127 
129  Matrix6d cov_pose = Matrix6d::Zero();
130  ftf::mavlink_urt_to_covariance_matrix(odom_msg.pose_covariance, cov_pose);
131 
133  Matrix6d cov_vel = Matrix6d::Zero();
134  ftf::mavlink_urt_to_covariance_matrix(odom_msg.velocity_covariance, cov_vel);
135 
136  Eigen::Vector3d position {};
137  Eigen::Quaterniond orientation {};
138  Eigen::Vector3d lin_vel {};
139  Eigen::Vector3d ang_vel {};
140  Matrix6d r_pose = Matrix6d::Zero();
141  Matrix6d r_vel = Matrix6d::Zero();
142 
143  auto odom = boost::make_shared<nav_msgs::Odometry>();
144 
145  odom->header = m_uas->synchronized_header(fcu_odom_parent_id_des, odom_msg.time_usec);
146  odom->child_frame_id = fcu_odom_child_id_des;
147 
151  position = Eigen::Vector3d(tf_parent2parent_des.linear() * Eigen::Vector3d(odom_msg.x, odom_msg.y, odom_msg.z));
152  tf::pointEigenToMsg(position, odom->pose.pose.position);
153 
157  Eigen::Quaterniond q_child2parent(ftf::mavlink_to_quaternion(odom_msg.q));
158  Eigen::Affine3d tf_childDes2parentDes = tf_parent2parent_des * q_child2parent * tf_child2child_des.inverse();
159  orientation = Eigen::Quaterniond(tf_childDes2parentDes.linear());
160  tf::quaternionEigenToMsg(orientation, odom->pose.pose.orientation);
161 
166  lin_vel = Eigen::Vector3d(tf_child2child_des.linear() * Eigen::Vector3d(odom_msg.vx, odom_msg.vy, odom_msg.vz));
167  ang_vel = Eigen::Vector3d(tf_child2child_des.linear() * Eigen::Vector3d(odom_msg.rollspeed, odom_msg.pitchspeed, odom_msg.yawspeed));
168  tf::vectorEigenToMsg(lin_vel, odom->twist.twist.linear);
169  tf::vectorEigenToMsg(ang_vel, odom->twist.twist.angular);
170 
174  r_pose.block<3, 3>(0, 0) = r_pose.block<3, 3>(3, 3) = tf_parent2parent_des.linear();
176  cov_pose = r_pose * cov_pose * r_pose.transpose();
177  Eigen::Map<Matrix6d>(odom->pose.covariance.data(), cov_pose.rows(), cov_pose.cols()) = cov_pose;
178 
180  r_vel.block<3, 3>(0, 0) = r_vel.block<3, 3>(3, 3) = tf_child2child_des.linear();
181  cov_vel = r_vel * cov_vel * r_vel.transpose();
182  Eigen::Map<Matrix6d>(odom->twist.covariance.data(), cov_vel.rows(), cov_vel.cols()) = cov_vel;
183 
185  odom_pub.publish(odom);
186  }
187 
199  {
203  Eigen::Affine3d tf_parent2parent_des;
204  Eigen::Affine3d tf_child2child_des;
205 
206  lookup_static_transform("odom_ned", odom->header.frame_id, tf_parent2parent_des);
207  lookup_static_transform("base_link_frd", odom->child_frame_id, tf_child2child_des);
208 
210  ftf::Covariance6d cov_pose = odom->pose.covariance;
211  ftf::EigenMapCovariance6d cov_pose_map(cov_pose.data());
212 
214  ftf::Covariance6d cov_vel = odom->twist.covariance;
215  ftf::EigenMapCovariance6d cov_vel_map(cov_vel.data());
216 
220  Eigen::Vector3d position {};
221  Eigen::Quaterniond orientation {};
222  Eigen::Vector3d lin_vel {};
223  Eigen::Vector3d ang_vel {};
224  Matrix6d r_pose = Matrix6d::Zero();
225  Matrix6d r_vel = Matrix6d::Zero();
226 
227  mavlink::common::msg::ODOMETRY msg {};
228  msg.frame_id = utils::enum_value(MAV_FRAME::LOCAL_FRD);
229  msg.child_frame_id = utils::enum_value(MAV_FRAME::BODY_FRD);
230  msg.estimator_type = utils::enum_value(MAV_ESTIMATOR_TYPE::VISION);
231 
235  position = Eigen::Vector3d(tf_parent2parent_des.linear() * ftf::to_eigen(odom->pose.pose.position));
236 
240  Eigen::Quaterniond q_child2parent(ftf::to_eigen(odom->pose.pose.orientation));
241  Eigen::Affine3d tf_childDes2parentDes = tf_parent2parent_des * q_child2parent * tf_child2child_des.inverse();
242  orientation = Eigen::Quaterniond(tf_childDes2parentDes.linear());
243 
247  lin_vel = Eigen::Vector3d(tf_child2child_des.linear() * ftf::to_eigen(odom->twist.twist.linear));
248  ang_vel = Eigen::Vector3d(tf_child2child_des.linear() * ftf::to_eigen(odom->twist.twist.angular));
249 
251  r_pose.block<3, 3>(0, 0) = r_pose.block<3, 3>(3, 3) = tf_parent2parent_des.linear();
252  r_vel.block<3, 3>(0, 0) = r_vel.block<3, 3>(3, 3) = tf_child2child_des.linear();
253  cov_pose_map = r_pose * cov_pose_map * r_pose.transpose();
254  cov_vel_map = r_vel * cov_vel_map * r_vel.transpose();
255 
256  ROS_DEBUG_STREAM_NAMED("odom", "ODOM: output: pose covariance matrix:" << std::endl << cov_pose_map);
257  ROS_DEBUG_STREAM_NAMED("odom", "ODOM: output: velocity covariance matrix:" << std::endl << cov_vel_map);
258 
259  /* -*- ODOMETRY msg parser -*- */
260  msg.time_usec = odom->header.stamp.toNSec() / 1e3;
261 
262  // [[[cog:
263  // for a, b in (('', 'position'), ('v', 'lin_vel')):
264  // for f in 'xyz':
265  // cog.outl("msg.{a}{f} = {b}.{f}();".format(**locals()))
266  // for a, b in zip("xyz", ('rollspeed', 'pitchspeed', 'yawspeed')):
267  // cog.outl("msg.{b} = ang_vel.{a}();".format(**locals()))
268  // ]]]
269  msg.x = position.x();
270  msg.y = position.y();
271  msg.z = position.z();
272  msg.vx = lin_vel.x();
273  msg.vy = lin_vel.y();
274  msg.vz = lin_vel.z();
275  msg.rollspeed = ang_vel.x();
276  msg.pitchspeed = ang_vel.y();
277  msg.yawspeed = ang_vel.z();
278  // [[[end]]] (checksum: ead24a1a6a14496c9de6c1951ccfbbd7)
279 
280  ftf::quaternion_to_mavlink(orientation, msg.q);
281  ftf::covariance_urt_to_mavlink(cov_pose_map, msg.pose_covariance);
282  ftf::covariance_urt_to_mavlink(cov_vel_map, msg.velocity_covariance);
283 
284  // send ODOMETRY msg
285  UAS_FCU(m_uas)->send_message_ignore_drop(msg);
286  }
287 };
288 } // namespace extra_plugins
289 } // namespace mavros
290 
msg
void lookup_static_transform(const std::string &target, const std::string &source, Eigen::Affine3d &tf_source2target)
Lookup static transform with error handling.
Definition: odom.cpp:90
std::shared_ptr< MAVConnInterface const > ConstPtr
std_msgs::Header synchronized_header(const std::string &frame_id, const T time_stamp)
Subscriptions get_subscriptions() override
Definition: odom.cpp:69
ros::Subscriber odom_sub
nav_msgs/Odometry subscriber
Definition: odom.cpp:79
#define ROS_DEBUG_STREAM_NAMED(name, args)
void publish(const boost::shared_ptr< M > &message) const
void quaternionEigenToMsg(const Eigen::Quaterniond &e, geometry_msgs::Quaternion &m)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
Eigen::Matrix< double, 6, 6, Eigen::RowMajor > Matrix6d
Definition: odom.cpp:30
HandlerInfo make_handler(const mavlink::msgid_t id, void(_C::*fn)(const mavlink::mavlink_message_t *msg, const mavconn::Framing framing))
Eigen::Quaterniond mavlink_to_quaternion(const std::array< float, 4 > &q)
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
Eigen::Map< Eigen::Matrix< double, 6, 6, Eigen::RowMajor > > EigenMapCovariance6d
void quaternion_to_mavlink(const Eigen::Quaternion< _Scalar > &q, std::array< float, 4 > &qmsg)
std::string fcu_odom_child_id_des
desired orientation of the fcu odometry message&#39;s child frame
Definition: odom.cpp:82
EIGEN_MAKE_ALIGNED_OPERATOR_NEW OdometryPlugin()
Definition: odom.cpp:48
void mavlink_urt_to_covariance_matrix(const std::array< float, ARR_SIZE > &covmsg, T &covmat)
tf2_ros::Buffer tf2_buffer
void vectorEigenToMsg(const Eigen::Vector3d &e, geometry_msgs::Vector3 &m)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ros::NodeHandle odom_nh
node handler
Definition: odom.cpp:77
#define UAS_FCU(uasobjptr)
void handle_odom(const mavlink::mavlink_message_t *msg, mavlink::common::msg::ODOMETRY &odom_msg)
Handle ODOMETRY MAVlink message.
Definition: odom.cpp:117
#define ROS_ERROR_THROTTLE_NAMED(rate, name,...)
Eigen::Vector3d to_eigen(const geometry_msgs::Point r)
void covariance_urt_to_mavlink(const T &covmap, std::array< float, ARR_SIZE > &covmsg)
geometry_msgs::PoseWithCovariance::_covariance_type Covariance6d
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void pointEigenToMsg(const Eigen::Vector3d &e, geometry_msgs::Point &m)
void odom_cb(const nav_msgs::Odometry::ConstPtr &odom)
Sends odometry data msgs to the FCU.
Definition: odom.cpp:198
std::vector< HandlerInfo > Subscriptions
void initialize(UAS &uas_) override
ros::Publisher odom_pub
nav_msgs/Odometry publisher
Definition: odom.cpp:78
std::string fcu_odom_parent_id_des
desired orientation of the fcu odometry message&#39;s parent frame
Definition: odom.cpp:81
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
Eigen::Isometry3d transformToEigen(const geometry_msgs::Transform &t)
void initialize(UAS &uas_) override
Definition: odom.cpp:54
constexpr std::underlying_type< _T >::type enum_value(_T e)


mavros_extras
Author(s): Vladimir Ermakov , Amilcar Lucas
autogenerated on Tue Jun 1 2021 02:36:36