Nav2 Navigation Stack - jazzy  jazzy
ROS 2 Navigation Stack
simple_goal_checker.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 <memory>
36 #include <string>
37 #include <limits>
38 #include <vector>
39 #include "nav2_controller/plugins/simple_goal_checker.hpp"
40 #include "pluginlib/class_list_macros.hpp"
41 #include "angles/angles.h"
42 #include "nav2_util/node_utils.hpp"
43 #include "nav2_util/geometry_utils.hpp"
44 #pragma GCC diagnostic push
45 #pragma GCC diagnostic ignored "-Wpedantic"
46 #include "tf2/utils.h"
47 #pragma GCC diagnostic pop
48 
49 using rcl_interfaces::msg::ParameterType;
50 using std::placeholders::_1;
51 
52 namespace nav2_controller
53 {
54 
55 SimpleGoalChecker::SimpleGoalChecker()
56 : xy_goal_tolerance_(0.25),
57  yaw_goal_tolerance_(0.25),
58  stateful_(true),
59  check_xy_(true),
60  symmetric_yaw_tolerance_(false),
61  xy_goal_tolerance_sq_(0.0625)
62 {
63 }
64 
65 void SimpleGoalChecker::initialize(
66  const rclcpp_lifecycle::LifecycleNode::WeakPtr & parent,
67  const std::string & plugin_name,
68  const std::shared_ptr<nav2_costmap_2d::Costmap2DROS>/*costmap_ros*/)
69 {
70  plugin_name_ = plugin_name;
71  auto node = parent.lock();
72 
73  nav2_util::declare_parameter_if_not_declared(
74  node,
75  plugin_name + ".xy_goal_tolerance", rclcpp::ParameterValue(0.25));
76  nav2_util::declare_parameter_if_not_declared(
77  node,
78  plugin_name + ".yaw_goal_tolerance", rclcpp::ParameterValue(0.25));
79  nav2_util::declare_parameter_if_not_declared(
80  node,
81  plugin_name + ".stateful", rclcpp::ParameterValue(true));
82  nav2_util::declare_parameter_if_not_declared(
83  node,
84  plugin_name + ".symmetric_yaw_tolerance", rclcpp::ParameterValue(false));
85 
86  node->get_parameter(plugin_name + ".xy_goal_tolerance", xy_goal_tolerance_);
87  node->get_parameter(plugin_name + ".yaw_goal_tolerance", yaw_goal_tolerance_);
88  node->get_parameter(plugin_name + ".stateful", stateful_);
89  node->get_parameter(plugin_name + ".symmetric_yaw_tolerance", symmetric_yaw_tolerance_);
90 
91  xy_goal_tolerance_sq_ = xy_goal_tolerance_ * xy_goal_tolerance_;
92 
93  // Add callback for dynamic parameters
94  dyn_params_handler_ = node->add_on_set_parameters_callback(
95  std::bind(&SimpleGoalChecker::dynamicParametersCallback, this, _1));
96 }
97 
98 void SimpleGoalChecker::reset()
99 {
100  check_xy_ = true;
101 }
102 
103 bool SimpleGoalChecker::isGoalReached(
104  const geometry_msgs::msg::Pose & query_pose, const geometry_msgs::msg::Pose & goal_pose,
105  const geometry_msgs::msg::Twist &)
106 {
107  if (check_xy_) {
108  double dx = query_pose.position.x - goal_pose.position.x,
109  dy = query_pose.position.y - goal_pose.position.y;
110  if (dx * dx + dy * dy > xy_goal_tolerance_sq_) {
111  return false;
112  }
113  // We are within the window
114  // If we are stateful, change the state.
115  if (stateful_) {
116  check_xy_ = false;
117  }
118  }
119 
120  double query_yaw = tf2::getYaw(query_pose.orientation);
121  double goal_yaw = tf2::getYaw(goal_pose.orientation);
122  if (symmetric_yaw_tolerance_) {
123  // For symmetric robots: accept either goal orientation or goal + 180°
124  double dyaw_forward = angles::shortest_angular_distance(query_yaw, goal_yaw);
125  double dyaw_backward = angles::shortest_angular_distance(
126  query_yaw, angles::normalize_angle(goal_yaw + M_PI));
127 
128  bool forward_match = fabs(dyaw_forward) <= yaw_goal_tolerance_;
129  bool backward_match = fabs(dyaw_backward) <= yaw_goal_tolerance_;
130 
131  return forward_match || backward_match;
132  } else {
133  double dyaw = angles::shortest_angular_distance(query_yaw, goal_yaw);
134  return fabs(dyaw) <= yaw_goal_tolerance_;
135  }
136 }
137 
138 bool SimpleGoalChecker::getTolerances(
139  geometry_msgs::msg::Pose & pose_tolerance,
140  geometry_msgs::msg::Twist & vel_tolerance)
141 {
142  double invalid_field = std::numeric_limits<double>::lowest();
143 
144  pose_tolerance.position.x = xy_goal_tolerance_;
145  pose_tolerance.position.y = xy_goal_tolerance_;
146  pose_tolerance.position.z = invalid_field;
147  pose_tolerance.orientation =
148  nav2_util::geometry_utils::orientationAroundZAxis(yaw_goal_tolerance_);
149 
150  vel_tolerance.linear.x = invalid_field;
151  vel_tolerance.linear.y = invalid_field;
152  vel_tolerance.linear.z = invalid_field;
153 
154  vel_tolerance.angular.x = invalid_field;
155  vel_tolerance.angular.y = invalid_field;
156  vel_tolerance.angular.z = invalid_field;
157 
158  return true;
159 }
160 
161 rcl_interfaces::msg::SetParametersResult
162 SimpleGoalChecker::dynamicParametersCallback(std::vector<rclcpp::Parameter> parameters)
163 {
164  rcl_interfaces::msg::SetParametersResult result;
165  for (auto & parameter : parameters) {
166  const auto & type = parameter.get_type();
167  const auto & name = parameter.get_name();
168 
169  if (type == ParameterType::PARAMETER_DOUBLE) {
170  if (name == plugin_name_ + ".xy_goal_tolerance") {
171  xy_goal_tolerance_ = parameter.as_double();
172  xy_goal_tolerance_sq_ = xy_goal_tolerance_ * xy_goal_tolerance_;
173  } else if (name == plugin_name_ + ".yaw_goal_tolerance") {
174  yaw_goal_tolerance_ = parameter.as_double();
175  }
176  } else if (type == ParameterType::PARAMETER_BOOL) {
177  if (name == plugin_name_ + ".stateful") {
178  stateful_ = parameter.as_bool();
179  } else if (name == plugin_name_ + ".symmetric_yaw_tolerance") {
180  symmetric_yaw_tolerance_ = parameter.as_bool();
181  }
182  }
183  }
184  result.successful = true;
185  return result;
186 }
187 
188 } // namespace nav2_controller
189 
Goal Checker plugin that only checks the position difference.
Function-object for checking whether a goal has been reached.