Skip to content

Commit 33cb0b6

Browse files
padhupradheepSteveMacenski
authored andcommitted
Feature addition: capability for the RRP to drive the robot backwards (#2443)
* Feature addition: capability for the RRP to drive the robot backwards * findDirectionChange(): returns maximum double value + removing the size check for the indexer in for loop * satisfying ament_uncrustify and ament_cpplint * removing the unnecessary condition in the cusp determination * Satisfying ament_uncrustify - 2
1 parent bdc600f commit 33cb0b6

File tree

3 files changed

+81
-10
lines changed

3 files changed

+81
-10
lines changed

nav2_regulated_pure_pursuit_controller/include/nav2_regulated_pure_pursuit_controller/regulated_pure_pursuit_controller.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class RegulatedPurePursuitController : public nav2_core::Controller
210210
void applyConstraints(
211211
const double & dist_error, const double & lookahead_dist,
212212
const double & curvature, const geometry_msgs::msg::Twist & speed,
213-
const double & pose_cost, double & linear_vel);
213+
const double & pose_cost, double & linear_vel, double & sign);
214214

215215
/**
216216
* @brief Get lookahead point
@@ -220,6 +220,13 @@ class RegulatedPurePursuitController : public nav2_core::Controller
220220
*/
221221
geometry_msgs::msg::PoseStamped getLookAheadPoint(const double &, const nav_msgs::msg::Path &);
222222

223+
/**
224+
* @brief checks for the cusp position
225+
* @param pose Pose input to determine the cusp position
226+
* @return robot distance from the cusp
227+
*/
228+
double findDirectionChange(const geometry_msgs::msg::PoseStamped & pose);
229+
223230
std::shared_ptr<tf2_ros::Buffer> tf_;
224231
std::string plugin_name_;
225232
std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros_;
@@ -251,6 +258,7 @@ class RegulatedPurePursuitController : public nav2_core::Controller
251258
double max_angular_accel_;
252259
double rotate_to_heading_min_angle_;
253260
double goal_dist_tol_;
261+
bool allow_reversing_;
254262

255263
nav_msgs::msg::Path global_plan_;
256264
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<nav_msgs::msg::Path>> global_path_pub_;

nav2_regulated_pure_pursuit_controller/src/regulated_pure_pursuit_controller.cpp

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <algorithm>
1717
#include <string>
18+
#include <limits>
1819
#include <memory>
1920
#include <utility>
2021

@@ -103,6 +104,8 @@ void RegulatedPurePursuitController::configure(
103104
node, plugin_name_ + ".rotate_to_heading_min_angle", rclcpp::ParameterValue(0.785));
104105
declare_parameter_if_not_declared(
105106
node, plugin_name_ + ".max_angular_accel", rclcpp::ParameterValue(3.2));
107+
declare_parameter_if_not_declared(
108+
node, plugin_name_ + ".allow_reversing", rclcpp::ParameterValue(false));
106109

