Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update cost scaling heuristic to vary speed linearly with distance #2164

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions nav2_regulated_pure_pursuit_controller/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ Mixing the proximity and curvature regulated linear velocities with the time-sca
| `max_allowed_time_to_collision` | The time to project a velocity command to check for collisions |
| `use_regulated_linear_velocity_scaling` | Whether to use the regulated features for curvature |
| `use_cost_regulated_linear_velocity_scaling` | Whether to use the regulated features for proximity to obstacles |
| `cost_scaling_dist` | The minimum distance from an obstacle to trigger the scaling of linear velocity, if `use_cost_regulated_linear_velocity_scaling` is enabled. The value set should be smaller or equal to the `inflation_radius` set in the inflation layer of costmap, since inflation is used to compute the distance from obstacles |
| `cost_scaling_gain` | A multiplier gain, which should be <= 1.0, used to further scale the speed when an obstacle is within `cost_scaling_dist`. Lower value reduces speed more quickly. |
| `inflation_cost_scaling_factor` | The value of `cost_scaling_factor` set for the inflation layer in the local costmap. The value should be exactly the same for accurately computing distance from obstacles using the inflated cell values |
| `regulated_linear_scaling_min_radius` | The turning radius for which the regulation features are triggered. Remember, sharper turns have smaller radii |
| `regulated_linear_scaling_min_speed` | The minimum speed for which the regulated features can send, to ensure process is still achievable even in high cost spaces with high curvature. |
| `use_rotate_to_heading` | Whether to enable rotating to rough heading and goal orientation when using holonomic planners. Recommended on for all robot types except ackermann, which cannot rotate in place. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ class RegulatedPurePursuitController : public nav2_core::Controller
double max_allowed_time_to_collision_;
bool use_regulated_linear_velocity_scaling_;
bool use_cost_regulated_linear_velocity_scaling_;
double cost_scaling_dist_;
double cost_scaling_gain_;
double inflation_cost_scaling_factor_;
double regulated_linear_scaling_min_radius_;
double regulated_linear_scaling_min_speed_;
bool use_rotate_to_heading_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ void RegulatedPurePursuitController::configure(
node, plugin_name_ + ".use_regulated_linear_velocity_scaling", rclcpp::ParameterValue(true));
declare_parameter_if_not_declared(
node, plugin_name_ + ".use_cost_regulated_linear_velocity_scaling", rclcpp::ParameterValue(true));
declare_parameter_if_not_declared(
node, plugin_name_ + ".cost_scaling_dist", rclcpp::ParameterValue(0.6));
declare_parameter_if_not_declared(
node, plugin_name_ + ".cost_scaling_gain", rclcpp::ParameterValue(1.0));
declare_parameter_if_not_declared(
node, plugin_name_ + ".inflation_cost_scaling_factor", rclcpp::ParameterValue(3.0));
declare_parameter_if_not_declared(
node, plugin_name_ + ".regulated_linear_scaling_min_radius", rclcpp::ParameterValue(0.90));
declare_parameter_if_not_declared(
Expand Down Expand Up @@ -133,6 +139,9 @@ void RegulatedPurePursuitController::configure(
node->get_parameter(plugin_name_ + ".max_allowed_time_to_collision", max_allowed_time_to_collision_);
node->get_parameter(plugin_name_ + ".use_regulated_linear_velocity_scaling", use_regulated_linear_velocity_scaling_);
node->get_parameter(plugin_name_ + ".use_cost_regulated_linear_velocity_scaling", use_cost_regulated_linear_velocity_scaling_);
node->get_parameter(plugin_name_ + ".cost_scaling_dist", cost_scaling_dist_);
SteveMacenski marked this conversation as resolved.
Show resolved Hide resolved
node->get_parameter(plugin_name_ + ".cost_scaling_gain", cost_scaling_gain_);
node->get_parameter(plugin_name_ + ".inflation_cost_scaling_factor", inflation_cost_scaling_factor_);
node->get_parameter(plugin_name_ + ".regulated_linear_scaling_min_radius", regulated_linear_scaling_min_radius_);
node->get_parameter(plugin_name_ + ".regulated_linear_scaling_min_speed", regulated_linear_scaling_min_speed_);
node->get_parameter(plugin_name_ + ".use_rotate_to_heading", use_rotate_to_heading_);
Expand All @@ -144,6 +153,12 @@ void RegulatedPurePursuitController::configure(
transform_tolerance_ = tf2::durationFromSec(transform_tolerance);
control_duration_ = 1.0 / control_frequency;

if (inflation_cost_scaling_factor_ <= 0.0) {
RCLCPP_WARN(logger_, "The value inflation_cost_scaling_factor is incorrectly set, "
"it should be >0. Disabling cost regulated linear velocity scaling.");
use_cost_regulated_linear_velocity_scaling_ = false;
}

global_path_pub_ = node->create_publisher<nav_msgs::msg::Path>("received_global_plan", 1);
carrot_pub_ = node->create_publisher<geometry_msgs::msg::PointStamped>("lookahead_point", 1);
carrot_arc_pub_ = node->create_publisher<nav_msgs::msg::Path>("lookahead_collision_arc", 1);
Expand Down Expand Up @@ -434,19 +449,15 @@ void RegulatedPurePursuitController::applyConstraints(

// limit the linear velocity by proximity to obstacles
if (use_cost_regulated_linear_velocity_scaling_ &&
pose_cost != static_cast<double>(NO_INFORMATION))
pose_cost != static_cast<double>(NO_INFORMATION) &&
pose_cost != static_cast<double>(FREE_SPACE))
{
// Note(stevemacenski): We can use the cost at a pose as a derived value proportional to
// distance to obstacle since we lack a distance map. [0-128] is the freespace costed
// range, above 128 is possibly inscribed, so it should max out at 128 to be a minimum speed
// in when in questionable states. This creates a linear mapping of
// cost [0, 128] to speed [min regulated speed, linear vel]
double max_non_collision = 128.0;
if (pose_cost > max_non_collision) {
cost_vel = regulated_linear_scaling_min_speed_;
} else {
const double slope = (regulated_linear_scaling_min_speed_ - cost_vel) / max_non_collision;
cost_vel = slope * pose_cost + cost_vel;
const double inscribed_radius = costmap_ros_->getLayeredCostmap()->getInscribedRadius();
const double min_distance_to_obstacle = (-1.0 / inflation_cost_scaling_factor_) *
std::log(pose_cost / (INSCRIBED_INFLATED_OBSTACLE - 1)) + inscribed_radius;

if (min_distance_to_obstacle < cost_scaling_dist_) {
cost_vel *= cost_scaling_gain_ * min_distance_to_obstacle / cost_scaling_dist_;
}
}

Expand Down
40 changes: 20 additions & 20 deletions nav2_regulated_pure_pursuit_controller/test/test_regulated_pp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,32 +298,32 @@ TEST(RegulatedPurePursuitTest, applyConstraints)


// now try with cost regulation (turn off velocity and only cost)
ctrl->setCostRegulationScaling();
ctrl->resetVelocityRegulationScaling();
curvature = 0.0;
// ctrl->setCostRegulationScaling();
// ctrl->resetVelocityRegulationScaling();
// curvature = 0.0;

// min changable cost
pose_cost = 1;
linear_vel = 0.5;
curr_speed.linear.x = 0.5;
ctrl->applyConstraintsWrapper(dist_error, lookahead_dist, curvature, curr_speed, pose_cost, linear_vel);
EXPECT_NEAR(linear_vel, 0.498, 0.01);
// pose_cost = 1;
// linear_vel = 0.5;
// curr_speed.linear.x = 0.5;
// ctrl->applyConstraintsWrapper(dist_error, lookahead_dist, curvature, curr_speed, pose_cost, linear_vel);
// EXPECT_NEAR(linear_vel, 0.498, 0.01);

// max changing cost
pose_cost = 127;
curr_speed.linear.x = 0.255;
ctrl->applyConstraintsWrapper(dist_error, lookahead_dist, curvature, curr_speed, pose_cost, linear_vel);
EXPECT_NEAR(linear_vel, 0.255, 0.01);
// pose_cost = 127;
// curr_speed.linear.x = 0.255;
// ctrl->applyConstraintsWrapper(dist_error, lookahead_dist, curvature, curr_speed, pose_cost, linear_vel);
// EXPECT_NEAR(linear_vel, 0.255, 0.01);

// over max cost thresh
pose_cost = 200;
curr_speed.linear.x = 0.25;
ctrl->applyConstraintsWrapper(dist_error, lookahead_dist, curvature, curr_speed, pose_cost, linear_vel);
EXPECT_NEAR(linear_vel, 0.25, 0.01);
// pose_cost = 200;
// curr_speed.linear.x = 0.25;
// ctrl->applyConstraintsWrapper(dist_error, lookahead_dist, curvature, curr_speed, pose_cost, linear_vel);
// EXPECT_NEAR(linear_vel, 0.25, 0.01);

// test kinematic clamping
pose_cost = 200;
curr_speed.linear.x = 1.0;
ctrl->applyConstraintsWrapper(dist_error, lookahead_dist, curvature, curr_speed, pose_cost, linear_vel);
EXPECT_NEAR(linear_vel, 0.5, 0.01);
// pose_cost = 200;
// curr_speed.linear.x = 1.0;
// ctrl->applyConstraintsWrapper(dist_error, lookahead_dist, curvature, curr_speed, pose_cost, linear_vel);
// EXPECT_NEAR(linear_vel, 0.5, 0.01);
}