20 #include "angles/angles.h"
21 #include "nav2_controller/plugins/axis_goal_checker.hpp"
22 #include "pluginlib/class_list_macros.hpp"
23 #include "nav2_ros_common/node_utils.hpp"
24 #include "nav2_util/geometry_utils.hpp"
26 using rcl_interfaces::msg::ParameterType;
27 using std::placeholders::_1;
29 namespace nav2_controller
33 : along_path_tolerance_(0.25), cross_track_tolerance_(0.25),
34 path_length_tolerance_(1.0), is_overshoot_valid_(false)
40 auto node = node_.lock();
41 if (post_set_params_handler_ && node) {
42 node->remove_post_set_parameters_callback(post_set_params_handler_.get());
44 post_set_params_handler_.reset();
45 if (on_set_params_handler_ && node) {
46 node->remove_on_set_parameters_callback(on_set_params_handler_.get());
48 on_set_params_handler_.reset();
52 const nav2::LifecycleNode::WeakPtr & parent,
53 const std::string & plugin_name,
54 const std::shared_ptr<nav2_costmap_2d::Costmap2DROS>)
56 plugin_name_ = plugin_name;
58 auto node = node_.lock();
59 logger_ = node->get_logger();
61 along_path_tolerance_ = node->declare_or_get_parameter(
62 plugin_name +
".along_path_tolerance", 0.25);
63 cross_track_tolerance_ = node->declare_or_get_parameter(
64 plugin_name +
".cross_track_tolerance", 0.25);
65 path_length_tolerance_ = node->declare_or_get_parameter(
66 plugin_name +
".path_length_tolerance", 1.0);
67 is_overshoot_valid_ = node->declare_or_get_parameter(
68 plugin_name +
".is_overshoot_valid",
false);
71 post_set_params_handler_ = node->add_post_set_parameters_callback(
74 this, std::placeholders::_1));
75 on_set_params_handler_ = node->add_on_set_parameters_callback(
78 this, std::placeholders::_1));
86 const geometry_msgs::msg::Pose & query_pose,
const geometry_msgs::msg::Pose & goal_pose,
87 const geometry_msgs::msg::Twist & velocity,
88 const nav_msgs::msg::Path & transformed_global_plan)
92 return isGoalXYReached(query_pose, goal_pose, velocity, transformed_global_plan);
96 const geometry_msgs::msg::Pose & query_pose,
const geometry_msgs::msg::Pose & goal_pose,
97 const geometry_msgs::msg::Twist &,
98 const nav_msgs::msg::Path & transformed_global_plan)
100 std::lock_guard<std::mutex> lock_reinit(mutex_);
102 if (nav2_util::geometry_utils::calculate_path_length(transformed_global_plan) >
103 path_length_tolerance_)
109 if (transformed_global_plan.poses.size() >= 2) {
112 const geometry_msgs::msg::Pose * before_goal_pose_ptr =
nullptr;
116 for (
int i = transformed_global_plan.poses.size() - 2; i >= 0; --i) {
117 const auto & candidate_pose = transformed_global_plan.poses[i].pose;
118 dx = goal_pose.position.x - candidate_pose.position.x;
119 dy = goal_pose.position.y - candidate_pose.position.y;
120 double pose_distance = std::hypot(dx, dy);
122 if (pose_distance >= 1e-6) {
123 before_goal_pose_ptr = &candidate_pose;
129 if (!before_goal_pose_ptr) {
132 "All poses in path are too close to goal, falling back to simple distance check");
133 double distance_to_goal = std::hypot(
134 goal_pose.position.x - query_pose.position.x,
135 goal_pose.position.y - query_pose.position.y);
136 double tolerance = std::hypot(along_path_tolerance_, cross_track_tolerance_);
137 return distance_to_goal < tolerance;
141 double end_of_path_yaw = atan2(dy, dx);
144 double robot_to_goal_dx = goal_pose.position.x - query_pose.position.x;
145 double robot_to_goal_dy = goal_pose.position.y - query_pose.position.y;
146 double distance_to_goal = std::hypot(robot_to_goal_dx, robot_to_goal_dy);
148 if (distance_to_goal < 1e-6) {
152 double robot_to_goal_yaw = atan2(robot_to_goal_dy, robot_to_goal_dx);
153 double projection_angle = angles::shortest_angular_distance(
154 robot_to_goal_yaw, end_of_path_yaw);
155 double along_path_distance = distance_to_goal * cos(projection_angle);
156 double cross_track_distance = distance_to_goal * sin(projection_angle);
158 if (is_overshoot_valid_) {
159 return along_path_distance < along_path_tolerance_ &&
160 fabs(cross_track_distance) < cross_track_tolerance_;
162 return fabs(along_path_distance) < along_path_tolerance_ &&
163 fabs(cross_track_distance) < cross_track_tolerance_;
169 "Path has fewer than 2 poses, falling back to simple distance check");
170 double distance_to_goal = std::hypot(
171 goal_pose.position.x - query_pose.position.x,
172 goal_pose.position.y - query_pose.position.y);
173 double tolerance = std::hypot(along_path_tolerance_, cross_track_tolerance_);
174 return distance_to_goal < tolerance;
179 geometry_msgs::msg::Pose & pose_tolerance,
180 geometry_msgs::msg::Twist & vel_tolerance,
181 double & path_length_tolerance)
183 std::lock_guard<std::mutex> lock_reinit(mutex_);
184 double invalid_field = std::numeric_limits<double>::lowest();
186 pose_tolerance.position.x = std::min(along_path_tolerance_, cross_track_tolerance_);
187 pose_tolerance.position.y = std::min(along_path_tolerance_, cross_track_tolerance_);
188 pose_tolerance.position.z = invalid_field;
189 pose_tolerance.orientation =
190 nav2_util::geometry_utils::orientationAroundZAxis(M_PI_2);
192 vel_tolerance.linear.x = invalid_field;
193 vel_tolerance.linear.y = invalid_field;
194 vel_tolerance.linear.z = invalid_field;
196 vel_tolerance.angular.x = invalid_field;
197 vel_tolerance.angular.y = invalid_field;
198 vel_tolerance.angular.z = invalid_field;
200 path_length_tolerance = path_length_tolerance_;
205 rcl_interfaces::msg::SetParametersResult
207 const std::vector<rclcpp::Parameter> & parameters)
209 rcl_interfaces::msg::SetParametersResult result;
210 result.successful =
true;
211 for (
auto parameter : parameters) {
212 const auto & param_type = parameter.get_type();
213 const auto & param_name = parameter.get_name();
214 if (param_name.find(plugin_name_ +
".") != 0) {
217 if (param_type == ParameterType::PARAMETER_DOUBLE) {
218 if (parameter.as_double() < 0.0) {
220 logger_,
"The value of parameter '%s' is incorrectly set to %f, "
221 "it should be >=0. Ignoring parameter update.",
222 param_name.c_str(), parameter.as_double());
223 result.successful =
false;
232 const std::vector<rclcpp::Parameter> & parameters)
234 std::lock_guard<std::mutex> lock_reinit(mutex_);
235 for (
const auto & parameter : parameters) {
236 const auto & type = parameter.get_type();
237 const auto & name = parameter.get_name();
238 if (name.find(plugin_name_ +
".") != 0) {
241 if (type == ParameterType::PARAMETER_DOUBLE) {
242 if (name == plugin_name_ +
".along_path_tolerance") {
243 along_path_tolerance_ = parameter.as_double();
244 }
else if (name == plugin_name_ +
".cross_track_tolerance") {
245 cross_track_tolerance_ = parameter.as_double();
246 }
else if (name == plugin_name_ +
".path_length_tolerance") {
247 path_length_tolerance_ = parameter.as_double();
249 }
else if (type == ParameterType::PARAMETER_BOOL) {
250 if (name == plugin_name_ +
".is_overshoot_valid") {
251 is_overshoot_valid_ = parameter.as_bool();
Goal Checker plugin that checks progress along the axis defined by the last segment of the path to th...
bool getTolerances(geometry_msgs::msg::Pose &pose_tolerance, geometry_msgs::msg::Twist &vel_tolerance, double &path_length_tolerance) override
Get the position and velocity tolerances.
~AxisGoalChecker()
Destroy the Axis Goal Checker object.
bool isGoalXYReached(const geometry_msgs::msg::Pose &query_pose, const geometry_msgs::msg::Pose &goal_pose, const geometry_msgs::msg::Twist &velocity, const nav_msgs::msg::Path &transformed_global_plan) override
Check if XY goal position has been reached (without considering yaw)
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(const std::vector< rclcpp::Parameter > ¶meters)
Validate incoming parameter updates before applying them. This callback is triggered when one or more...
void reset() override
Reset the goal checker state.
void initialize(const nav2::LifecycleNode::WeakPtr &parent, const std::string &plugin_name, const std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros) override
Initialize the goal checker.
bool isGoalReached(const geometry_msgs::msg::Pose &query_pose, const geometry_msgs::msg::Pose &goal_pose, const geometry_msgs::msg::Twist &velocity, const nav_msgs::msg::Path &transformed_global_plan) override
Check if the goal is reached.
void updateParametersCallback(const std::vector< rclcpp::Parameter > ¶meters)
Apply parameter updates after validation This callback is executed when parameters have been successf...
AxisGoalChecker()
Construct a new Axis Goal Checker object.
Function-object for checking whether a goal has been reached.