107110
node->get_parameter(plugin_name_ + ".desired_linear_vel", desired_linear_vel_);
108111
base_desired_linear_vel_ = desired_linear_vel_;
@@ -148,6 +151,7 @@ void RegulatedPurePursuitController::configure(
148151
node->get_parameter(plugin_name_ + ".use_rotate_to_heading", use_rotate_to_heading_);
149152
node->get_parameter(plugin_name_ + ".rotate_to_heading_min_angle", rotate_to_heading_min_angle_);
150153
node->get_parameter(plugin_name_ + ".max_angular_accel", max_angular_accel_);
154+
node->get_parameter(plugin_name_ + ".allow_reversing", allow_reversing_);
151155
node->get_parameter("controller_frequency", control_frequency);
152156

153157
transform_tolerance_ = tf2::durationFromSec(transform_tolerance);
@@ -160,6 +164,16 @@ void RegulatedPurePursuitController::configure(
160164
use_cost_regulated_linear_velocity_scaling_ = false;
161165
}
162166

167+
/** Possible to drive in reverse direction if and only if
168+
"use_rotate_to_heading" parameter is set to false **/
169+
170+
if (use_rotate_to_heading_ && allow_reversing_) {
171+
RCLCPP_WARN(
172+
logger_, "Disabling reversing. Both use_rotate_to_heading and allow_reversing "
173+
"parameter cannot be set to true. By default setting use_rotate_to_heading true");
174+
allow_reversing_ = false;
175+
}
176+
163177
global_path_pub_ = node->create_publisher<nav_msgs::msg::Path>("received_global_plan", 1);
164178
carrot_pub_ = node->create_publisher<geometry_msgs::msg::PointStamped>("lookahead_point", 1);
165179
carrot_arc_pub_ = node->create_publisher<nav_msgs::msg::Path>("lookahead_collision_arc", 1);
@@ -243,7 +257,19 @@ geometry_msgs::msg::TwistStamped RegulatedPurePursuitController::computeVelocity
243257
auto transformed_plan = transformGlobalPlan(pose);
244258

245259
// Find look ahead distance and point on path and publish
246-
const double lookahead_dist = getLookAheadDistance(speed);
260+
double lookahead_dist = getLookAheadDistance(speed);
261+
262+
// Check for reverse driving
263+
if (allow_reversing_) {
264+
// Cusp check
265+
double dist_to_direction_change = findDirectionChange(pose);
266+
267+
// if the lookahead distance is further than the cusp, use the cusp distance instead
268+
if (dist_to_direction_change < lookahead_dist) {
269+
lookahead_dist = dist_to_direction_change;
270+
}
271+
}
272+
247273
auto carrot_pose = getLookAheadPoint(lookahead_dist, transformed_plan);
248274
carrot_pub_->publish(createCarrotMsg(carrot_pose));
249275

@@ -261,6 +287,12 @@ geometry_msgs::msg::TwistStamped RegulatedPurePursuitController::computeVelocity
261287
curvature = 2.0 * carrot_pose.pose.position.y / carrot_dist2;
262288
}
263289

290+
// Setting the velocity direction
291+
double sign = 1.0;
292+
if (allow_reversing_) {
293+
sign = carrot_pose.pose.position.x >= 0.0 ? 1.0 : -1.0;
294+
}
295+
264296
linear_vel = desired_linear_vel_;
265297

266298
// Make sure we're in compliance with basic constraints
@@ -274,7 +306,7 @@ geometry_msgs::msg::TwistStamped RegulatedPurePursuitController::computeVelocity
274306
applyConstraints(
275307
fabs(lookahead_dist - sqrt(carrot_dist2)),
276308
lookahead_dist, curvature, speed,
277-
costAtPose(pose.pose.position.x, pose.pose.position.y), linear_vel);
309+
costAtPose(pose.pose.position.x, pose.pose.position.y), linear_vel, sign);
278310

279311
// Apply curvature to angular velocity after constraining linear velocity
280312
angular_vel = linear_vel * curvature;
@@ -427,7 +459,7 @@ double RegulatedPurePursuitController::costAtPose(const double & x, const double
427459
void RegulatedPurePursuitController::applyConstraints(
428460
const double & dist_error, const double & lookahead_dist,
429461
const double & curvature, const geometry_msgs::msg::Twist & curr_speed,
430-
const double & pose_cost, double & linear_vel)
462+
const double & pose_cost, double & linear_vel, double & sign)
431463
{
432464
double curvature_vel = linear_vel;
433465
double cost_vel = linear_vel;
@@ -474,11 +506,13 @@ void RegulatedPurePursuitController::applyConstraints(
474506
}
475507

476508
// Limit linear velocities to be valid and kinematically feasible, v = v0 + a * dt
509+
linear_vel = sign * linear_vel;
477510
double & dt = control_duration_;
478511
const double max_feasible_linear_speed = curr_speed.linear.x + max_linear_accel_ * dt;
479512
const double min_feasible_linear_speed = curr_speed.linear.x - max_linear_decel_ * dt;
480513
linear_vel = std::clamp(linear_vel, min_feasible_linear_speed, max_feasible_linear_speed);
481-
linear_vel = std::clamp(linear_vel, 0.0, desired_linear_vel_);
514+
linear_vel = std::clamp(fabs(linear_vel), 0.0, desired_linear_vel_);
515+
linear_vel = sign * linear_vel;
482516
}
483517

484518
void RegulatedPurePursuitController::setPlan(const nav_msgs::msg::Path & path)
@@ -568,6 +602,34 @@ nav_msgs::msg::Path RegulatedPurePursuitController::transformGlobalPlan(
568602
return transformed_plan;
569603
}
570604

