setpoint_position.cpp
Go to the documentation of this file.
1 
9 /*
10  * Copyright 2014,2016 Vladimir Ermakov.
11  *
12  * This file is part of the mavros package and subject to the license terms
13  * in the top-level LICENSE file of the mavros repository.
14  * https://github.com/mavlink/mavros/tree/master/LICENSE.md
15  */
16 
17 #include <mavros/mavros_plugin.h>
18 #include <mavros/setpoint_mixin.h>
20 
21 #include <geometry_msgs/PoseStamped.h>
22 
23 #include <mavros_msgs/SetMavFrame.h>
24 #include <mavros_msgs/GlobalPositionTarget.h>
25 
26 #include <GeographicLib/Geocentric.hpp>
27 //#include <GeographicLib/Geoid.hpp>
28 
29 namespace mavros {
30 namespace std_plugins {
31 using mavlink::common::MAV_FRAME;
38  private plugin::SetPositionTargetLocalNEDMixin<SetpointPositionPlugin>,
39  private plugin::TF2ListenerMixin<SetpointPositionPlugin> {
40 public:
41  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
42 
44  sp_nh("~setpoint_position"),
45  spg_nh("~"),
46  tf_rate(50.0),
47  tf_listen(false)
48  { }
49 
50  void initialize(UAS &uas_)
51  {
52  PluginBase::initialize(uas_);
53 
54  // tf params
55  sp_nh.param("tf/listen", tf_listen, false);
56  sp_nh.param<std::string>("tf/frame_id", tf_frame_id, "map");
57  sp_nh.param<std::string>("tf/child_frame_id", tf_child_frame_id, "target_position");
58  sp_nh.param("tf/rate_limit", tf_rate, 50.0);
59 
60  if (tf_listen) {
61  ROS_INFO_STREAM_NAMED("setpoint", "Listen to position setpoint transform "
62  << tf_frame_id << " -> " << tf_child_frame_id);
64  }
65  else {
67  // Subscriber for goal gps
69 
70  // subscriber for current gps state, mavros/global_position/global.
71  gps_sub = spg_nh.subscribe("global_position/global", 10, &SetpointPositionPlugin::gps_cb, this);
72  // Subscribe for current local ENU pose.
73  local_sub = spg_nh.subscribe("local_position/pose", 10, &SetpointPositionPlugin::local_cb, this);
74  }
76 
77  // mav_frame
78  std::string mav_frame_str;
79  if (!sp_nh.getParam("mav_frame", mav_frame_str)) {
80  mav_frame = MAV_FRAME::LOCAL_NED;
81  } else {
82  mav_frame = utils::mav_frame_from_str(mav_frame_str);
83  }
84  }
85 
87  {
88  return { /* Rx disabled */ };
89  }
90 
91 private:
93  friend class TF2ListenerMixin;
94 
102 
103  /* Stores current gps state. */
104  //sensor_msgs::NavSatFix current_gps_msg;
105  Eigen::Vector3d current_gps;
106  Eigen::Vector3d current_local_pos;
107  uint32_t old_gps_stamp = 0;
108 
109  std::string tf_frame_id;
110  std::string tf_child_frame_id;
111 
112  bool tf_listen;
113  double tf_rate;
114 
116 
117  /* -*- mid-level helpers -*- */
118 
124  void send_position_target(const ros::Time &stamp, const Eigen::Affine3d &tr)
125  {
126  using mavlink::common::MAV_FRAME;
127 
128  /* Documentation start from bit 1 instead 0;
129  * Ignore velocity and accel vectors, yaw rate.
130  *
131  * In past versions on PX4 there been bug described in #273.
132  * If you got similar issue please try update firmware first.
133  */
134  const uint16_t ignore_all_except_xyz_y = (1 << 11) | (7 << 6) | (7 << 3);
135 
136  auto p = [&] () {
137  if (static_cast<MAV_FRAME>(mav_frame) == MAV_FRAME::BODY_NED || static_cast<MAV_FRAME>(mav_frame) == MAV_FRAME::BODY_OFFSET_NED) {
138  return ftf::transform_frame_baselink_aircraft(Eigen::Vector3d(tr.translation()));
139  } else {
140  return ftf::transform_frame_enu_ned(Eigen::Vector3d(tr.translation()));
141  }
142  } ();
143 
144  auto q = [&] () {
145  if (mav_frame == MAV_FRAME::BODY_NED || mav_frame == MAV_FRAME::BODY_OFFSET_NED) {
146  return ftf::transform_orientation_baselink_aircraft(Eigen::Quaterniond(tr.rotation()));
147  } else {
149  ftf::transform_orientation_baselink_aircraft(Eigen::Quaterniond(tr.rotation())));
150  }
151  } ();
152 
153  set_position_target_local_ned(stamp.toNSec() / 1000000,
154  utils::enum_value(mav_frame),
155  ignore_all_except_xyz_y,
156  p,
157  Eigen::Vector3d::Zero(),
158  Eigen::Vector3d::Zero(),
159  ftf::quaternion_get_yaw(q), 0.0);
160  }
161 
162  /* -*- callbacks -*- */
163 
164  /* common TF listener moved to mixin */
165  void transform_cb(const geometry_msgs::TransformStamped &transform)
166  {
167  Eigen::Affine3d tr;
168  // TODO: later, when tf2 5.12 will be released need to revisit and replace this to
169  // tf2::convert()
170  tf::transformMsgToEigen(transform.transform, tr);
171 
172  send_position_target(transform.header.stamp, tr);
173  }
174 
176  {
177  Eigen::Affine3d tr;
178  tf::poseMsgToEigen(req->pose, tr);
179 
180  send_position_target(req->header.stamp, tr);
181  }
182 
187  {
196  GeographicLib::Geocentric earth(GeographicLib::Constants::WGS84_a(), GeographicLib::Constants::WGS84_f());
197 
198  Eigen::Vector3d goal_gps(req->latitude, req->longitude, req->altitude);
199 
200  // current gps -> curent ECEF
201  Eigen::Vector3d current_ecef;
202  earth.Forward(current_gps.x(), current_gps.y(), current_gps.z(),
203  current_ecef.x(), current_ecef.y(), current_ecef.z());
204 
205  // goal gps -> goal ECEF
206  Eigen::Vector3d goal_ecef;
207  earth.Forward(goal_gps.x(), goal_gps.y(), goal_gps.z(),
208  goal_ecef.x(), goal_ecef.y(), goal_ecef.z());
209 
210  // get ENU offset from ECEF offset
211  Eigen::Vector3d ecef_offset = goal_ecef - current_ecef;
212  Eigen::Vector3d enu_offset = ftf::transform_frame_ecef_enu(ecef_offset, current_gps);
213 
214  // prepare yaw angle
215  Eigen::Affine3d sp; // holds position setpoint
216  Eigen::Quaterniond q; // holds desired yaw
217 
218  q = Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitX()) // roll
219  * Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitY()) // pitch
220  * Eigen::AngleAxisd(req->yaw, Eigen::Vector3d::UnitZ()); // yaw
221 
222  // set position setpoint
223  sp.translation() = current_local_pos + enu_offset;
224  // set desired orientation
225  sp.linear() = q.toRotationMatrix();
226 
227  // Only send if current gps is updated, to avoid divergence
228  if ((req->header.stamp.toNSec() / 1000000) > old_gps_stamp) {
229  old_gps_stamp = req->header.stamp.toNSec() / 1000000;
230  send_position_target(req->header.stamp, sp);
231  }
232  else {
233  ROS_WARN_THROTTLE_NAMED(10, "spgp", "SPG: sp not sent.");
234  }
235  }
236 
241  {
242  current_gps = {msg->latitude, msg->longitude, msg->altitude};
243  }
244 
249  {
250  current_local_pos = ftf::to_eigen(msg->pose.position);
251  }
252 
253  bool set_mav_frame_cb(mavros_msgs::SetMavFrame::Request &req, mavros_msgs::SetMavFrame::Response &res)
254  {
255  mav_frame = static_cast<MAV_FRAME>(req.mav_frame);
256  const std::string mav_frame_str = utils::to_string(mav_frame);
257  sp_nh.setParam("mav_frame", mav_frame_str);
258  res.success = true;
259  return true;
260  }
261 };
262 } // namespace std_plugins
263 } // namespace mavros
264 
MAVROS Plugin base class.
Definition: mavros_plugin.h:37
std::shared_ptr< MAVConnInterface const > ConstPtr
ros::Subscriber setpointg_sub
GPS setpoint.
mavlink::common::MAV_FRAME mav_frame_from_str(const std::string &mav_frame)
Retreive MAV_FRAME from name.
bool set_mav_frame_cb(mavros_msgs::SetMavFrame::Request &req, mavros_msgs::SetMavFrame::Response &res)
#define ROS_WARN_THROTTLE_NAMED(period, name,...)
void setpointg_cb(const mavros_msgs::GlobalPositionTarget::ConstPtr &req)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
MAVROS Plugin base.
void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e)
This mixin adds TF2 listener thread to plugin.
uint32_t old_gps_stamp
old time gps time stamp in [ms], to check if new gps msg is received
void tf2_start(const char *_thd_name, void(SetpointPositionPlugin::*cbp)(const geometry_msgs::TransformStamped &))
start tf listener
#define ROS_INFO_STREAM_NAMED(name, args)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void set_position_target_local_ned(uint32_t time_boot_ms, uint8_t coordinate_frame, uint16_t type_mask, Eigen::Vector3d p, Eigen::Vector3d v, Eigen::Vector3d af, float yaw, float yaw_rate)
Message specification: https://mavlink.io/en/messages/common.html#SET_POSITION_TARGET_LOCAL_NED.
void setpoint_cb(const geometry_msgs::PoseStamped::ConstPtr &req)
T transform_orientation_enu_ned(const T &in)
Transform from attitude represented WRT ENU frame to attitude represented WRT NED frame...
Definition: frame_tf.h:161
void local_cb(const geometry_msgs::PoseStamped::ConstPtr &msg)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW SetpointPositionPlugin()
PluginBase()
Plugin constructor Should not do anything before initialize()
Definition: mavros_plugin.h:75
UAS for plugins.
Definition: mavros_uas.h:66
bool param(const std::string &param_name, T &param_val, const T &default_val) const
Eigen::Vector3d current_gps
geodetic coordinates LLA
Mixin for setpoint plugins.
Subscriptions get_subscriptions()
Return vector of MAVLink message subscriptions (handlers)
std::string to_string(timesync_mode e)
uint64_t toNSec() const
Eigen::Vector3d to_eigen(const geometry_msgs::Point r)
Helper to convert common ROS geometry_msgs::Point to Eigen::Vector3d.
Definition: frame_tf.h:423
T transform_frame_baselink_aircraft(const T &in)
Transform data expressed in Baselink frame to Aircraft frame.
Definition: frame_tf.h:214
T transform_frame_enu_ned(const T &in)
Transform data expressed in ENU to NED frame.
Definition: frame_tf.h:196
void transformMsgToEigen(const geometry_msgs::Transform &m, Eigen::Affine3d &e)
void gps_cb(const sensor_msgs::NavSatFix::ConstPtr &msg)
void transform_cb(const geometry_msgs::TransformStamped &transform)
This mixin adds set_position_target_local_ned()
std::vector< HandlerInfo > Subscriptions
Subscriptions vector.
Definition: mavros_plugin.h:48
double quaternion_get_yaw(const Eigen::Quaterniond &q)
Get Yaw angle from quaternion.
bool getParam(const std::string &key, std::string &s) const
T transform_frame_ecef_enu(const T &in, const T &map_origin)
Transform data expressed in ECEF frame to ENU frame.
Definition: frame_tf.h:226
T transform_orientation_baselink_aircraft(const T &in)
Transform from attitude represented WRT baselink frame to attitude represented WRT body frame...
Definition: frame_tf.h:179
void send_position_target(const ros::Time &stamp, const Eigen::Affine3d &tr)
Send setpoint to FCU position controller.
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
void initialize(UAS &uas_)
Plugin initializer.
ros::NodeHandle spg_nh
to get local position and gps coord which are not under sp_h()
ros::Subscriber local_sub
current local ENU
constexpr std::underlying_type< _T >::type enum_value(_T e)
Definition: utils.h:55
Eigen::Vector3d current_local_pos
Current local position in ENU.


mavros
Author(s): Vladimir Ermakov
autogenerated on Mon Jul 8 2019 03:20:11