Skip to content

Commit 2ecc91e

Browse files
Add API to gracefully cancel a controller (#4136)
* Add API to gracefully cancel a controller Signed-off-by: Ramon Wijnands <[email protected]> * Add `cancel_deceleration` to RegulatedPurePursuitController Signed-off-by: Ramon Wijnands <[email protected]> * Update nav2_regulated_pure_pursuit_controller/src/parameter_handler.cpp Co-authored-by: Steve Macenski <[email protected]> Signed-off-by: Ramon Wijnands <[email protected]> --------- Signed-off-by: Ramon Wijnands <[email protected]> Signed-off-by: Ramon Wijnands <[email protected]> Co-authored-by: Steve Macenski <[email protected]>
1 parent 80bb5bf commit 2ecc91e

File tree

6 files changed

+60
-4
lines changed

6 files changed

+60
-4
lines changed

nav2_controller/src/controller_server.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,10 +460,15 @@ void ControllerServer::computeControl()
460460
}
461461

462462
if (action_server_->is_cancel_requested()) {
463-
RCLCPP_INFO(get_logger(), "Goal was canceled. Stopping the robot.");
464-
action_server_->terminate_all();
465-
publishZeroVelocity();
466-
return;
463+
if (controllers_[current_controller_]->cancel()) {
464+
RCLCPP_INFO(get_logger(), "Cancellation was successful. Stopping the robot.");
465+
action_server_->terminate_all();
466+
publishZeroVelocity();
467+
return;
468+
} else {
469+
RCLCPP_INFO_THROTTLE(
470+
get_logger(), *get_clock(), 1000, "Waiting for the controller to finish cancellation");
471+
}
467472
}
468473

469474
// Don't compute a trajectory until costmap is valid (after clear costmap)

nav2_core/include/nav2_core/controller.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ class Controller
116116
const geometry_msgs::msg::Twist & velocity,
117117
nav2_core::GoalChecker * goal_checker) = 0;
118118

119+
/**
120+
* @brief Cancel the current control action
121+
* @return True if the cancellation was successful. If false is returned, computeVelocityCommands
122+
* will be called until cancel returns true.
123+
*/
124+
virtual bool cancel()
125+
{
126+
return true;
127+
}
128+
119129
/**
120130
* @brief Limits the maximum linear speed of the robot.
121131
* @param speed_limit expressed in absolute value (in m/s)

nav2_regulated_pure_pursuit_controller/include/nav2_regulated_pure_pursuit_controller/parameter_handler.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct Parameters
5353
double curvature_lookahead_dist;
5454
bool use_rotate_to_heading;
5555
double max_angular_accel;
56+
double cancel_deceleration;
5657
double rotate_to_heading_min_angle;
5758
bool allow_reversing;
5859
double max_robot_pose_search_dist;

nav2_regulated_pure_pursuit_controller/include/nav2_regulated_pure_pursuit_controller/regulated_pure_pursuit_controller.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ class RegulatedPurePursuitController : public nav2_core::Controller
9696
const geometry_msgs::msg::Twist & velocity,
9797
nav2_core::GoalChecker * /*goal_checker*/) override;
9898

99+
bool cancel() override;
100+
99101
/**
100102
* @brief nav2_core setPlan - Sets the global plan
101103
* @param path The global plan
@@ -111,6 +113,8 @@ class RegulatedPurePursuitController : public nav2_core::Controller
111113
*/
112114
void setSpeedLimit(const double & speed_limit, const bool & percentage) override;
113115

