turtlebot_move_action_server.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Willow Garage, Inc.
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 the Willow Garage, Inc. 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 
31 #include <ros/ros.h>
32 #include <std_msgs/Float32.h>
34 #include <turtlebot_actions/TurtlebotMoveAction.h>
35 #include <geometry_msgs/Twist.h>
36 #include <tf/transform_listener.h>
37 #include <cmath>
38 
40 {
41 private:
42 
45  std::string action_name_;
46 
47  turtlebot_actions::TurtlebotMoveFeedback feedback_;
48  turtlebot_actions::TurtlebotMoveResult result_;
49  turtlebot_actions::TurtlebotMoveGoalConstPtr goal_;
50 
54 
55  // Parameters
56  std::string base_frame;
57  std::string odom_frame;
58  double turn_rate;
59  double forward_rate;
60 
61 public:
62  MoveActionServer(const std::string name) :
63  nh_("~"), as_(nh_, name, false), action_name_(name)
64  {
65  // Get parameters
66  nh_.param<std::string>("base_frame", base_frame, "base_link");
67  nh_.param<std::string>("odom_frame", odom_frame, "odom");
68  nh_.param<double>("turn_rate", turn_rate, 0.75);
69  nh_.param<double>("forward_rate", forward_rate, 0.25);
70 
71  //register the goal and feeback callbacks
72  as_.registerGoalCallback(boost::bind(&MoveActionServer::goalCB, this));
74 
75  as_.start();
76 
77  cmd_vel_pub_ = nh_.advertise<geometry_msgs::Twist>("cmd_vel", 1);
78  }
79 
80  void goalCB()
81  {
82  // accept the new goal
83  feedback_.forward_distance = 0.0;
84  feedback_.turn_distance = 0.0;
85 
86  result_.forward_distance = 0.0;
87  result_.turn_distance = 0.0;
88 
89  goal_ = as_.acceptNewGoal();
90 
91  if (!turnOdom(goal_->turn_distance))
92  {
93  as_.setAborted(result_);
94  return;
95  }
96 
97  if (driveForwardOdom(goal_->forward_distance))
98  as_.setSucceeded(result_);
99  else
100  as_.setAborted(result_);
101  }
102 
103  void preemptCB()
104  {
105  ROS_INFO("%s: Preempted", action_name_.c_str());
106  // set the action state to preempted
107  as_.setPreempted();
108  }
109 
111  {
112  // If the distance to travel is negligble, don't even try.
113  if (fabs(distance) < 0.01)
114  return true;
115 
116  //we will record transforms here
117  tf::StampedTransform start_transform;
118  tf::StampedTransform current_transform;
119 
120  try
121  {
122  //wait for the listener to get the first message
123  listener_.waitForTransform(base_frame, odom_frame,
124  ros::Time::now(), ros::Duration(1.0));
125 
126  //record the starting transform from the odometry to the base frame
127  listener_.lookupTransform(base_frame, odom_frame,
128  ros::Time(0), start_transform);
129  }
130  catch (tf::TransformException ex)
131  {
132  ROS_ERROR("%s",ex.what());
133  return false;
134  }
135 
136  //we will be sending commands of type "twist"
137  geometry_msgs::Twist base_cmd;
138  //the command will be to go forward at 0.25 m/s
139  base_cmd.linear.y = base_cmd.angular.z = 0;
140  base_cmd.linear.x = forward_rate;
141 
142  if (distance < 0)
143  base_cmd.linear.x = -base_cmd.linear.x;
144 
145  ros::Rate rate(25.0);
146  bool done = false;
147  while (!done && nh_.ok() && as_.isActive())
148  {
149  //send the drive command
150  cmd_vel_pub_.publish(base_cmd);
151  rate.sleep();
152  //get the current transform
153  try
154  {
155  listener_.lookupTransform(base_frame, odom_frame,
156  ros::Time(0), current_transform);
157  }
158  catch (tf::TransformException ex)
159  {
160  ROS_ERROR("%s",ex.what());
161  break;
162  }
163  //see how far we've traveled
164  tf::Transform relative_transform =
165  start_transform.inverse() * current_transform;
166  double dist_moved = relative_transform.getOrigin().length();
167 
168  // Update feedback and result.
169  feedback_.forward_distance = dist_moved;
170  result_.forward_distance = dist_moved;
171  as_.publishFeedback(feedback_);
172 
173  if(fabs(dist_moved) > fabs(distance))
174  {
175  done = true;
176  }
177  }
178  base_cmd.linear.x = 0.0;
179  base_cmd.angular.z = 0.0;
180  cmd_vel_pub_.publish(base_cmd);
181 
182  if (done) return true;
183  return false;
184  }
185 
186  bool turnOdom(double radians)
187  {
188  // If the distance to travel is negligble, don't even try.
189  if (fabs(radians) < 0.01)
190  return true;
191 
192  while(radians < -M_PI) radians += 2*M_PI;
193  while(radians > M_PI) radians -= 2*M_PI;
194 
195  //we will record transforms here
196  tf::StampedTransform start_transform;
197  tf::StampedTransform current_transform;
198 
199  try
200  {
201  //wait for the listener to get the first message
202  listener_.waitForTransform(base_frame, odom_frame,
203  ros::Time::now(), ros::Duration(1.0));
204 
205  //record the starting transform from the odometry to the base frame
206  listener_.lookupTransform(base_frame, odom_frame,
207  ros::Time(0), start_transform);
208  }
209  catch (tf::TransformException ex)
210  {
211  ROS_ERROR("%s",ex.what());
212  return false;
213  }
214 
215  //we will be sending commands of type "twist"
216  geometry_msgs::Twist base_cmd;
217  //the command will be to turn at 0.75 rad/s
218  base_cmd.linear.x = base_cmd.linear.y = 0.0;
219  base_cmd.angular.z = turn_rate;
220  if (radians < 0)
221  base_cmd.angular.z = -turn_rate;
222 
223  //the axis we want to be rotating by
224  tf::Vector3 desired_turn_axis(0,0,1);
225 
226  ros::Rate rate(25.0);
227  bool done = false;
228  while (!done && nh_.ok() && as_.isActive())
229  {
230  //send the drive command
231  cmd_vel_pub_.publish(base_cmd);
232  rate.sleep();
233  //get the current transform
234  try
235  {
236  listener_.lookupTransform(base_frame, odom_frame,
237  ros::Time(0), current_transform);
238  }
239  catch (tf::TransformException ex)
240  {
241  ROS_ERROR("%s",ex.what());
242  break;
243  }
244  tf::Transform relative_transform =
245  start_transform.inverse() * current_transform;
246  tf::Vector3 actual_turn_axis =
247  relative_transform.getRotation().getAxis();
248  double angle_turned = relative_transform.getRotation().getAngle();
249 
250  // Update feedback and result.
251  feedback_.turn_distance = angle_turned;
252  result_.turn_distance = angle_turned;
253  as_.publishFeedback(feedback_);
254 
255  if ( fabs(angle_turned) < 1.0e-2) continue;
256 
257  //if ( actual_turn_axis.dot( desired_turn_axis ) < 0 )
258  // angle_turned = 2 * M_PI - angle_turned;
259 
260  if (fabs(angle_turned) > fabs(radians)) done = true;
261  }
262  if (done) return true;
263  return false;
264  }
265 
266 
267 };
268 
269 int main(int argc, char** argv)
270 {
271  ros::init(argc, argv, "turtlebot_move_action_server");
272 
273  MoveActionServer server("turtlebot_move");
274  ros::spin();
275 
276  return 0;
277 }
278 
boost::shared_ptr< const Goal > acceptNewGoal()
void publishFeedback(const FeedbackConstPtr &feedback)
int main(int argc, char **argv)
tfScalar getAngle() const
void publish(const boost::shared_ptr< M > &message) const
rs_error * e
actionlib::SimpleActionServer< turtlebot_actions::TurtlebotMoveAction > as_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
GLsizei GLsizei GLfloat distance
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
ROSCPP_DECL void spin(Spinner &spinner)
bool waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const
void setPreempted(const Result &result=Result(), const std::string &text=std::string(""))
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
#define M_PI
tf::TransformListener listener_
Vector3 getAxis() const
void registerPreemptCallback(boost::function< void()> cb)
turtlebot_actions::TurtlebotMoveGoalConstPtr goal_
Transform inverse() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool driveForwardOdom(double distance)
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
bool sleep()
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
turtlebot_actions::TurtlebotMoveResult result_
Quaternion getRotation() const
GLuint const GLchar * name
static Time now()
bool ok() const
void registerGoalCallback(boost::function< void()> cb)
MoveActionServer(const std::string name)
turtlebot_actions::TurtlebotMoveFeedback feedback_
#define ROS_ERROR(...)
TFSIMD_FORCE_INLINE tfScalar length() const


turtlebot_actions
Author(s): Helen Oleynikova, Melonee Wise
autogenerated on Mon Jun 10 2019 15:43:57