planner_manager.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, The Regents of the University of California (Regents).
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
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: David Fridovich-Keil ( dfk@eecs.berkeley.edu )
35  */
36 
38 //
39 // Defines the PlannerManager class, which listens for new trajectory
40 // messages and, on a timer, repeatedly queries the current trajectory and
41 // publishes the corresponding reference.
42 //
43 // The PlannerManager is also responsible for requesting new plans.
44 // This base class only calls the planner once upon takeoff; as needs will vary
45 // derived classes may add further functionality such as receding
46 // horizon planning.
47 //
49 
50 #ifndef FASTRACK_PLANNING_PLANNER_MANAGER_H
51 #define FASTRACK_PLANNING_PLANNER_MANAGER_H
52 
54 #include <fastrack/utils/types.h>
56 
57 #include <fastrack_msgs/ReplanRequest.h>
58 
59 #include <ros/ros.h>
60 #include <visualization_msgs/Marker.h>
61 #include <std_msgs/Empty.h>
62 #include <geometry_msgs/Vector3.h>
63 #include <geometry_msgs/TransformStamped.h>
64 #include <tf2_ros/transform_broadcaster.h>
65 
66 namespace fastrack {
67 namespace planning {
68 
69 using trajectory::Trajectory;
70 
71 template<typename S>
72 class PlannerManager : private Uncopyable {
73 public:
74  virtual ~PlannerManager() {}
75  explicit PlannerManager()
76  : ready_(false),
77  waiting_for_traj_(false),
78  serviced_updated_env_(false),
79  initialized_(false) {}
80 
81  // Initialize this class with all parameters and callbacks.
82  bool Initialize(const ros::NodeHandle& n);
83 
84 protected:
85  // Load parameters and register callbacks. These may be overridden, however
86  // derived classes should still call these functions.
87  virtual bool LoadParameters(const ros::NodeHandle& n);
88  virtual bool RegisterCallbacks(const ros::NodeHandle& n);
89 
90  // If not already waiting, request a new trajectory that starts along the
91  // current trajectory at the state corresponding to when the planner will
92  // return, and ends at the goal location. This may be overridden by derived
93  // classes with more specific replanning needs.
94  virtual void MaybeRequestTrajectory();
95 
96  // Callback for applying tracking controller. This may be overridden, however
97  // derived classes should still call thhis function.
98  virtual void TimerCallback(const ros::TimerEvent& e);
99 
100  // Create and publish a marker at goal state.
101  virtual void VisualizeGoal() const ;
102 
103  // Callback for processing trajectory updates.
104  inline void TrajectoryCallback(const fastrack_msgs::Trajectory::ConstPtr& msg) {
105  waiting_for_traj_ = false;
106 
107  // Catch failure (empty msg).
108  if (msg->states.empty() || msg->times.empty()) {
109  ROS_WARN_THROTTLE(1.0, "%s: Received empty trajectory.", name_.c_str());
110  return;
111  }
112 
113  // Update current trajectory and visualize.
114  traj_ = Trajectory<S>(msg);
115  traj_.Visualize(traj_vis_pub_, fixed_frame_);
116  }
117 
118  // Is the system ready?
119  inline void ReadyCallback(const std_msgs::Empty::ConstPtr& msg) {
120  ready_ = true;
121  }
122 
123  // Generate a new trajectory request when environment has been updated.
124  inline void UpdatedEnvironmentCallback(const std_msgs::Empty::ConstPtr& msg) {
125  serviced_updated_env_ = false;
127  }
128 
129  // Current trajectory.
130  Trajectory<S> traj_;
131 
132  // Planner runtime -- how long does it take for the planner to run.
134 
135  // Are we waiting for a new trajectory?
137 
138  // Have we serviced the most recent updated environment callback?
140 
141  // Start/goal states.
142  fastrack_msgs::State start_;
143  fastrack_msgs::State goal_;
144 
145  // Set a recurring timer for a discrete-time controller.
146  ros::Timer timer_;
147  double time_step_;
148 
149  // Publishers/subscribers and related topics.
150  ros::Publisher goal_pub_;
151  ros::Publisher ref_pub_;
152  ros::Publisher replan_request_pub_;
153  ros::Publisher traj_vis_pub_;
154  ros::Subscriber traj_sub_;
155  ros::Subscriber ready_sub_;
156  ros::Subscriber updated_env_sub_;
157 
158  std::string goal_topic_;
159  std::string ref_topic_;
161  std::string traj_vis_topic_;
162  std::string traj_topic_;
163  std::string ready_topic_;
164  std::string updated_env_topic_;
165 
166  // Frames of reference for publishing markers.
167  std::string fixed_frame_;
168  std::string planner_frame_;
169 
170  // Transform broadcaster for planner position.
171  tf2_ros::TransformBroadcaster tf_broadcaster_;
172 
173  // Are we in flight?
174  bool ready_;
175 
176  // Naming and initialization.
177  std::string name_;
179 };
180 
181 // ---------------------------- IMPLEMENTATION ------------------------------ //
182 
183 // Initialize this class with all parameters and callbacks.
184 template<typename S>
185 bool PlannerManager<S>::Initialize(const ros::NodeHandle& n) {
186  name_ = ros::names::append(n.getNamespace(), "PlannerManager");
187 
188  // Load parameters.
189  if (!LoadParameters(n)) {
190  ROS_ERROR("%s: Failed to load parameters.", name_.c_str());
191  return false;
192  }
193 
194  // Register callbacks.
195  if (!RegisterCallbacks(n)) {
196  ROS_ERROR("%s: Failed to register callbacks.", name_.c_str());
197  return false;
198  }
199 
200  initialized_ = true;
201  return true;
202 }
203 
204 // Load parameters.
205 template<typename S>
206 bool PlannerManager<S>::LoadParameters(const ros::NodeHandle& n) {
207  ros::NodeHandle nl(n);
208 
209  // Topics.
210  if (!nl.getParam("topic/ready", ready_topic_)) return false;
211  if (!nl.getParam("topic/traj", traj_topic_)) return false;
212  if (!nl.getParam("topic/ref", ref_topic_)) return false;
213  if (!nl.getParam("topic/replan_request", replan_request_topic_)) return false;
214  if (!nl.getParam("topic/updated_env", updated_env_topic_)) return false;
215  if (!nl.getParam("vis/traj", traj_vis_topic_)) return false;
216  if (!nl.getParam("vis/goal", goal_topic_)) return false;
217 
218  // Frames.
219  if (!nl.getParam("frame/fixed", fixed_frame_)) return false;
220  if (!nl.getParam("frame/planner", planner_frame_)) return false;
221 
222  // Time step.
223  if (!nl.getParam("time_step", time_step_)) return false;
224 
225  // Planner runtime, start, and goal.
226  if (!nl.getParam("planner_runtime", planner_runtime_)) return false;
227  if (!nl.getParam("start", start_.x)) return false;
228  if (!nl.getParam("goal", goal_.x)) return false;
229 
230  return true;
231 }
232 
233 // Register callbacks.
234 template<typename S>
235 bool PlannerManager<S>::RegisterCallbacks(const ros::NodeHandle& n) {
236  ros::NodeHandle nl(n);
237 
238  // Subscribers.
239  ready_sub_ = nl.subscribe(ready_topic_.c_str(), 1,
241 
242  traj_sub_ = nl.subscribe(traj_topic_.c_str(), 1,
244 
245  updated_env_sub_ = nl.subscribe(updated_env_topic_.c_str(), 1,
247 
248  // Publishers.
249  ref_pub_ = nl.advertise<fastrack_msgs::State>(ref_topic_.c_str(), 1, false);
250 
251  replan_request_pub_ = nl.advertise<fastrack_msgs::ReplanRequest>(
252  replan_request_topic_.c_str(), 1, false);
253 
254  goal_pub_ = nl.advertise<visualization_msgs::Marker>(
255  goal_topic_.c_str(), 1, false);
256 
257  traj_vis_pub_ = nl.advertise<visualization_msgs::Marker>(
258  traj_vis_topic_.c_str(), 1, false);
259 
260  // Timer.
261  timer_ = nl.createTimer(ros::Duration(time_step_),
263 
264  return true;
265 }
266 
267 // If not already waiting, request a new trajectory that starts along the
268 // current trajectory at the state corresponding to when the planner will
269 // return, and ends at the goal location. This may be overridden by derived
270 // classes with more specific replanning needs.
271 template<typename S>
273  // Publish marker at goal location.
274  VisualizeGoal();
275 
276  if (!ready_ || waiting_for_traj_) {
277  return;
278  }
279 
280  // Set start and goal states.
281  fastrack_msgs::ReplanRequest msg;
282  msg.start = start_;
283  msg.goal = goal_;
284 
285  // Set start time.
286  msg.start_time = ros::Time::now().toSec() + planner_runtime_;
287 
288  // Reset start state for future state if we have a current trajectory.
289  if (traj_.Size() > 0) {
290  // Catch trajectory that's too short.
291  if (traj_.LastTime() < msg.start_time) {
292  ROS_ERROR("%s: Current trajectory is too short. Cannot interpolate.",
293  name_.c_str());
294  msg.start = traj_.LastState().ToRos();
295  } else {
296  msg.start = traj_.Interpolate(msg.start_time).ToRos();
297  }
298  }
299 
300  // Publish request and set flag.
301  replan_request_pub_.publish(msg);
302  waiting_for_traj_ = true;
303  serviced_updated_env_ = true;
304 }
305 
306 // Callback for applying tracking controller.
307 template<typename S>
308 void PlannerManager<S>::TimerCallback(const ros::TimerEvent& e) {
309  if (!ready_)
310  return;
311 
312  if (traj_.Size() == 0) {
314  return;
315  } else if (waiting_for_traj_) {
316  ROS_WARN_THROTTLE(1.0, "%s: Waiting for trajectory.", name_.c_str());
317  } else if (!serviced_updated_env_) {
318  ROS_INFO_THROTTLE(1.0, "%s: Servicing old updated environment callback.",
319  name_.c_str());
321  }
322 
323  // Interpolate the current trajectory.
324  const S planner_x = traj_.Interpolate(ros::Time::now().toSec());
325 
326  // Convert to ROS msg and publish.
327  ref_pub_.publish(planner_x.ToRos());
328 
329  // Broadcast transform.
330  geometry_msgs::TransformStamped tf;
331  tf.header.frame_id = fixed_frame_;
332  tf.header.stamp = ros::Time::now();
333  tf.child_frame_id = planner_frame_;
334 
335  tf.transform.translation.x = planner_x.X();
336  tf.transform.translation.y = planner_x.Y();
337  tf.transform.translation.z = planner_x.Z();
338  tf.transform.rotation.x = 0;
339  tf.transform.rotation.y = 0;
340  tf.transform.rotation.z = 0;
341  tf.transform.rotation.w = 1;
342 
343  tf_broadcaster_.sendTransform(tf);
344 }
345 
346 // Converts the goal state into a Rviz marker.
347 template<typename S>
349  // Set up sphere marker.
350  visualization_msgs::Marker sphere;
351  sphere.ns = "sphere";
352  sphere.header.frame_id = fixed_frame_;
353  sphere.header.stamp = ros::Time::now();
354  sphere.id = 0;
355  sphere.type = visualization_msgs::Marker::SPHERE;
356  sphere.action = visualization_msgs::Marker::ADD;
357  sphere.color.a = 1.0;
358  sphere.color.r = 0.3;
359  sphere.color.g = 0.7;
360  sphere.color.b = 0.7;
361 
362  geometry_msgs::Point center;
363 
364  // Fill in center and scale.
365  sphere.scale.x = 0.1;
366  center.x = goal_.x[0];
367 
368  sphere.scale.y = 0.1;
369  center.y = goal_.x[1];
370 
371  sphere.scale.z = 0.1;
372  center.z = goal_.x[2];
373 
374  sphere.pose.position = center;
375  sphere.pose.orientation.x = 0.0;
376  sphere.pose.orientation.y = 0.0;
377  sphere.pose.orientation.z = 0.0;
378  sphere.pose.orientation.w = 1.0;
379 
380  goal_pub_.publish(sphere);
381 
382  return;
383 }
384 
385 } //\namespace planning
386 } //\namespace fastrack
387 
388 #endif
virtual bool RegisterCallbacks(const ros::NodeHandle &n)
virtual void VisualizeGoal() const
void TrajectoryCallback(const fastrack_msgs::Trajectory::ConstPtr &msg)
virtual bool LoadParameters(const ros::NodeHandle &n)
tf2_ros::TransformBroadcaster tf_broadcaster_
Definition: box.h:53
void ReadyCallback(const std_msgs::Empty::ConstPtr &msg)
bool Initialize(const ros::NodeHandle &n)
virtual void TimerCallback(const ros::TimerEvent &e)
void UpdatedEnvironmentCallback(const std_msgs::Empty::ConstPtr &msg)


fastrack
Author(s): David Fridovich-Keil
autogenerated on Mon Aug 3 2020 21:28:37