116+
void reset() override;
117+
114118
protected:
115119
/**
116120
* @brief Get lookahead distance
@@ -212,6 +216,8 @@ class RegulatedPurePursuitController : public nav2_core::Controller
212216
Parameters * params_;
213217
double goal_dist_tol_;
214218
double control_duration_;
219+
bool cancelling_ = false;
220+
bool finished_cancelling_ = false;
215221

216222
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<nav_msgs::msg::Path>> global_path_pub_;
217223
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<geometry_msgs::msg::PointStamped>>

nav2_regulated_pure_pursuit_controller/src/parameter_handler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ ParameterHandler::ParameterHandler(
8585
node, plugin_name_ + ".rotate_to_heading_min_angle", rclcpp::ParameterValue(0.785));
8686
declare_parameter_if_not_declared(
8787
node, plugin_name_ + ".max_angular_accel", rclcpp::ParameterValue(3.2));
88+
declare_parameter_if_not_declared(
89+
node, plugin_name_ + ".cancel_deceleration", rclcpp::ParameterValue(3.2));
8890
declare_parameter_if_not_declared(
8991
node, plugin_name_ + ".allow_reversing", rclcpp::ParameterValue(false));
9092
declare_parameter_if_not_declared(
@@ -151,6 +153,7 @@ ParameterHandler::ParameterHandler(
151153
node->get_parameter(
152154
plugin_name_ + ".rotate_to_heading_min_angle", params_.rotate_to_heading_min_angle);
153155
node->get_parameter(plugin_name_ + ".max_angular_accel", params_.max_angular_accel);
156+
node->get_parameter(plugin_name_ + ".cancel_deceleration", params_.cancel_deceleration);
154157
node->get_parameter(plugin_name_ + ".allow_reversing", params_.allow_reversing);
155158
node->get_parameter(
156159
plugin_name_ + ".max_robot_pose_search_dist",
@@ -237,6 +240,8 @@ ParameterHandler::dynamicParametersCallback(
237240
params_.regulated_linear_scaling_min_speed = parameter.as_double();
238241
} else if (name == plugin_name_ + ".max_angular_accel") {
239242
params_.max_angular_accel = parameter.as_double();
243+
} else if (name == plugin_name_ + ".cancel_deceleration") {
244+
params_.cancel_deceleration = parameter.as_double();
240245
} else if (name == plugin_name_ + ".rotate_to_heading_min_angle") {
241246
params_.rotate_to_heading_min_angle = parameter.as_double();
242247
}

nav2_regulated_pure_pursuit_controller/src/regulated_pure_pursuit_controller.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,23 @@ geometry_msgs::msg::TwistStamped RegulatedPurePursuitController::computeVelocity
238238
collision_checker_->costAtPose(pose.pose.position.x, pose.pose.position.y), transformed_plan,
239239
linear_vel, x_vel_sign);
240240

241+
if (cancelling_) {
242+
const double & dt = control_duration_;
243+
linear_vel = speed.linear.x - x_vel_sign * dt * params_->cancel_deceleration;
244+
245+
if (x_vel_sign > 0) {
246+
if (linear_vel <= 0) {
247+
linear_vel = 0;
248+
finished_cancelling_ = true;
249+
}
250+
} else {
251+
if (linear_vel >= 0) {
252+
linear_vel = 0;
253+
finished_cancelling_ = true;
254+
}
255+
}
256+
}
257+
241258
// Apply curvature to angular velocity after constraining linear velocity
242259
angular_vel = linear_vel * regulation_curvature;
243260
}
@@ -258,6 +275,12 @@ geometry_msgs::msg::TwistStamped RegulatedPurePursuitController::computeVelocity
258275
return cmd_vel;
259276
}
260277

278+
bool RegulatedPurePursuitController::cancel()
279+
{
280+
cancelling_ = true;
281+
return finished_cancelling_;
282+
}
283+
261284
bool RegulatedPurePursuitController::shouldRotateToPath(
262285
const geometry_msgs::msg::PoseStamped & carrot_pose, double & angle_to_path,
263286
double & x_vel_sign)
@@ -445,6 +468,12 @@ void RegulatedPurePursuitController::setSpeedLimit(
445468
}
446469
}
447470

471+
void RegulatedPurePursuitController::reset()
472+
{
473+
cancelling_ = false;
474+
finished_cancelling_ = false;
475+
}
476+
448477
double RegulatedPurePursuitController::findVelocitySignChange(
449478
const nav_msgs::msg::Path & transformed_plan)
450479
{

0 commit comments

Comments
 (0)