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"),
50  fcu_map_id_des("map"),
51  fcu_odom_parent_id_des("odom"),
52  fcu_odom_child_id_des("base_link")
53  { }
54 
55  void initialize(UAS &uas_) override
56  {
58 
59  // frame params:
60  odom_nh.param<std::string>("fcu/odom_parent_id_des", fcu_odom_parent_id_des, uas_.get_odom_frame_id());
61  odom_nh.param<std::string>("fcu/odom_child_id_des", fcu_odom_child_id_des, uas_.get_base_link_frame_id());
62  odom_nh.param<std::string>("fcu/map_id_des", fcu_map_id_des, uas_.get_map_frame_id());
63 
64  // publishers
65  odom_pub = odom_nh.advertise<nav_msgs::Odometry>("in", 10);
66 
67  // subscribers
69  }
70 
72  {
73  return {
75  };
76  }
77 
78 private:
82 
83  std::string fcu_odom_parent_id_des;
84  std::string fcu_odom_child_id_des;
85  std::string fcu_map_id_des;
86 
93  void lookup_static_transform(const std::string &target, const std::string &source,
94  Eigen::Affine3d &tf_source2target)
95  {
96  try {
97  // transform lookup at current time.
99  target, source, ros::Time(0)));
100  } catch (tf2::TransformException &ex) {
101  ROS_ERROR_THROTTLE_NAMED(1, "odom", "ODOM: Ex: %s", ex.what());
102  return;
103  }
104  }
105 
120  void handle_odom(const mavlink::mavlink_message_t *msg, mavlink::common::msg::ODOMETRY &odom_msg)
121  {
125  Eigen::Affine3d tf_parent2parent_des;
126  Eigen::Affine3d tf_child2child_des;
127 
128  lookup_static_transform(fcu_map_id_des, fcu_map_id_des+"_ned", tf_parent2parent_des);
130 
132  Matrix6d cov_pose = Matrix6d::Zero();
133  ftf::mavlink_urt_to_covariance_matrix(odom_msg.pose_covariance, cov_pose);
134 
136  Matrix6d cov_vel = Matrix6d::Zero();
137  ftf::mavlink_urt_to_covariance_matrix(odom_msg.velocity_covariance, cov_vel);
138 
139  Eigen::Vector3d position {};
140  Eigen::Quaterniond orientation {};
141  Eigen::Vector3d lin_vel {};
142  Eigen::Vector3d ang_vel {};
143  Matrix6d r_pose = Matrix6d::Zero();
144  Matrix6d r_vel = Matrix6d::Zero();
145 
146  auto odom = boost::make_shared<nav_msgs::Odometry>();
147 
148  odom->header = m_uas->synchronized_header(fcu_map_id_des, odom_msg.time_usec);
149  odom->child_frame_id = fcu_odom_child_id_des;
150 
154  position = Eigen::Vector3d(tf_parent2parent_des.linear() * Eigen::Vector3d(odom_msg.x, odom_msg.y, odom_msg.z));
155  tf::pointEigenToMsg(position, odom->pose.pose.position);
156 
160  Eigen::Quaterniond q_child2parent(ftf::mavlink_to_quaternion(odom_msg.q));
161  Eigen::Affine3d tf_childDes2parentDes = tf_parent2parent_des * q_child2parent * tf_child2child_des.inverse();
162  orientation = Eigen::Quaterniond(tf_childDes2parentDes.linear());
163  tf::quaternionEigenToMsg(orientation, odom->pose.pose.orientation);
164 
169  lin_vel = Eigen::Vector3d(tf_child2child_des.linear() * Eigen::Vector3d(odom_msg.vx, odom_msg.vy, odom_msg.vz));
170  ang_vel = Eigen::Vector3d(tf_child2child_des.linear() * Eigen::Vector3d(odom_msg.rollspeed, odom_msg.pitchspeed, odom_msg.yawspeed));
171  tf::vectorEigenToMsg(lin_vel, odom->twist.twist.linear);
172  tf::vectorEigenToMsg(ang_vel, odom->twist.twist.angular);
173 
177  r_pose.block<3, 3>(0, 0) = r_pose.block<3, 3>(3, 3) = tf_parent2parent_des.linear();
179  cov_pose = r_pose * cov_pose * r_pose.transpose();
180  Eigen::Map<Matrix6d>(odom->pose.covariance.data(), cov_pose.rows(), cov_pose.cols()) = cov_pose;
181 
183  r_vel.block<3, 3>(0, 0) = r_vel.block<3, 3>(3, 3) = tf_child2child_des.linear();
184  cov_vel = r_vel * cov_vel * r_vel.transpose();
185  Eigen::Map<Matrix6d>(odom->twist.covariance.data(), cov_vel.rows(), cov_vel.cols()) = cov_vel;
186 
188  odom_pub.publish(odom);
189  }
190 
202  {
206  Eigen::Affine3d tf_parent2parent_des;
207  Eigen::Affine3d tf_child2child_des;
208 
209  lookup_static_transform(fcu_odom_parent_id_des+"_ned", odom->header.frame_id, tf_parent2parent_des);
210  lookup_static_transform(fcu_odom_child_id_des+"_frd", odom->child_frame_id, tf_child2child_des);
211 
213  ftf::Covariance6d cov_pose = odom->pose.covariance;
214  ftf::EigenMapCovariance6d cov_pose_map(cov_pose.data());
215 
217  ftf::Covariance6d cov_vel = odom->twist.covariance;
218  ftf::EigenMapCovariance6d cov_vel_map(cov_vel.data());
219 
223  Eigen::Vector3d position {};
224  Eigen::Quaterniond orientation {};
225  Eigen::Vector3d lin_vel {};
226  Eigen::Vector3d ang_vel {};
227  Matrix6d r_pose = Matrix6d::Zero();
228  Matrix6d r_vel = Matrix6d::Zero();
229 
230  mavlink::common::msg::ODOMETRY msg {};
231  msg.frame_id = utils::enum_value(MAV_FRAME::LOCAL_FRD);
232  msg.child_frame_id = utils::enum_value(MAV_FRAME::BODY_FRD);
233  msg.estimator_type = utils::enum_value(MAV_ESTIMATOR_TYPE::VISION);
234 
238  position = Eigen::Vector3d(tf_parent2parent_des.linear() * ftf::to_eigen(odom->pose.pose.position));
239 
243  Eigen::Quaterniond q_child2parent(ftf::to_eigen(odom->pose.pose.orientation));
244  Eigen::Affine3d tf_childDes2parentDes = tf_parent2parent_des * q_child2parent * tf_child2child_des.inverse();
245  orientation = Eigen::Quaterniond(tf_childDes2parentDes.linear());
246 
250  lin_vel = Eigen::Vector3d(tf_child2child_des.linear() * ftf::to_eigen(odom->twist.twist.linear));
251  ang_vel = Eigen::Vector3d(tf_child2child_des.linear() * ftf::to_eigen(odom->twist.twist.angular));
252 
254  r_pose.block<3, 3>(0, 0) = r_pose.block<3, 3>(3, 3) = tf_parent2parent_des.linear();
255  r_vel.block<3, 3>(0, 0) = r_vel.block<3, 3>(3, 3) = tf_child2child_des.linear();
256  cov_pose_map = r_pose * cov_pose_map * r_pose.transpose();
257  cov_vel_map = r_vel * cov_vel_map * r_vel.transpose();
258 
259  ROS_DEBUG_STREAM_NAMED("odom", "ODOM: output: pose covariance matrix:" << std::endl << cov_pose_map);
260  ROS_DEBUG_STREAM_NAMED("odom", "ODOM: output: velocity covariance matrix:" << std::endl << cov_vel_map);
261 
262  /* -*- ODOMETRY msg parser -*- */
263  msg.time_usec = odom->header.stamp.toNSec() / 1e3;
264 
265  // [[[cog:
266  // for a, b in (('', 'position'), ('v', 'lin_vel')):
267  // for f in 'xyz':
268  // cog.outl("msg.{a}{f} = {b}.{f}();".format(**locals()))
269  // for a, b in zip("xyz", ('rollspeed', 'pitchspeed', 'yawspeed')):
270  // cog.outl("msg.{b} = ang_vel.{a}();".format(**locals()))
271  // ]]]
272  msg.x = position.x();
273  msg.y = position.y();
274  msg.z = position.z();
275  msg.vx = lin_vel.x();
276  msg.vy = lin_vel.y();
277  msg.vz = lin_vel.z();
278  msg.rollspeed = ang_vel.x();
279  msg.pitchspeed = ang_vel.y();
280  msg.yawspeed = ang_vel.z();
281  // [[[end]]] (checksum: ead24a1a6a14496c9de6c1951ccfbbd7)
282 
283  ftf::quaternion_to_mavlink(orientation, msg.q);
284  ftf::covariance_urt_to_mavlink(cov_pose_map, msg.pose_covariance);
285  ftf::covariance_urt_to_mavlink(cov_vel_map, msg.velocity_covariance);
286 
287  // send ODOMETRY msg
288  UAS_FCU(m_uas)->send_message_ignore_drop(msg);
289  }
290 };
291 } // namespace extra_plugins
292 } // namespace mavros
293 
mavros::extra_plugins::OdometryPlugin::fcu_map_id_des
std::string fcu_map_id_des
desired orientation of the fcu map frame
Definition: odom.cpp:85
mavros::plugin::PluginBase::m_uas
UAS * m_uas
ROS_ERROR_THROTTLE_NAMED
#define ROS_ERROR_THROTTLE_NAMED(period, name,...)
mavros::extra_plugins::OdometryPlugin::odom_cb
void odom_cb(const nav_msgs::Odometry::ConstPtr &odom)
Sends odometry data msgs to the FCU.
Definition: odom.cpp:201
mavros::plugin::PluginBase::Subscriptions
std::vector< HandlerInfo > Subscriptions
mavros::extra_plugins::Matrix6d
Eigen::Matrix< double, 6, 6, Eigen::RowMajor > Matrix6d
Definition: odom.cpp:30
msg
msg
ros::Publisher
mavros::ftf::mavlink_urt_to_covariance_matrix
void mavlink_urt_to_covariance_matrix(const std::array< float, ARR_SIZE > &covmsg, T &covmat)
tf2_eigen.h
ROS_DEBUG_STREAM_NAMED
#define ROS_DEBUG_STREAM_NAMED(name, args)
mavros::plugin::PluginBase::PluginBase
PluginBase()
UAS_FCU
#define UAS_FCU(uasobjptr)
mavros::UAS
mavros::extra_plugins::OdometryPlugin::fcu_odom_parent_id_des
std::string fcu_odom_parent_id_des
desired orientation of the fcu odometry message's parent frame
Definition: odom.cpp:83
mavros::UAS::get_map_frame_id
std::string get_map_frame_id()
ConstPtr
std::shared_ptr< MAVConnInterface const > ConstPtr
mavros::UAS::tf2_buffer
tf2_ros::Buffer tf2_buffer
mavros::extra_plugins::OdometryPlugin::initialize
void initialize(UAS &uas_) override
Definition: odom.cpp:55
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
mavros::ftf::to_eigen
Eigen::Vector3d to_eigen(const geometry_msgs::Point r)
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
mavros::extra_plugins::OdometryPlugin::fcu_odom_child_id_des
std::string fcu_odom_child_id_des
desired orientation of the fcu odometry message's child frame
Definition: odom.cpp:84
mavros::ftf::mavlink_to_quaternion
Eigen::Quaterniond mavlink_to_quaternion(const std::array< float, 4 > &q)
tf::vectorEigenToMsg
void vectorEigenToMsg(const Eigen::Vector3d &e, geometry_msgs::Vector3 &m)
PLUGINLIB_EXPORT_CLASS
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
mavros_plugin.h
tf::pointEigenToMsg
void pointEigenToMsg(const Eigen::Vector3d &e, geometry_msgs::Point &m)
mavros::extra_plugins::OdometryPlugin::lookup_static_transform
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:93
mavros::extra_plugins::OdometryPlugin::get_subscriptions
Subscriptions get_subscriptions() override
Definition: odom.cpp:71
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
mavros::UAS::get_odom_frame_id
std::string get_odom_frame_id()
mavros::ftf::EigenMapCovariance6d
Eigen::Map< Eigen::Matrix< double, 6, 6, Eigen::RowMajor > > EigenMapCovariance6d
mavros::extra_plugins::OdometryPlugin::odom_pub
ros::Publisher odom_pub
nav_msgs/Odometry publisher
Definition: odom.cpp:80
tf2::transformToEigen
Eigen::Isometry3d transformToEigen(const geometry_msgs::Transform &t)
mavros::extra_plugins::OdometryPlugin::odom_sub
ros::Subscriber odom_sub
nav_msgs/Odometry subscriber
Definition: odom.cpp:81
mavros::extra_plugins::OdometryPlugin::odom_nh
ros::NodeHandle odom_nh
node handler
Definition: odom.cpp:79
mavros
mavros::UAS::get_base_link_frame_id
std::string get_base_link_frame_id()
mavros::UAS::synchronized_header
std_msgs::Header synchronized_header(const std::string &frame_id, const T time_stamp)
ros::Time
tf::quaternionEigenToMsg
void quaternionEigenToMsg(const Eigen::Quaterniond &e, geometry_msgs::Quaternion &m)
initialize
virtual void initialize(UAS &uas)
mavros::plugin::PluginBase
mavros::extra_plugins::OdometryPlugin::OdometryPlugin
EIGEN_MAKE_ALIGNED_OPERATOR_NEW OdometryPlugin()
Definition: odom.cpp:48
class_list_macros.hpp
mavros::extra_plugins::OdometryPlugin::handle_odom
void handle_odom(const mavlink::mavlink_message_t *msg, mavlink::common::msg::ODOMETRY &odom_msg)
Handle ODOMETRY MAVlink message.
Definition: odom.cpp:120
ros::NodeHandle::param
T param(const std::string &param_name, const T &default_val) const
mavros::extra_plugins::OdometryPlugin
Odometry plugin.
Definition: odom.cpp:44
mavros::ftf::covariance_urt_to_mavlink
void covariance_urt_to_mavlink(const T &covmap, std::array< float, ARR_SIZE > &covmsg)
mavros::plugin::PluginBase::make_handler
HandlerInfo make_handler(const mavlink::msgid_t id, void(_C::*fn)(const mavlink::mavlink_message_t *msg, const mavconn::Framing framing))
tf2::TransformException
mavros::utils::enum_value
constexpr std::underlying_type< _T >::type enum_value(_T e)
tf2_ros::Buffer::lookupTransform
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const ros::Time &target_time, const std::string &source_frame, const ros::Time &source_time, const std::string &fixed_frame, const ros::Duration timeout) const
ros::NodeHandle
ros::Subscriber
mavros::ftf::quaternion_to_mavlink
void quaternion_to_mavlink(const Eigen::Quaternion< _Scalar > &q, std::array< float, 4 > &qmsg)
mavros::ftf::Covariance6d
geometry_msgs::PoseWithCovariance::_covariance_type Covariance6d


mavros_extras
Author(s): Vladimir Ermakov , Amilcar Lucas
autogenerated on Tue May 6 2025 02:34:08