605+
double RegulatedPurePursuitController::findDirectionChange(
606+
const geometry_msgs::msg::PoseStamped & pose)
607+
{
608+
// Iterating through the global path to determine the position of the cusp
609+
for (unsigned int pose_id = 1; pose_id < global_plan_.poses.size(); ++pose_id) {
610+
// We have two vectors for the dot product OA and AB. Determining the vectors.
611+
double oa_x = global_plan_.poses[pose_id].pose.position.x -
612+
global_plan_.poses[pose_id - 1].pose.position.x;
613+
double oa_y = global_plan_.poses[pose_id].pose.position.y -
614+
global_plan_.poses[pose_id - 1].pose.position.y;
615+
double ab_x = global_plan_.poses[pose_id + 1].pose.position.x -
616+
global_plan_.poses[pose_id].pose.position.x;
617+
double ab_y = global_plan_.poses[pose_id + 1].pose.position.y -
618+
global_plan_.poses[pose_id].pose.position.y;
619+
620+
/* Checking for the existance of cusp, in the path, using the dot product
621+
and determine it's distance from the robot. If there is no cusp in the path,
622+
then just determine the distance to the goal location. */
623+
if ( (oa_x * ab_x) + (oa_y * ab_y) < 0.0) {
624+
auto x = global_plan_.poses[pose_id].pose.position.x - pose.pose.position.x;
625+
auto y = global_plan_.poses[pose_id].pose.position.y - pose.pose.position.y;
626+
return hypot(x, y); // returning the distance if there is a cusp
627+
}
628+
}
629+
630+
return std::numeric_limits<double>::max();
631+
}
632+
571633
bool RegulatedPurePursuitController::transformPose(
572634
const std::string frame,
573635
const geometry_msgs::msg::PoseStamped & in_pose,

nav2_regulated_pure_pursuit_controller/test/test_regulated_pp.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ class BasicAPIRPP : public nav2_regulated_pure_pursuit_controller::RegulatedPure
8585
void applyConstraintsWrapper(
8686
const double & dist_error, const double & lookahead_dist,
8787
const double & curvature, const geometry_msgs::msg::Twist & curr_speed,
88-
const double & pose_cost, double & linear_vel)
88+
const double & pose_cost, double & linear_vel, double & sign)
8989
{
9090
return applyConstraints(
9191
dist_error, lookahead_dist, curvature, curr_speed, pose_cost,
92-
linear_vel);
92+
linear_vel, sign);
9393
}
9494
};
9595

@@ -286,6 +286,7 @@ TEST(RegulatedPurePursuitTest, applyConstraints)
286286
geometry_msgs::msg::Twist curr_speed;
287287
double pose_cost = 0.0;
288288
double linear_vel = 0.0;
289+
double sign = 1.0;
289290

290291
// since costmaps here are bogus, we can't access them
291292
ctrl->resetVelocityApproachScaling();
@@ -294,23 +295,23 @@ TEST(RegulatedPurePursuitTest, applyConstraints)
294295
curr_speed.linear.x = 0.25;
295296
ctrl->applyConstraintsWrapper(
296297
dist_error, lookahead_dist, curvature, curr_speed, pose_cost,
297-
linear_vel);
298+
linear_vel, sign);
298299
EXPECT_EQ(linear_vel, 0.25); // min set speed
299300

300301
linear_vel = 1.0;
301302
curvature = 0.7407;
302303
curr_speed.linear.x = 0.5;
303304
ctrl->applyConstraintsWrapper(
304305
dist_error, lookahead_dist, curvature, curr_speed, pose_cost,
305-
linear_vel);
306+
linear_vel, sign);
306307
EXPECT_NEAR(linear_vel, 0.5, 0.01); // lower by curvature
307308

308309
linear_vel = 1.0;
309310
curvature = 1000.0;
310311
curr_speed.linear.x = 0.25;
311312
ctrl->applyConstraintsWrapper(
312313
dist_error, lookahead_dist, curvature, curr_speed, pose_cost,
313-
linear_vel);
314+
linear_vel, sign);
314315
EXPECT_NEAR(linear_vel, 0.25, 0.01); // min out by curvature
315316

316317

0 commit comments

Comments
 (0)