helpers.h
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2012-2016, Institute of Flight Systems and Automatic Control,
3 // Technische Universität Darmstadt.
4 // All rights reserved.
5 
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of hector_quadrotor nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
29 #ifndef HECTOR_QUADROTOR_INTERFACE_HELPERS_H
30 #define HECTOR_QUADROTOR_INTERFACE_HELPERS_H
31 
32 #include <geometry_msgs/PoseStamped.h>
33 #include <sensor_msgs/Imu.h>
34 #include <nav_msgs/Odometry.h>
35 #include <geometry_msgs/Pose.h>
36 #include <geometry_msgs/Twist.h>
37 #include <geometry_msgs/Accel.h>
38 #include <geometry_msgs/TransformStamped.h>
39 
40 #include <hector_uav_msgs/AttitudeCommand.h>
41 #include <hector_uav_msgs/YawrateCommand.h>
42 #include <hector_uav_msgs/ThrustCommand.h>
43 #include <std_msgs/Header.h>
44 
45 #include <ros/ros.h>
46 #include <boost/thread/mutex.hpp>
47 #include <boost/circular_buffer.hpp>
51 
53 {
54 
56 {
57 public:
58  ImuSubscriberHelper(ros::NodeHandle nh, std::string topic, sensor_msgs::Imu &imu)
59  : imu_(imu)
60  {
61  imu_sub_ = nh.subscribe<sensor_msgs::Imu>(topic, 1, boost::bind(&ImuSubscriberHelper::imuCallback, this, _1));
62  }
63 
65  {
67  }
68 
69 private:
70  sensor_msgs::Imu &imu_;
72 
73  void imuCallback(const sensor_msgs::ImuConstPtr &imu)
74  {
75  imu_ = *imu;
76  }
77 
78 };
79 
80 // TODO switch to shapeshifter
81 
83 {
84 public:
85  OdomSubscriberHelper(ros::NodeHandle nh, std::string topic, geometry_msgs::Pose &pose, geometry_msgs::Twist &twist,
86  geometry_msgs::Accel &acceleration, std_msgs::Header &header)
87  : pose_(pose), twist_(twist), acceleration_(acceleration), header_(header)
88  {
89  odom_sub_ = nh.subscribe<nav_msgs::Odometry>(topic, 1,
90  boost::bind(&OdomSubscriberHelper::odomCallback, this, _1));
91  }
92 
94  {
95  odom_sub_.shutdown();
96  }
97 
98 private:
100 
101  geometry_msgs::Pose &pose_;
102  geometry_msgs::Twist &twist_;
103  geometry_msgs::Accel &acceleration_;
104  std_msgs::Header header_;
105 
106  void odomCallback(const nav_msgs::OdometryConstPtr &odom)
107  {
108  // calculate acceleration
109  if (!header_.stamp.isZero() && !odom->header.stamp.isZero())
110  {
111  const double acceleration_time_constant = 0.1;
112  double dt((odom->header.stamp - header_.stamp).toSec());
113  if (dt > 0.0)
114  {
115  acceleration_.linear.x =
116  ((odom->twist.twist.linear.x - twist_.linear.x) + acceleration_time_constant * acceleration_.linear.x) /
117  (dt + acceleration_time_constant);
118  acceleration_.linear.y =
119  ((odom->twist.twist.linear.y - twist_.linear.y) + acceleration_time_constant * acceleration_.linear.y) /
120  (dt + acceleration_time_constant);
121  acceleration_.linear.z =
122  ((odom->twist.twist.linear.z - twist_.linear.z) + acceleration_time_constant * acceleration_.linear.z) /
123  (dt + acceleration_time_constant);
124  acceleration_.angular.x = ((odom->twist.twist.angular.x - twist_.angular.x) +
125  acceleration_time_constant * acceleration_.angular.x) /
126  (dt + acceleration_time_constant);
127  acceleration_.angular.y = ((odom->twist.twist.angular.y - twist_.angular.y) +
128  acceleration_time_constant * acceleration_.angular.y) /
129  (dt + acceleration_time_constant);
130  acceleration_.angular.z = ((odom->twist.twist.angular.z - twist_.angular.z) +
131  acceleration_time_constant * acceleration_.angular.z) /
132  (dt + acceleration_time_constant);
133  }
134  }
135 
136  header_ = odom->header;
137  pose_ = odom->pose.pose;
138  twist_ = odom->twist.twist;
139  }
140 
141 };
142 
144 {
145 public:
146  PoseSubscriberHelper(ros::NodeHandle nh, std::string topic)
147  {
148  pose_sub_ = nh.subscribe<geometry_msgs::PoseStamped>(topic, 1,
149  boost::bind(&PoseSubscriberHelper::poseCallback, this,
150  _1));
151  }
152 
154  {
155  pose_sub_.shutdown();
156  }
157 
158  geometry_msgs::PoseStampedConstPtr get() const { return pose_; }
159 
160 private:
162 
163  geometry_msgs::PoseStampedConstPtr pose_;
164 
165  void poseCallback(const geometry_msgs::PoseStampedConstPtr &pose)
166  {
167  pose_ = pose;
168  }
169 
170 };
171 
173 {
174 public:
175  void updateAndEstimate(const ros::Time &time, const geometry_msgs::Pose &pose, geometry_msgs::Twist &twist,
176  geometry_msgs::Accel &accel)
177  {
178 
179  if (last_pose_)
180  {
181 
182  double dt = (time - last_time_).toSec();
183  double roll, pitch, yaw, last_roll, last_pitch, last_yaw;
184  tf2::Quaternion q;
185 
186  tf2::fromMsg(pose.orientation, q);
187  tf2::Matrix3x3(q).getRPY(roll, pitch, yaw);
188 
189  tf2::fromMsg(last_pose_->orientation, q);
190  tf2::Matrix3x3(q).getRPY(last_roll, last_pitch, last_yaw);
191 
192  twist.linear.x = (pose.position.x - last_pose_->position.x) / dt;
193  twist.linear.y = (pose.position.y - last_pose_->position.y) / dt;
194  twist.linear.z = (pose.position.z - last_pose_->position.z) / dt;
195  twist.angular.x = differenceWithWraparound(roll, last_roll) / dt;
196  twist.angular.y = differenceWithWraparound(pitch, last_pitch) / dt;
197  twist.angular.z = differenceWithWraparound(yaw, last_yaw) / dt;
198 
199  if (last_twist_)
200  {
201  accel.linear.x = (twist.linear.x - last_twist_->linear.x) / dt;
202  accel.linear.y = (twist.linear.y - last_twist_->linear.y) / dt;
203  accel.linear.z = (twist.linear.z - last_twist_->linear.z) / dt;
204 
205  accel.angular.x = (twist.angular.x - last_twist_->angular.x) / dt;
206  accel.angular.y = (twist.angular.y - last_twist_->angular.y) / dt;
207  accel.angular.z = (twist.angular.z - last_twist_->angular.z) / dt;
208  *last_twist_ = twist;
209  }
210  else
211  {
212  last_twist_ = boost::make_shared<geometry_msgs::Twist>(twist);
213  }
214  *last_pose_ = pose;
215 
216  }
217  else
218  {
219  last_pose_ = boost::make_shared<geometry_msgs::Pose>(pose);
220  }
221  last_time_ = time;
222 
223  }
224 
225 private:
226  geometry_msgs::PosePtr last_pose_;
227  geometry_msgs::TwistPtr last_twist_;
229 
230  double differenceWithWraparound(double angle, double last_angle)
231  {
232 
233  double diff = angle - last_angle;
234  if (diff > M_PI)
235  {
236  return diff - 2 * M_PI;
237  }
238  else if (diff < -M_PI)
239  {
240  return diff + 2 * M_PI;
241  }
242  else
243  {
244  return diff;
245  }
246 
247  }
248 
249 };
250 
252 {
253 public:
254  StateSubscriberHelper(ros::NodeHandle nh, std::string topic, geometry_msgs::Pose &pose,
255  geometry_msgs::Twist &twist, geometry_msgs::Accel &accel, std_msgs::Header &header)
256  : pose_(pose), twist_(twist), accel_(accel), header_(header)
257  {
258  available_ = false;
259  tf_sub_ = nh.subscribe<geometry_msgs::TransformStamped>(topic, 1,
260  boost::bind(&StateSubscriberHelper::tfCb,
261  this, _1));
262  }
263 
265  {
266  tf_sub_.shutdown();
267  }
268 
269  bool isAvailable(){ return available_; }
270 
271 private:
273 
274  //TODO remove available?
276 
277  geometry_msgs::Pose &pose_;
278  geometry_msgs::Twist &twist_;
279  geometry_msgs::Accel &accel_;
280  std_msgs::Header &header_;
281 
283 
284  void tfCb(const geometry_msgs::TransformStampedConstPtr &transform)
285  {
286  header_ = transform->header;
287  pose_.position.x = transform->transform.translation.x;
288  pose_.position.y = transform->transform.translation.y;
289  pose_.position.z = transform->transform.translation.z;
290  pose_.orientation = transform->transform.rotation;
291 
292  diff_.updateAndEstimate(header_.stamp, pose_, twist_, accel_);
293  available_ = true;
294  }
295 
296  // TODO shapeshifter to replace PoseSubscriber and OdomSubscriberHelper
297 // void stateCb(topic_tools::ShapeShifter const &input) {
298 // if (input.getDataType() == "nav_msgs/Odometry") {
299 // nav_msgs::Odometry::ConstPtr odom = input.instantiate<nav_msgs::Odometry>();
300 // odomCallback(*odom);
301 // return;
302 // }
303 
304 // if (input.getDataType() == "geometry_msgs/PoseStamped") {
305 // geometry_msgs::PoseStamped::ConstPtr pose = input.instantiate<geometry_msgs::PoseStamped>();
306 // poseCallback(*pose);
307 // return;
308 // }
309 
310 // if (input.getDataType() == "sensor_msgs/Imu") {
311 // sensor_msgs::Imu::ConstPtr imu = input.instantiate<sensor_msgs::Imu>();
312 // imuCallback(*imu);
313 // return;
314 // }
315 
316 // if (input.getDataType() == "geometry_msgs/TransformStamped") {
317 // geometry_msgs::TransformStamped::ConstPtr tf = input.instantiate<geometry_msgs::TransformStamped>();
318 // tfCallback(*tf);
319 // return;
320 // }
321 
322 // ROS_ERROR_THROTTLE(1.0, "message_to_tf received a %s message. Supported message types: nav_msgs/Odometry geometry_msgs/PoseStamped sensor_msgs/Imu", input.getDataType().c_str());
323 // }
324 
325 };
326 
328 {
329 public:
330 
331  AttitudeSubscriberHelper(ros::NodeHandle nh, boost::mutex &command_mutex,
332  hector_uav_msgs::AttitudeCommand &attitude_command,
333  hector_uav_msgs::YawrateCommand &yawrate_command,
334  hector_uav_msgs::ThrustCommand &thrust_command)
335  : command_mutex_(command_mutex), attitude_command_(attitude_command), yawrate_command_(yawrate_command),
336  thrust_command_(thrust_command)
337  {
338  attitude_subscriber_ = nh.subscribe<hector_uav_msgs::AttitudeCommand>("attitude", 1, boost::bind(
340  yawrate_subscriber_ = nh.subscribe<hector_uav_msgs::YawrateCommand>("yawrate", 1, boost::bind(
342  thrust_subscriber_ = nh.subscribe<hector_uav_msgs::ThrustCommand>("thrust", 1, boost::bind(
344  }
345 
347  {
348  attitude_subscriber_.shutdown();
349  yawrate_subscriber_.shutdown();
350  thrust_subscriber_.shutdown();
351  }
352 
353 private:
354  ros::Subscriber attitude_subscriber_, yawrate_subscriber_, thrust_subscriber_;
355  boost::mutex &command_mutex_;
356  hector_uav_msgs::AttitudeCommand &attitude_command_;
357  hector_uav_msgs::YawrateCommand &yawrate_command_;
358  hector_uav_msgs::ThrustCommand &thrust_command_;
359 
360  void attitudeCommandCb(const hector_uav_msgs::AttitudeCommandConstPtr &command)
361  {
362  boost::mutex::scoped_lock lock(command_mutex_);
363  attitude_command_ = *command;
364  if (attitude_command_.header.stamp.isZero())
365  { attitude_command_.header.stamp = ros::Time::now(); }
366  }
367 
368  void yawrateCommandCb(const hector_uav_msgs::YawrateCommandConstPtr &command)
369  {
370  boost::mutex::scoped_lock lock(command_mutex_);
371  yawrate_command_ = *command;
372  if (yawrate_command_.header.stamp.isZero())
373  { yawrate_command_.header.stamp = ros::Time::now(); }
374  }
375 
376  void thrustCommandCb(const hector_uav_msgs::ThrustCommandConstPtr &command)
377  {
378  boost::mutex::scoped_lock lock(command_mutex_);
379  thrust_command_ = *command;
380  if (thrust_command_.header.stamp.isZero())
381  { attitude_command_.header.stamp = ros::Time::now(); }
382  }
383 };
384 
385 bool getMassAndInertia(const ros::NodeHandle &nh, double &mass, double inertia[3]);
386 
387 
388 bool poseWithinTolerance(const geometry_msgs::Pose &pose_current, const geometry_msgs::Pose &pose_target,
389  const double dist_tolerance, const double yaw_tolerance);
390 
391 } // namespace hector_quadrotor_interface
392 
393 #endif // HECTOR_QUADROTOR_INTERFACE_HELPERS_H
void getRPY(tf2Scalar &roll, tf2Scalar &pitch, tf2Scalar &yaw, unsigned int solution_number=1) const
hector_uav_msgs::AttitudeCommand & attitude_command_
Definition: helpers.h:356
void thrustCommandCb(const hector_uav_msgs::ThrustCommandConstPtr &command)
Definition: helpers.h:376
void attitudeCommandCb(const hector_uav_msgs::AttitudeCommandConstPtr &command)
Definition: helpers.h:360
void yawrateCommandCb(const hector_uav_msgs::YawrateCommandConstPtr &command)
Definition: helpers.h:368
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
hector_uav_msgs::YawrateCommand & yawrate_command_
Definition: helpers.h:357
bool poseWithinTolerance(const geometry_msgs::Pose &pose_current, const geometry_msgs::Pose &pose_target, const double dist_tolerance, const double yaw_tolerance)
Definition: helpers.cpp:73
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
hector_uav_msgs::ThrustCommand & thrust_command_
Definition: helpers.h:358
AttitudeSubscriberHelper(ros::NodeHandle nh, boost::mutex &command_mutex, hector_uav_msgs::AttitudeCommand &attitude_command, hector_uav_msgs::YawrateCommand &yawrate_command, hector_uav_msgs::ThrustCommand &thrust_command)
Definition: helpers.h:331
double differenceWithWraparound(double angle, double last_angle)
Definition: helpers.h:230
PoseSubscriberHelper(ros::NodeHandle nh, std::string topic)
Definition: helpers.h:146
OdomSubscriberHelper(ros::NodeHandle nh, std::string topic, geometry_msgs::Pose &pose, geometry_msgs::Twist &twist, geometry_msgs::Accel &acceleration, std_msgs::Header &header)
Definition: helpers.h:85
void imuCallback(const sensor_msgs::ImuConstPtr &imu)
Definition: helpers.h:73
StateSubscriberHelper(ros::NodeHandle nh, std::string topic, geometry_msgs::Pose &pose, geometry_msgs::Twist &twist, geometry_msgs::Accel &accel, std_msgs::Header &header)
Definition: helpers.h:254
void fromMsg(const A &, B &b)
geometry_msgs::PoseStampedConstPtr pose_
Definition: helpers.h:163
ImuSubscriberHelper(ros::NodeHandle nh, std::string topic, sensor_msgs::Imu &imu)
Definition: helpers.h:58
void tfCb(const geometry_msgs::TransformStampedConstPtr &transform)
Definition: helpers.h:284
void updateAndEstimate(const ros::Time &time, const geometry_msgs::Pose &pose, geometry_msgs::Twist &twist, geometry_msgs::Accel &accel)
Definition: helpers.h:175
static Time now()
bool getMassAndInertia(const ros::NodeHandle &nh, double &mass, double inertia[3])
Definition: helpers.cpp:35
void poseCallback(const geometry_msgs::PoseStampedConstPtr &pose)
Definition: helpers.h:165
void odomCallback(const nav_msgs::OdometryConstPtr &odom)
Definition: helpers.h:106


hector_quadrotor_interface
Author(s): Johannes Meyer , Paul Bovbel
autogenerated on Mon Jun 10 2019 13:36:46