Skip to content

Commit 83c9c71

Browse files
jadhmSteveMacenski
authored andcommitted
Add stateful to regulated pure pursuit controller (#5167)
* add_stateful_to_regulated_pure_pursuit_controller Signed-off-by: Jad haj mustafa <jhajmustafa@lely.com> * fix naming Signed-off-by: Jad haj mustafa <jhajmustafa@lely.com> * fix naming left over Signed-off-by: Jad haj mustafa <jhajmustafa@lely.com> * resolve comments Signed-off-by: Jad haj mustafa <jhajmustafa@lely.com> * typo Signed-off-by: Jad haj mustafa <jhajmustafa@lely.com> * add unit test for both cases stateful and not stateful Signed-off-by: Jad haj mustafa <jhajmustafa@lely.com> --------- Signed-off-by: Jad haj mustafa <jhajmustafa@lely.com>
1 parent 630fd45 commit 83c9c71

File tree

5 files changed

+54
-3
lines changed

5 files changed

+54
-3
lines changed

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
@@ -61,6 +61,7 @@ struct Parameters
6161
bool interpolate_curvature_after_goal;
6262
bool use_collision_detection;
6363
double transform_tolerance;
64+
bool stateful;
6465
};
6566

6667
/**

nav2_regulated_pure_pursuit_controller/include/nav2_regulated_pure_pursuit_controller/regulated_pure_pursuit_controller.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ class RegulatedPurePursuitController : public nav2_core::Controller
220220
bool cancelling_ = false;
221221
bool finished_cancelling_ = false;
222222
bool is_rotating_to_heading_ = false;
223+
bool has_reached_xy_tolerance_ = false;
223224

224225
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<nav_msgs::msg::Path>> global_path_pub_;
225226
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
@@ -101,6 +101,8 @@ ParameterHandler::ParameterHandler(
101101
declare_parameter_if_not_declared(
102102
node, plugin_name_ + ".use_collision_detection",
103103
rclcpp::ParameterValue(true));
104+
declare_parameter_if_not_declared(
105+
node, plugin_name_ + ".stateful", rclcpp::ParameterValue(true));
104106

105107
node->get_parameter(plugin_name_ + ".desired_linear_vel", params_.desired_linear_vel);
106108
params_.base_desired_linear_vel = params_.desired_linear_vel;
@@ -181,6 +183,7 @@ ParameterHandler::ParameterHandler(
181183
node->get_parameter(
182184
plugin_name_ + ".use_collision_detection",
183185
params_.use_collision_detection);
186+
node->get_parameter(plugin_name_ + ".stateful", params_.stateful);
184187

185188
if (params_.inflation_cost_scaling_factor <= 0.0) {
186189
RCLCPP_WARN(
@@ -307,6 +310,8 @@ ParameterHandler::updateParametersCallback(
307310
params_.use_cost_regulated_linear_velocity_scaling = parameter.as_bool();
308311
} else if (name == plugin_name_ + ".use_collision_detection") {
309312
params_.use_collision_detection = parameter.as_bool();
313+
} else if (name == plugin_name_ + ".stateful") {
314+
params_.stateful = parameter.as_bool();
310315
} else if (name == plugin_name_ + ".use_rotate_to_heading") {
311316
params_.use_rotate_to_heading = parameter.as_bool();
312317
} else if (name == plugin_name_ + ".use_cancel_deceleration") {

nav2_regulated_pure_pursuit_controller/src/regulated_pure_pursuit_controller.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,21 @@ bool RegulatedPurePursuitController::shouldRotateToGoalHeading(
320320
const geometry_msgs::msg::PoseStamped & carrot_pose)
321321
{
322322
// Whether we should rotate robot to goal heading
323-
double dist_to_goal = std::hypot(carrot_pose.pose.position.x, carrot_pose.pose.position.y);
324-
return params_->use_rotate_to_heading && dist_to_goal < goal_dist_tol_;
323+
if (!params_->use_rotate_to_heading) {
324+
return false;
325+
}
326+
327+
double dist_to_goal = std::hypot(
328+
carrot_pose.pose.position.x, carrot_pose.pose.position.y);
329+
330+
if (params_->stateful) {
331+
if (!has_reached_xy_tolerance_ && dist_to_goal < goal_dist_tol_) {
332+
has_reached_xy_tolerance_ = true;
333+
}
334+
return has_reached_xy_tolerance_;
335+
}
336+
337+
return dist_to_goal < goal_dist_tol_;
325338
}
326339

327340
void RegulatedPurePursuitController::rotateToHeading(
@@ -466,6 +479,7 @@ void RegulatedPurePursuitController::applyConstraints(
466479

467480
void RegulatedPurePursuitController::setPlan(const nav_msgs::msg::Path & path)
468481
{
482+
has_reached_xy_tolerance_ = false;
469483
path_handler_->setPlan(path);
470484
}
471485

@@ -493,6 +507,7 @@ void RegulatedPurePursuitController::reset()
493507
{
494508
cancelling_ = false;
495509
finished_cancelling_ = false;
510+
has_reached_xy_tolerance_ = false;
496511
}
497512

498513
double RegulatedPurePursuitController::findVelocitySignChange(

nav2_regulated_pure_pursuit_controller/test/test_regulated_pp.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,14 @@ TEST(RegulatedPurePursuitTest, lookaheadAPI)
498498

499499
TEST(RegulatedPurePursuitTest, rotateTests)
500500
{
501+
// --------------------------
502+
// Non-Stateful Configuration
503+
// --------------------------
501504
auto ctrl = std::make_shared<BasicAPIRPP>();
502505
auto node = std::make_shared<rclcpp_lifecycle::LifecycleNode>("testRPP");
506+
nav2_util::declare_parameter_if_not_declared(
507+
node, "PathFollower.stateful", rclcpp::ParameterValue(false));
508+
503509
std::string name = "PathFollower";
504510
auto tf = std::make_shared<tf2_ros::Buffer>(node->get_clock());
505511
auto costmap = std::make_shared<nav2_costmap_2d::Costmap2DROS>("fake_costmap");
@@ -565,6 +571,27 @@ TEST(RegulatedPurePursuitTest, rotateTests)
565571
curr_speed.angular.z = 1.0;
566572
ctrl->rotateToHeadingWrapper(lin_v, ang_v, angle_to_path, curr_speed);
567573
EXPECT_NEAR(ang_v, 0.84, 0.01);
574+
575+
// -----------------------
576+
// Stateful Configuration
577+
// -----------------------
578+
node->set_parameter(
579+
rclcpp::Parameter("PathFollower.stateful", true));
580+
581+
ctrl->configure(node, name, tf, costmap);
582+
583+
// Start just outside tolerance
584+
carrot.pose.position.x = 0.0;
585+
carrot.pose.position.y = 0.26;
586+
EXPECT_EQ(ctrl->shouldRotateToGoalHeadingWrapper(carrot), false);
587+
588+
// Enter tolerance (should set internal flag)
589+
carrot.pose.position.y = 0.24;
590+
EXPECT_EQ(ctrl->shouldRotateToGoalHeadingWrapper(carrot), true);
591+
592+
// Move outside tolerance again - still expect true (due to persistent state)
593+
carrot.pose.position.y = 0.26;
594+
EXPECT_EQ(ctrl->shouldRotateToGoalHeadingWrapper(carrot), true);
568595
}
569596

570597
TEST(RegulatedPurePursuitTest, applyConstraints)
@@ -705,7 +732,8 @@ TEST(RegulatedPurePursuitTest, testDynamicParameter)
705732
rclcpp::Parameter("test.use_cost_regulated_linear_velocity_scaling", false),
706733
rclcpp::Parameter("test.inflation_cost_scaling_factor", 1.0),
707734
rclcpp::Parameter("test.allow_reversing", false),
708-
rclcpp::Parameter("test.use_rotate_to_heading", false)});
735+
rclcpp::Parameter("test.use_rotate_to_heading", false),
736+
rclcpp::Parameter("test.stateful", false)});
709737

710738
rclcpp::spin_until_future_complete(
711739
node->get_node_base_interface(),
@@ -736,6 +764,7 @@ TEST(RegulatedPurePursuitTest, testDynamicParameter)
736764
"test.use_cost_regulated_linear_velocity_scaling").as_bool(), false);
737765
EXPECT_EQ(node->get_parameter("test.allow_reversing").as_bool(), false);
738766
EXPECT_EQ(node->get_parameter("test.use_rotate_to_heading").as_bool(), false);
767+
EXPECT_EQ(node->get_parameter("test.stateful").as_bool(), false);
739768

740769
// Should fail
741770
auto results2 = rec_param->set_parameters_atomically(

0 commit comments

Comments
 (0)