diff_drive_pose_controller_ros.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Marcus Liebhardt, Yujin Robot.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
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 Yujin Robot nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <cmath>
31 #include <std_msgs/Bool.h>
32 #include <geometry_msgs/Twist.h>
34 
36 
37 namespace yocs
38 {
39 
41 {
45  this);
46  command_velocity_publisher_ = nh_.advertise<geometry_msgs::Twist>("command_velocity", 10);
47  pose_reached_publisher_ = nh_.advertise<std_msgs::Bool>("pose_reached", 10);
48 
49  // retrieve configuration parameters
50  base_frame_name_ = "base_footprint";
51  if (!nh_.getParam("base_frame_name", base_frame_name_))
52  {
54  "Couldn't retrieve parameter 'base_frame_name' from parameter server! Using default '" << base_frame_name_ << "'. [" << name_ <<"]");
55  }
56  goal_frame_name_ = "base_goal_pose";
57  if (!nh_.getParam("goal_frame_name", goal_frame_name_))
58  {
60  "Couldn't retrieve parameter 'goal_frame_name' from parameter server! Using default '" << goal_frame_name_ << "'. [" << name_ <<"]");
61  }
62 
63  if (!nh_.getParam("v_min", v_min_movement_))
64  {
66  "Couldn't retrieve parameter 'v_min' from parameter server! Using default '" << v_min_movement_ << "'. [" << name_ <<"]");
67  }
69  if (!nh_.getParam("v_max", v_max_))
70  {
72  "Couldn't retrieve parameter 'v_max' from parameter server! Using default '" << v_max_ << "'. [" << name_ <<"]");
73  }
74 // v_min_ = -v_max_; //if we also want to enable driving backwards
75  if (!nh_.getParam("w_min", w_min_movement_))
76  {
78  "Couldn't retrieve parameter 'w_min' from parameter server! Using default '" << w_min_movement_ << "'. [" << name_ <<"]");
79  }
80  w_max_ = M_PI / 4 * v_max_;
81  if (!nh_.getParam("w_max", w_max_))
82  {
84  "Couldn't retrieve parameter 'w_max' from parameter server! Using default '" << w_max_ << "'. [" << name_ <<"]");
85  }
86  w_min_ = -w_max_;
87 
88  if (!nh_.getParam("k_1", k_1_))
89  {
91  "Couldn't retrieve parameter 'k_1' from parameter server! Using default '" << k_1_ << "'. [" << name_ <<"]");
92  }
93  if (!nh_.getParam("k_2", k_2_))
94  {
96  "Couldn't retrieve parameter 'k_2' from parameter server! Using default '" << k_2_ << "'. [" << name_ <<"]");
97  }
98  if (!nh_.getParam("beta", beta_))
99  {
101  "Couldn't retrieve parameter 'beta' from parameter server! Using default '" << beta_ << "'. [" << name_ <<"]");
102  }
103  if (!nh_.getParam("lambda", lambda_))
104  {
106  "Couldn't retrieve parameter 'lambda' from parameter server! Using default '" << lambda_ << "'. [" << name_ <<"]");
107  }
108  if (!nh_.getParam("dist_thres", dist_thres_))
109  {
111  "Couldn't retrieve parameter 'dist_thres' from parameter server! Using default '" << dist_thres_ << "'. [" << name_ <<"]");
112  }
113  if (!nh_.getParam("orient_thres", orient_thres_))
114  {
116  "Couldn't retrieve parameter 'orient_thres' from parameter server! Using default '" << orient_thres_ << "'. [" << name_ <<"]");
117  }
118  dist_eps_ = dist_eps_ * 0.2;
119  if (!nh_.getParam("dist_eps", dist_eps_))
120  {
122  "Couldn't retrieve parameter 'dist_eps' from parameter server! Using default '" << dist_eps_ << "'. [" << name_ <<"]");
123  }
124  orient_eps_ = orient_thres_ * 0.2;
125  if (!nh_.getParam("orient_eps", orient_eps_))
126  {
128  "Couldn't retrieve parameter 'orient_eps' from parameter server! Using default '" << orient_eps_ << "'. [" << name_ <<"]");
129  }
130 
131  ROS_DEBUG_STREAM("Controller initialised with the following parameters: [" << name_ <<"]");
133  "base_frame_name = " << base_frame_name_ <<", goal_frame_name = " << goal_frame_name_ << " [" << name_ <<"]");
135  "v_max = " << v_max_ <<", k_1 = " << k_1_ << ", k_2 = " << k_2_ << ", beta = " << beta_ << ", lambda = " << lambda_ << ", dist_thres = " << dist_thres_ << ", orient_thres = " << orient_thres_ <<" [" << name_ <<"]");
136  return true;
137 }
138 
140 {
141  if (this->getState())
142  {
143  ROS_DEBUG_STREAM_THROTTLE(1.0, "Controller spinning. [" << name_ <<"]");
144  // determine pose difference in polar coordinates
145  if (!getPoseDiff())
146  {
147  ROS_WARN_STREAM_THROTTLE(1.0, "Getting pose difference failed. Skipping control loop. [" << name_ <<"]");
148  return;
149  }
150  // determine controller output (v, w) and check if goal is reached
151  step();
152 
153  // set control output (v, w)
155  // Logging
156  ROS_DEBUG_STREAM_THROTTLE(1.0, "Current state: [" << name_ <<"]");
158  "r = " << r_ << ", theta = " << theta_ << ", delta = " << delta_ << " [" << name_ <<"]");
159  ROS_DEBUG_STREAM_THROTTLE(1.0, "cur = " << cur_ << ", v = " << v_ << ", w = " << w_ << " [" << name_ <<"]");
160  }
161  else
162  {
163  ROS_DEBUG_STREAM_THROTTLE(3.0, "Controller is disabled. Idling ... [" << name_ <<"]");
164  }
165 }
166 
168 {
169  // use tf to get information about the goal pose relative to the base
170  try
171  {
173  }
174  catch (tf::TransformException const &ex)
175  {
176  ROS_WARN_STREAM_THROTTLE(1.0, "Couldn't get transform from base to goal pose! [" << name_ <<"]");
177  ROS_DEBUG_STREAM_THROTTLE(1.0, "tf error: " << ex.what());
178  return false;
179  }
180 
181  // determine distance to goal
182  double r = std::sqrt(
183  std::pow(tf_goal_pose_rel_.getOrigin().getX(), 2) + std::pow(tf_goal_pose_rel_.getOrigin().getY(), 2));
184  // determine orientation of r relative to the base frame
185  double delta = std::atan2(-tf_goal_pose_rel_.getOrigin().getY(), tf_goal_pose_rel_.getOrigin().getX());
186 
187  // determine orientation of r relative to the goal frame
188  // helper: theta = tf's orientation + delta
190  double theta = heading + delta;
191 
192  setInput(r, delta, theta);
193 
194  return true;
195 }
196 
198 {
199  std_msgs::Bool bool_msg;
200  bool_msg.data = true;
202 }
203 
205 {
206  geometry_msgs::TwistPtr cmd_vel(new geometry_msgs::Twist());
207  if (!pose_reached_)
208  {
209  cmd_vel->linear.x = v_;
210  cmd_vel->angular.z = w_;
211  }
213 }
214 
215 void DiffDrivePoseControllerROS::controlMaxVelCB(const std_msgs::Float32ConstPtr msg)
216 {
217  v_max_ = msg->data;
218  //v_min_ = -v_max_; //if we also want to enable driving backwards
219  ROS_INFO_STREAM("Maximum linear control velocity has been set to " << v_max_ << ". [" << name_ << "]");
220 }
221 
222 void DiffDrivePoseControllerROS::enableCB(const std_msgs::StringConstPtr msg)
223 {
224  if (this->enable())
225  {
226  goal_frame_name_ = msg->data;
227  ROS_INFO_STREAM("Controller has been enabled. [" << name_ << "] with goal frame [" << goal_frame_name_ << "]");
228  }
229  else
230  {
231  ROS_INFO_STREAM("Controller was already enabled. [" << name_ <<"] with Goal frame [" << goal_frame_name_ << "]");
232  }
233 }
234 
235 void DiffDrivePoseControllerROS::disableCB(const std_msgs::EmptyConstPtr msg)
236 {
237  if (this->disable())
238  {
239  ROS_INFO_STREAM("Controller has been disabled. [" << name_ <<"]");
240  }
241  else
242  {
243  ROS_INFO_STREAM("Controller was already disabled. [" << name_ <<"]");
244  }
245 }
246 
247 } // namespace yocs
ros::Subscriber disable_controller_subscriber_
subscriber for disabling the controller
double v_min_movement_
minimum linear base velocity at which we still move [m/s]
#define ROS_DEBUG_STREAM_THROTTLE(rate, args)
double wrapAngle(double a)
bool init()
Set-up necessary publishers/subscribers and variables.
double delta_
current heading of the base [rad]
double r_
distance to pose goal [m]
void publish(const boost::shared_ptr< M > &message) const
double dist_eps_
Error in distance above which pose is considered different.
bool getPoseDiff()
Determines the pose difference in polar coordinates.
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
double k_2_
constant factor applied to the heading error feedback
static double getYaw(const Quaternion &bt_q)
tf::TransformListener tf_listener_
tf used to get goal pose relative to the base pose
TFSIMD_FORCE_INLINE const tfScalar & getY() const
ros::Subscriber enable_controller_subscriber_
subscriber for enabling the controller
double orient_eps_
Error in orientation above which pose is considered different.
void setControlOutput()
Calculates the controller output based on the current pose difference.
std::string base_frame_name_
frame name of the base
tf::StampedTransform tf_goal_pose_rel_
transform for the goal pose relative to the base pose
double w_
angular base velocity [rad/s]
double w_min_
(current) minimum angular base velocity [rad/s]
void controlMaxVelCB(const std_msgs::Float32ConstPtr msg)
Callback for updating the controller&#39;s maximum linear control velocity.
double cur_
path to goal curvature
bool pose_reached_
True, if pose has been reached (v == 0, w == 0)
double theta_
direction of the pose goal [rad]
void spinOnce()
Calculates velocity commands to move the diff-drive base to the (next) pose goal. ...
double v_max_
maximum linear base velocity [m/s]
virtual void setInput(double distance_to_goal, double delta, double theta)
Set input of controller. Should be called before each spinOnce.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
double w_min_movement_
minimum angular base velocity at which we still move [rad/s]
double v_min_
(current) minimum linear base velocity [m/s]
#define ROS_WARN_STREAM(args)
#define ROS_DEBUG_STREAM(args)
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
#define ROS_WARN_STREAM_THROTTLE(rate, args)
virtual void onGoalReached()
Publishes goal is reached message.
ros::Publisher pose_reached_publisher_
publishes the status of the goal pose tracking
ros::Publisher command_velocity_publisher_
publisher for sending out base velocity commands
std::string goal_frame_name_
frame name of the goal (pose)
ros::Subscriber control_velocity_subscriber_
subscriber for setting the controller&#39;s linear velocity
#define ROS_INFO_STREAM(args)
void enableCB(const std_msgs::StringConstPtr msg)
Callback for enabling the controler.
Quaternion getRotation() const
double orient_thres_
lower bound for the orientation (w = 0)
bool getParam(const std::string &key, std::string &s) const
double v_
linear base velocity [m/s]
TFSIMD_FORCE_INLINE const tfScalar & getX() const
double w_max_
maximum angular base velocity [rad/s]
double dist_thres_
lower bound for the distance (v = 0)
double k_1_
constant factor determining the ratio of the rate of change in theta to the rate of change in r ...
void disableCB(const std_msgs::EmptyConstPtr msg)
Callback for disabling the controler.
double heading(geometry_msgs::Point p)
virtual bool step()
Execute one controller step.


yocs_diff_drive_pose_controller
Author(s): Marcus Liebhardt
autogenerated on Mon Jun 10 2019 15:53:50