Nav2 Navigation Stack - jazzy  jazzy
ROS 2 Navigation Stack
dwb_local_planner.cpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2017, Locus Robotics
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * 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
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <algorithm>
36 #include <memory>
37 #include <string>
38 #include <utility>
39 #include <vector>
40 
41 #include "dwb_core/dwb_local_planner.hpp"
42 #include "dwb_core/exceptions.hpp"
43 #include "dwb_core/illegal_trajectory_tracker.hpp"
44 #include "dwb_msgs/msg/critic_score.hpp"
45 #include "nav_2d_msgs/msg/twist2_d.hpp"
46 #include "nav_2d_utils/conversions.hpp"
47 #include "nav_2d_utils/tf_help.hpp"
48 #include "nav2_util/geometry_utils.hpp"
49 #include "nav2_util/lifecycle_node.hpp"
50 #include "nav2_util/node_utils.hpp"
51 #include "nav2_core/controller_exceptions.hpp"
52 #include "pluginlib/class_list_macros.hpp"
53 #include "nav_msgs/msg/path.hpp"
54 #include "geometry_msgs/msg/twist_stamped.hpp"
55 
56 using nav2_util::declare_parameter_if_not_declared;
57 using nav2_util::geometry_utils::euclidean_distance;
58 
59 namespace dwb_core
60 {
61 
63 : traj_gen_loader_("dwb_core", "dwb_core::TrajectoryGenerator"),
64  critic_loader_("dwb_core", "dwb_core::TrajectoryCritic")
65 {
66 }
67 
69  const rclcpp_lifecycle::LifecycleNode::WeakPtr & parent,
70  std::string name, std::shared_ptr<tf2_ros::Buffer> tf,
71  std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros)
72 {
73  node_ = parent;
74  auto node = node_.lock();
75 
76  logger_ = node->get_logger();
77  clock_ = node->get_clock();
78  costmap_ros_ = costmap_ros;
79  tf_ = tf;
80  dwb_plugin_name_ = name;
81  declare_parameter_if_not_declared(
82  node, dwb_plugin_name_ + ".critics",
83  rclcpp::PARAMETER_STRING_ARRAY);
84  declare_parameter_if_not_declared(
85  node, dwb_plugin_name_ + ".default_critic_namespaces",
86  rclcpp::ParameterValue(std::vector<std::string>()));
87  declare_parameter_if_not_declared(
88  node, dwb_plugin_name_ + ".prune_plan",
89  rclcpp::ParameterValue(true));
90  declare_parameter_if_not_declared(
91  node, dwb_plugin_name_ + ".prune_distance",
92  rclcpp::ParameterValue(2.0));
93  declare_parameter_if_not_declared(
94  node, dwb_plugin_name_ + ".forward_prune_distance",
95  rclcpp::ParameterValue(2.0));
96  declare_parameter_if_not_declared(
97  node, dwb_plugin_name_ + ".debug_trajectory_details",
98  rclcpp::ParameterValue(false));
99  declare_parameter_if_not_declared(
100  node, dwb_plugin_name_ + ".trajectory_generator_name",
101  rclcpp::ParameterValue(std::string("dwb_plugins::StandardTrajectoryGenerator")));
102  declare_parameter_if_not_declared(
103  node, dwb_plugin_name_ + ".transform_tolerance",
104  rclcpp::ParameterValue(0.1));
105  declare_parameter_if_not_declared(
106  node, dwb_plugin_name_ + ".shorten_transformed_plan",
107  rclcpp::ParameterValue(true));
108  declare_parameter_if_not_declared(
109  node, dwb_plugin_name_ + ".short_circuit_trajectory_evaluation",
110  rclcpp::ParameterValue(true));
111 
112  std::string traj_generator_name;
113 
114  double transform_tolerance;
115  node->get_parameter(dwb_plugin_name_ + ".transform_tolerance", transform_tolerance);
116  transform_tolerance_ = rclcpp::Duration::from_seconds(transform_tolerance);
117  RCLCPP_INFO(logger_, "Setting transform_tolerance to %f", transform_tolerance);
118 
119  node->get_parameter(dwb_plugin_name_ + ".prune_plan", prune_plan_);
120  node->get_parameter(dwb_plugin_name_ + ".prune_distance", prune_distance_);
121  node->get_parameter(dwb_plugin_name_ + ".forward_prune_distance", forward_prune_distance_);
122  if (forward_prune_distance_ < 0.0) {
123  RCLCPP_WARN(
124  logger_, "Forward prune distance is negative, setting to max to search"
125  " every point on path for the closest value.");
126  forward_prune_distance_ = std::numeric_limits<double>::max();
127  }
128  node->get_parameter(dwb_plugin_name_ + ".debug_trajectory_details", debug_trajectory_details_);
129  node->get_parameter(dwb_plugin_name_ + ".trajectory_generator_name", traj_generator_name);
130  node->get_parameter(
131  dwb_plugin_name_ + ".short_circuit_trajectory_evaluation",
132  short_circuit_trajectory_evaluation_);
133  node->get_parameter(dwb_plugin_name_ + ".shorten_transformed_plan", shorten_transformed_plan_);
134 
135  pub_ = std::make_unique<DWBPublisher>(node, dwb_plugin_name_);
136  pub_->on_configure();
137 
138  traj_generator_ = traj_gen_loader_.createUniqueInstance(traj_generator_name);
139 
140  traj_generator_->initialize(node, dwb_plugin_name_);
141 
142  try {
143  loadCritics();
144  } catch (const std::exception & e) {
145  RCLCPP_ERROR(logger_, "Couldn't load critics! Caught exception: %s", e.what());
147  "Couldn't load critics! Caught exception: " +
148  std::string(e.what()));
149  }
150 }
151 
152 void
154 {
155  pub_->on_activate();
156 }
157 
158 void
160 {
161  pub_->on_deactivate();
162 }
163 
164 void
166 {
167  pub_->on_cleanup();
168 
169  traj_generator_.reset();
170 }
171 
172 std::string
174 {
175  if (base_name.find("Critic") == std::string::npos) {
176  base_name = base_name + "Critic";
177  }
178 
179  if (base_name.find("::") == std::string::npos) {
180  for (unsigned int j = 0; j < default_critic_namespaces_.size(); j++) {
181  std::string full_name = default_critic_namespaces_[j] + "::" + base_name;
182  if (critic_loader_.isClassAvailable(full_name)) {
183  return full_name;
184  }
185  }
186  }
187  return base_name;
188 }
189 
190 void
192 {
193  auto node = node_.lock();
194  if (!node) {
195  throw std::runtime_error{"Failed to lock node"};
196  }
197 
198  node->get_parameter(dwb_plugin_name_ + ".default_critic_namespaces", default_critic_namespaces_);
199  if (default_critic_namespaces_.empty()) {
200  default_critic_namespaces_.emplace_back("dwb_critics");
201  }
202 
203  std::vector<std::string> critic_names;
204  if (!node->get_parameter(dwb_plugin_name_ + ".critics", critic_names)) {
205  throw std::runtime_error("No critics defined for " + dwb_plugin_name_);
206  }
207 
208  node->get_parameter(dwb_plugin_name_ + ".critics", critic_names);
209  for (unsigned int i = 0; i < critic_names.size(); i++) {
210  std::string critic_plugin_name = critic_names[i];
211  std::string plugin_class;
212 
213  declare_parameter_if_not_declared(
214  node, dwb_plugin_name_ + "." + critic_plugin_name + ".class",
215  rclcpp::ParameterValue(critic_plugin_name));
216  node->get_parameter(dwb_plugin_name_ + "." + critic_plugin_name + ".class", plugin_class);
217 
218  plugin_class = resolveCriticClassName(plugin_class);
219 
220  TrajectoryCritic::Ptr plugin = critic_loader_.createUniqueInstance(plugin_class);
221  RCLCPP_INFO(
222  logger_,
223  "Using critic \"%s\" (%s)", critic_plugin_name.c_str(), plugin_class.c_str());
224  critics_.push_back(plugin);
225  try {
226  plugin->initialize(node, critic_plugin_name, dwb_plugin_name_, costmap_ros_);
227  } catch (const std::exception & e) {
228  RCLCPP_ERROR(logger_, "Couldn't initialize critic plugin!");
230  "Couldn't initialize critic plugin: " +
231  std::string(e.what()));
232  }
233  RCLCPP_INFO(logger_, "Critic plugin initialized");
234  }
235 }
236 
237 void
238 DWBLocalPlanner::setPlan(const nav_msgs::msg::Path & path)
239 {
240  auto path2d = nav_2d_utils::pathToPath2D(path);
241  for (TrajectoryCritic::Ptr & critic : critics_) {
242  critic->reset();
243  }
244 
245  traj_generator_->reset();
246 
247  pub_->publishGlobalPlan(path2d);
248  global_plan_ = path2d;
249 }
250 
251 geometry_msgs::msg::TwistStamped
253  const geometry_msgs::msg::PoseStamped & pose,
254  const geometry_msgs::msg::Twist & velocity,
255  nav2_core::GoalChecker * /*goal_checker*/)
256 {
257  std::shared_ptr<dwb_msgs::msg::LocalPlanEvaluation> results = nullptr;
258  if (pub_->shouldRecordEvaluation()) {
259  results = std::make_shared<dwb_msgs::msg::LocalPlanEvaluation>();
260  }
261 
262  try {
263  nav_2d_msgs::msg::Twist2DStamped cmd_vel2d = computeVelocityCommands(
264  nav_2d_utils::poseStampedToPose2D(pose),
265  nav_2d_utils::twist3Dto2D(velocity), results);
266  pub_->publishEvaluation(results);
267  geometry_msgs::msg::TwistStamped cmd_vel;
268  cmd_vel.twist = nav_2d_utils::twist2Dto3D(cmd_vel2d.velocity);
269  return cmd_vel;
270  } catch (const nav2_core::ControllerTFError & e) {
271  pub_->publishEvaluation(results);
272  throw e;
273  } catch (const nav2_core::InvalidPath & e) {
274  pub_->publishEvaluation(results);
275  throw e;
276  } catch (const nav2_core::NoValidControl & e) {
277  pub_->publishEvaluation(results);
278  throw e;
279  } catch (const nav2_core::ControllerException & e) {
280  pub_->publishEvaluation(results);
281  throw e;
282  }
283 }
284 
285 void
287  const nav_2d_msgs::msg::Pose2DStamped & pose, nav_2d_msgs::msg::Path2D & transformed_plan,
288  nav_2d_msgs::msg::Pose2DStamped & goal_pose, bool publish_plan)
289 {
290  transformed_plan = transformGlobalPlan(pose);
291  if (publish_plan) {
292  pub_->publishTransformedPlan(transformed_plan);
293  }
294 
295  goal_pose.header.frame_id = global_plan_.header.frame_id;
296  goal_pose.pose = global_plan_.poses.back();
297  nav_2d_utils::transformPose(
298  tf_, costmap_ros_->getGlobalFrameID(), goal_pose,
299  goal_pose, transform_tolerance_);
300 }
301 
302 nav_2d_msgs::msg::Twist2DStamped
304  const nav_2d_msgs::msg::Pose2DStamped & pose,
305  const nav_2d_msgs::msg::Twist2D & velocity,
306  std::shared_ptr<dwb_msgs::msg::LocalPlanEvaluation> & results)
307 {
308  if (results) {
309  results->header.frame_id = pose.header.frame_id;
310  results->header.stamp = clock_->now();
311  }
312 
313  nav_2d_msgs::msg::Path2D transformed_plan;
314  nav_2d_msgs::msg::Pose2DStamped goal_pose;
315 
316  prepareGlobalPlan(pose, transformed_plan, goal_pose);
317 
318  nav2_costmap_2d::Costmap2D * costmap = costmap_ros_->getCostmap();
319  std::unique_lock<nav2_costmap_2d::Costmap2D::mutex_t> lock(*(costmap->getMutex()));
320 
321  for (TrajectoryCritic::Ptr & critic : critics_) {
322  if (!critic->prepare(pose.pose, velocity, goal_pose.pose, transformed_plan)) {
323  RCLCPP_WARN(rclcpp::get_logger("DWBLocalPlanner"), "A scoring function failed to prepare");
324  }
325  }
326 
327  try {
328  dwb_msgs::msg::TrajectoryScore best = coreScoringAlgorithm(pose.pose, velocity, results);
329 
330  // Return Value
331  nav_2d_msgs::msg::Twist2DStamped cmd_vel;
332  cmd_vel.header.stamp = clock_->now();
333  cmd_vel.velocity = best.traj.velocity;
334 
335  // debrief stateful scoring functions
336  for (TrajectoryCritic::Ptr & critic : critics_) {
337  critic->debrief(cmd_vel.velocity);
338  }
339 
340  lock.unlock();
341 
342  pub_->publishLocalPlan(pose.header, best.traj);
343  pub_->publishCostGrid(costmap_ros_, critics_);
344 
345  return cmd_vel;
346  } catch (const dwb_core::NoLegalTrajectoriesException & e) {
347  nav_2d_msgs::msg::Twist2D empty_cmd;
348  dwb_msgs::msg::Trajectory2D empty_traj;
349  // debrief stateful scoring functions
350  for (TrajectoryCritic::Ptr & critic : critics_) {
351  critic->debrief(empty_cmd);
352  }
353 
354  lock.unlock();
355 
356  pub_->publishLocalPlan(pose.header, empty_traj);
357  pub_->publishCostGrid(costmap_ros_, critics_);
358 
360  "Could not find a legal trajectory: " +
361  std::string(e.what()));
362  }
363 }
364 
365 dwb_msgs::msg::TrajectoryScore
367  const geometry_msgs::msg::Pose2D & pose,
368  const nav_2d_msgs::msg::Twist2D velocity,
369  std::shared_ptr<dwb_msgs::msg::LocalPlanEvaluation> & results)
370 {
371  nav_2d_msgs::msg::Twist2D twist;
372  dwb_msgs::msg::Trajectory2D traj;
373  dwb_msgs::msg::TrajectoryScore best, worst;
374  best.total = -1;
375  worst.total = -1;
376  IllegalTrajectoryTracker tracker;
377 
378  traj_generator_->startNewIteration(velocity);
379  while (traj_generator_->hasMoreTwists()) {
380  twist = traj_generator_->nextTwist();
381  traj = traj_generator_->generateTrajectory(pose, velocity, twist);
382 
383  try {
384  dwb_msgs::msg::TrajectoryScore score = scoreTrajectory(traj, best.total);
385  tracker.addLegalTrajectory();
386  if (results) {
387  results->twists.push_back(score);
388  }
389  if (best.total < 0 || score.total < best.total) {
390  best = score;
391  if (results) {
392  results->best_index = results->twists.size() - 1;
393  }
394  }
395  if (worst.total < 0 || score.total > worst.total) {
396  worst = score;
397  if (results) {
398  results->worst_index = results->twists.size() - 1;
399  }
400  }
401  } catch (const dwb_core::IllegalTrajectoryException & e) {
402  if (results) {
403  dwb_msgs::msg::TrajectoryScore failed_score;
404  failed_score.traj = traj;
405 
406  dwb_msgs::msg::CriticScore cs;
407  cs.name = e.getCriticName();
408  cs.raw_score = -1.0;
409  failed_score.scores.push_back(cs);
410  failed_score.total = -1.0;
411  results->twists.push_back(failed_score);
412  }
413  tracker.addIllegalTrajectory(e);
414  }
415  }
416 
417  if (best.total < 0) {
418  if (debug_trajectory_details_) {
419  RCLCPP_ERROR(rclcpp::get_logger("DWBLocalPlanner"), "%s", tracker.getMessage().c_str());
420  for (auto const & x : tracker.getPercentages()) {
421  RCLCPP_ERROR(
422  rclcpp::get_logger(
423  "DWBLocalPlanner"), "%.2f: %10s/%s", x.second,
424  x.first.first.c_str(), x.first.second.c_str());
425  }
426  }
427  throw NoLegalTrajectoriesException(tracker);
428  }
429 
430  return best;
431 }
432 
433 dwb_msgs::msg::TrajectoryScore
435  const dwb_msgs::msg::Trajectory2D & traj,
436  double best_score)
437 {
438  dwb_msgs::msg::TrajectoryScore score;
439  score.traj = traj;
440 
441  for (TrajectoryCritic::Ptr & critic : critics_) {
442  dwb_msgs::msg::CriticScore cs;
443  cs.name = critic->getName();
444  cs.scale = critic->getScale();
445 
446  if (cs.scale == 0.0) {
447  score.scores.push_back(cs);
448  continue;
449  }
450 
451  double critic_score = critic->scoreTrajectory(traj);
452  cs.raw_score = critic_score;
453  score.scores.push_back(cs);
454  score.total += critic_score * cs.scale;
455  if (short_circuit_trajectory_evaluation_ && best_score > 0 && score.total > best_score) {
456  // since we keep adding positives, once we are worse than the best, we will stay worse
457  break;
458  }
459  }
460 
461  return score;
462 }
463 
464 nav_2d_msgs::msg::Path2D
466  const nav_2d_msgs::msg::Pose2DStamped & pose)
467 {
468  if (global_plan_.poses.empty()) {
469  throw nav2_core::InvalidPath("Received plan with zero length");
470  }
471 
472  // let's get the pose of the robot in the frame of the plan
473  nav_2d_msgs::msg::Pose2DStamped robot_pose;
474  if (!nav_2d_utils::transformPose(
475  tf_, global_plan_.header.frame_id, pose,
476  robot_pose, transform_tolerance_))
477  {
478  throw nav2_core::
479  ControllerTFError("Unable to transform robot pose into global plan's frame");
480  }
481 
482  // we'll discard points on the plan that are outside the local costmap
483  nav2_costmap_2d::Costmap2D * costmap = costmap_ros_->getCostmap();
484  double dist_threshold = std::max(costmap->getSizeInCellsX(), costmap->getSizeInCellsY()) *
485  costmap->getResolution() / 2.0;
486 
487  // If prune_plan is enabled (it is by default) then we want to restrict the
488  // plan to distances within that range as well.
489  double prune_dist = prune_distance_;
490 
491  // Set the maximum distance we'll include points before getting to the part
492  // of the path where the robot is located (the start of the plan). Basically,
493  // these are the points the robot has already passed.
494  double transform_start_threshold;
495  if (prune_plan_) {
496  transform_start_threshold = std::min(dist_threshold, prune_dist);
497  } else {
498  transform_start_threshold = dist_threshold;
499  }
500 
501  // Set the maximum distance we'll include points after the part of the plan
502  // near the robot (the end of the plan). This determines the amount of the
503  // plan passed on to the critics
504  double transform_end_threshold;
505  double forward_prune_dist = forward_prune_distance_;
506  if (shorten_transformed_plan_) {
507  transform_end_threshold = std::min(dist_threshold, forward_prune_dist);
508  } else {
509  transform_end_threshold = dist_threshold;
510  }
511 
512  // Find the first pose in the global plan that's further than forward prune distance
513  // from the robot using integrated distance
514  auto prune_point = nav2_util::geometry_utils::first_after_integrated_distance(
515  global_plan_.poses.begin(), global_plan_.poses.end(), forward_prune_distance_);
516 
517  // Find the first pose in the plan (upto prune_point) that's less than transform_start_threshold
518  // from the robot.
519  auto transformation_begin = std::find_if(
520  begin(global_plan_.poses), prune_point,
521  [&](const auto & global_plan_pose) {
522  return euclidean_distance(robot_pose.pose, global_plan_pose) < transform_start_threshold;
523  });
524 
525  // Find the first pose in the end of the plan that's further than transform_end_threshold
526  // from the robot using integrated distance
527  auto transformation_end = std::find_if(
528  transformation_begin, global_plan_.poses.end(),
529  [&](const auto & global_plan_pose) {
530  return euclidean_distance(global_plan_pose, robot_pose.pose) > transform_end_threshold;
531  });
532 
533  // Transform the near part of the global plan into the robot's frame of reference.
534  nav_2d_msgs::msg::Path2D transformed_plan;
535  transformed_plan.header.frame_id = costmap_ros_->getGlobalFrameID();
536  transformed_plan.header.stamp = pose.header.stamp;
537 
538  // Helper function for the transform below. Converts a pose2D from global
539  // frame to local
540  auto transformGlobalPoseToLocal = [&](const auto & global_plan_pose) {
541  nav_2d_msgs::msg::Pose2DStamped stamped_pose, transformed_pose;
542  stamped_pose.header.frame_id = global_plan_.header.frame_id;
543  stamped_pose.pose = global_plan_pose;
544  nav_2d_utils::transformPose(
545  tf_, transformed_plan.header.frame_id,
546  stamped_pose, transformed_pose, transform_tolerance_);
547  return transformed_pose.pose;
548  };
549 
550  std::transform(
551  transformation_begin, transformation_end,
552  std::back_inserter(transformed_plan.poses),
553  transformGlobalPoseToLocal);
554 
555  // Remove the portion of the global plan that we've already passed so we don't
556  // process it on the next iteration.
557  if (prune_plan_) {
558  global_plan_.poses.erase(begin(global_plan_.poses), transformation_begin);
559  pub_->publishGlobalPlan(global_plan_);
560  }
561 
562  if (transformed_plan.poses.empty()) {
563  throw nav2_core::InvalidPath("Resulting plan has 0 poses in it.");
564  }
565  return transformed_plan;
566 }
567 
568 } // namespace dwb_core
569 
570 // Register this controller as a nav2_core plugin
571 PLUGINLIB_EXPORT_CLASS(
Plugin-based flexible controller.
void cleanup() override
Cleanup lifecycle node.
void setPlan(const nav_msgs::msg::Path &path) override
nav2_core setPlan - Sets the global plan
std::string resolveCriticClassName(std::string base_name)
try to resolve a possibly shortened critic name with the default namespaces and the suffix "Critic"
void deactivate() override
Deactivate lifecycle node.
void configure(const rclcpp_lifecycle::LifecycleNode::WeakPtr &parent, std::string name, std::shared_ptr< tf2_ros::Buffer > tf, std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros) override
DWBLocalPlanner()
Constructor that brings up pluginlib loaders.
virtual dwb_msgs::msg::TrajectoryScore coreScoringAlgorithm(const geometry_msgs::msg::Pose2D &pose, const nav_2d_msgs::msg::Twist2D velocity, std::shared_ptr< dwb_msgs::msg::LocalPlanEvaluation > &results)
Iterate through all the twists and find the best one.
virtual dwb_msgs::msg::TrajectoryScore scoreTrajectory(const dwb_msgs::msg::Trajectory2D &traj, double best_score=-1)
Score a given command. Can be used for testing.
void prepareGlobalPlan(const nav_2d_msgs::msg::Pose2DStamped &pose, nav_2d_msgs::msg::Path2D &transformed_plan, nav_2d_msgs::msg::Pose2DStamped &goal_pose, bool publish_plan=true)
Helper method for two common operations for the operating on the global_plan.
geometry_msgs::msg::TwistStamped computeVelocityCommands(const geometry_msgs::msg::PoseStamped &pose, const geometry_msgs::msg::Twist &velocity, nav2_core::GoalChecker *) override
nav2_core computeVelocityCommands - calculates the best command given the current pose and velocity
virtual void loadCritics()
Load the critic parameters from the namespace.
void activate() override
Activate lifecycle node.
nav_2d_msgs::msg::Path2D global_plan_
Saved Global Plan.
virtual nav_2d_msgs::msg::Path2D transformGlobalPlan(const nav_2d_msgs::msg::Pose2DStamped &pose)
Transforms global plan into same frame as pose, clips far away poses and possibly prunes passed poses...
Thrown when one of the critics encountered a fatal error.
Definition: exceptions.hpp:50
Thrown when all the trajectories explored are illegal.
controller interface that acts as a virtual base class for all controller plugins
Definition: controller.hpp:61
Function-object for checking whether a goal has been reached.
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.hpp:68
double getResolution() const
Accessor for the resolution of the costmap.
Definition: costmap_2d.cpp:544
unsigned int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
Definition: costmap_2d.cpp:514
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.
Definition: costmap_2d.cpp:519