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

Bound closest pose by costmap and turnaround point #2812

Merged
merged 54 commits into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
43c0f49
created integrated distance util
sathak93 Jan 24, 2022
602df8e
chng transform begin , end and always limit lp pt
sathak93 Jan 24, 2022
9df341c
chg trnsfm begin end and use euclidean distance
sathak93 Jan 24, 2022
3ad7986
linting fix
sathak93 Jan 24, 2022
132d085
linting fix
sathak93 Jan 24, 2022
d0c80e7
limit trnsfm to cusp
sathak93 Jan 25, 2022
106e10f
Merge branch 'main' of https://github.com/sathak93/navigation2 into p…
sathak93 Jan 27, 2022
a63bf16
remove print
sathak93 Jan 27, 2022
5f3baa6
linting fix
sathak93 Jan 27, 2022
3674943
lint fix
sathak93 Jan 28, 2022
9487dbb
hypot
sathak93 Jan 29, 2022
4a9f473
Merge pull request #1 from sathak93/path_segment_pr
Aposhian Feb 8, 2022
6e5c45b
use direction change as upper bound for closest pose
Aposhian Feb 8, 2022
0d5ff98
bound closest waypoint by direction change
Aposhian Feb 8, 2022
c3b744c
use max_transform_dist for closest_pose_upper_bound
Aposhian Feb 11, 2022
cc14180
remove first_element_beyond optimization todo
Aposhian Feb 15, 2022
2bcbfd9
added path_utils for test path generation
Aposhian Feb 17, 2022
175377e
initial test for path_utils
Aposhian Feb 17, 2022
6a1da0b
added full failing test for path_utils
Aposhian Feb 17, 2022
20c7edf
fixed path_utils segfault
Aposhian Feb 18, 2022
11d3ddd
properly initialize straight transform
Aposhian Feb 18, 2022
f179622
fixed right turn infinite loop
Aposhian Feb 18, 2022
bebf697
fixed path_utils transforms for half-turns
Aposhian Feb 18, 2022
4b788bd
all path_utils tests passing
Aposhian Feb 18, 2022
2901642
added half turn test for path_utils
Aposhian Feb 18, 2022
fbcfd33
remove unused dependencies from test_path_utils
Aposhian Feb 18, 2022
e925749
move path_utils classes into path_building_blocks namespace
Aposhian Feb 18, 2022
edf088f
use hypot for euclidean_distance
Aposhian Feb 23, 2022
77c88bf
rename findDirectionChange to findCusp
Aposhian Feb 23, 2022
6e4c6cd
use integrated distance for lookahead distance
Aposhian Feb 23, 2022
6d7f854
Revert "use integrated distance for lookahead distance"
Aposhian Feb 23, 2022
80eeb3c
parameterize transformation_begin bound
Aposhian Feb 23, 2022
4d32c0a
change default to a regular constant
Aposhian Feb 24, 2022
e8a1aa6
use std::hypot for x, y, z
Aposhian Feb 28, 2022
babb55f
initial failing test for transformGlobalPlan
Aposhian Mar 1, 2022
4de99e7
refactor transform global plan into separate test fixture
Aposhian Mar 1, 2022
279682b
make TransformGlobalPlan test fixture, and fix transforms
Aposhian Mar 1, 2022
842d4e1
no_pruning_on_large_costmap test passing
Aposhian Mar 1, 2022
8803c3d
added another transformGlobalPlan test
Aposhian Mar 1, 2022
9f8bb38
added a test for all poses outside of costmap
Aposhian Mar 1, 2022
74517ef
added good shortcut test for transformGlobalPlan
Aposhian Mar 1, 2022
598e140
added more tests for rpp costmap pruning
Aposhian Mar 2, 2022
0ed294f
cpplint
Aposhian Mar 2, 2022
bd00378
remove unused rclcpp::init and rclcpp::shutdown
Aposhian Mar 2, 2022
ca8c7b7
change default max_distance_between_iterations to max_costmap_extent
Aposhian Mar 2, 2022
4ec587b
rename max_distance_between_iterations to max_robot_pose_search_dist
Aposhian Mar 11, 2022
0c597b9
increase default dwb prune distance
Aposhian Mar 11, 2022
e2ce471
add initial docs for max_robot_pose_search_dist to README
Aposhian Mar 11, 2022
cd3ee1c
add note about when to set max_robot_pose_search_dist
Aposhian Mar 11, 2022
842c66e
rename first_element_beyond to first_after_integrated_distance
Aposhian Mar 11, 2022
c614119
renamed findCusp to findVelocitySignChange
Aposhian Mar 14, 2022
a8ded84
move path_utils to RPP tests
Aposhian Mar 14, 2022
4dae993
only check velocity sign change when reversing is enabled
Aposhian Mar 14, 2022
88f2cc6
do not check cusp for dwb transformed plan end
Aposhian Mar 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 35 additions & 29 deletions nav2_dwb_controller/dwb_core/src/dwb_local_planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@
#include "nav_2d_utils/conversions.hpp"
#include "nav_2d_utils/parameters.hpp"
#include "nav_2d_utils/tf_help.hpp"
#include "nav2_util/geometry_utils.hpp"
#include "nav2_util/lifecycle_node.hpp"
#include "nav2_util/node_utils.hpp"
#include "pluginlib/class_list_macros.hpp"
#include "nav_msgs/msg/path.hpp"
#include "geometry_msgs/msg/twist_stamped.hpp"

using nav2_util::declare_parameter_if_not_declared;
using nav2_util::geometry_utils::euclidean_distance;

namespace dwb_core
{
Expand Down Expand Up @@ -434,17 +436,6 @@ DWBLocalPlanner::scoreTrajectory(
return score;
}

double
getSquareDistance(
const geometry_msgs::msg::Pose2D & pose_a,
const geometry_msgs::msg::Pose2D & pose_b)
{
double x_diff = pose_a.x - pose_b.x;
double y_diff = pose_a.y - pose_b.y;

return x_diff * x_diff + y_diff * y_diff;
}

nav_2d_msgs::msg::Path2D
DWBLocalPlanner::transformGlobalPlan(
const nav_2d_msgs::msg::Pose2DStamped & pose)
Expand All @@ -467,47 +458,62 @@ DWBLocalPlanner::transformGlobalPlan(
nav2_costmap_2d::Costmap2D * costmap = costmap_ros_->getCostmap();
double dist_threshold = std::max(costmap->getSizeInCellsX(), costmap->getSizeInCellsY()) *
costmap->getResolution() / 2.0;
double sq_dist_threshold = dist_threshold * dist_threshold;


// If prune_plan is enabled (it is by default) then we want to restrict the
// plan to distances within that range as well.
double sq_prune_dist = prune_distance_ * prune_distance_;
double prune_dist = prune_distance_;

// Set the maximum distance we'll include points before getting to the part
// of the path where the robot is located (the start of the plan). Basically,
// these are the points the robot has already passed.
double sq_transform_start_threshold;
double transform_start_threshold;
if (prune_plan_) {
sq_transform_start_threshold = std::min(sq_dist_threshold, sq_prune_dist);
transform_start_threshold = std::min(dist_threshold, prune_dist);
} else {
sq_transform_start_threshold = sq_dist_threshold;
transform_start_threshold = dist_threshold;
}

// Set the maximum distance we'll include points after the part of the part of
// the plan near the robot (the end of the plan). This determines the amount
// of the plan passed on to the critics
double sq_transform_end_threshold;
double transform_end_threshold;
if (shorten_transformed_plan_) {
sq_transform_end_threshold = std::min(sq_dist_threshold, sq_prune_dist);
transform_end_threshold = std::min(dist_threshold, prune_dist);
} else {
sq_transform_end_threshold = sq_dist_threshold;
transform_end_threshold = dist_threshold;
}

// Find the first pose in the plan that's less than sq_transform_start_threshold
// Find the first pose in the global plan that's further than prune distance
// from the robot using integrated distance
auto prune_point = nav2_util::geometry_utils::first_element_beyond(
global_plan_.poses.begin(), global_plan_.poses.end(), prune_dist);
SteveMacenski marked this conversation as resolved.
Show resolved Hide resolved

// Find the first pose in the plan (upto prune_point) that's less than transform_start_threshold
// from the robot.
auto transformation_begin = std::find_if(
begin(global_plan_.poses), end(global_plan_.poses),
begin(global_plan_.poses), prune_point,
[&](const auto & global_plan_pose) {
return getSquareDistance(robot_pose.pose, global_plan_pose) < sq_transform_start_threshold;
return euclidean_distance(robot_pose.pose, global_plan_pose) < transform_start_threshold;
});

// Find the first pose in the end of the plan that's further than sq_transform_end_threshold
// from the robot
auto transformation_end = std::find_if(
transformation_begin, end(global_plan_.poses),
[&](const auto & global_plan_pose) {
return getSquareDistance(robot_pose.pose, global_plan_pose) > sq_transform_end_threshold;
});
// Find the first pose in the end of the plan that's further than transform_end_threshold
// from the robot using integrated distance
auto transformation_end =
nav2_util::geometry_utils::first_element_beyond(
transformation_begin, global_plan_.poses.end(), transform_end_threshold);

for (auto it = transformation_begin + 1; it != transformation_end - 1; ++it) {
SteveMacenski marked this conversation as resolved.
Show resolved Hide resolved
double oa_x = it->x - (it - 1 )->x;
double oa_y = it->y - (it - 1)->y;
double ab_x = (it + 1)->x - it->x;
double ab_y = (it + 1)->y - it->y;

if ( (oa_x * ab_x) + (oa_y * ab_y) < 0.0) {
transformation_end = it;
break;
}
}

// Transform the near part of the global plan into the robot's frame of reference.
nav_2d_msgs::msg::Path2D transformed_plan;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ class RegulatedPurePursuitController : public nav2_core::Controller
* @param pose pose to transform
* @return Path in new frame
*/
nav_msgs::msg::Path transformGlobalPlan(const geometry_msgs::msg::PoseStamped & pose);
nav_msgs::msg::Path transformGlobalPlan(
const geometry_msgs::msg::PoseStamped & pose,
double dist_to_direction_change);

/**
* @brief Transform a pose to another frame.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,21 +261,17 @@ geometry_msgs::msg::TwistStamped RegulatedPurePursuitController::computeVelocity
goal_dist_tol_ = pose_tolerance.position.x;
}

double dist_to_direction_change = findDirectionChange(pose);

// Transform path to robot base frame
auto transformed_plan = transformGlobalPlan(pose);
auto transformed_plan = transformGlobalPlan(pose, dist_to_direction_change);

// Find look ahead distance and point on path and publish
double lookahead_dist = getLookAheadDistance(speed);

// Check for reverse driving
SteveMacenski marked this conversation as resolved.
Show resolved Hide resolved
if (allow_reversing_) {
// Cusp check
double dist_to_direction_change = findDirectionChange(pose);

// if the lookahead distance is further than the cusp, use the cusp distance instead
if (dist_to_direction_change < lookahead_dist) {
lookahead_dist = dist_to_direction_change;
}
// if the lookahead distance is further than the cusp, use the cusp distance instead
if (dist_to_direction_change < lookahead_dist) {
lookahead_dist = dist_to_direction_change;
}

auto carrot_pose = getLookAheadPoint(lookahead_dist, transformed_plan);
Expand Down Expand Up @@ -589,7 +585,7 @@ void RegulatedPurePursuitController::setSpeedLimit(
}

nav_msgs::msg::Path RegulatedPurePursuitController::transformGlobalPlan(
const geometry_msgs::msg::PoseStamped & pose)
const geometry_msgs::msg::PoseStamped & pose, double dist_to_direction_change)
{
if (global_plan_.poses.empty()) {
throw nav2_core::PlannerException("Received plan with zero length");
Expand All @@ -604,22 +600,29 @@ nav_msgs::msg::Path RegulatedPurePursuitController::transformGlobalPlan(
// We'll discard points on the plan that are outside the local costmap
nav2_costmap_2d::Costmap2D * costmap = costmap_ros_->getCostmap();
const double max_costmap_dim = std::max(costmap->getSizeInCellsX(), costmap->getSizeInCellsY());
const double max_transform_dist = max_costmap_dim * costmap->getResolution() / 2.0;
const double max_costmap_extent = max_costmap_dim * costmap->getResolution() / 2.0;
SteveMacenski marked this conversation as resolved.
Show resolved Hide resolved
const double max_transform_dist = std::min(max_costmap_extent, dist_to_direction_change);

// TODO(aposhian): for long paths, this might get computationally expensive to do all the time,
SteveMacenski marked this conversation as resolved.
Show resolved Hide resolved
// and we should be able to cache the results of this distance accumulation
auto closest_pose_upper_bound =
nav2_util::geometry_utils::first_element_beyond(
global_plan_.poses.begin(), global_plan_.poses.end(), max_transform_dist);

// First find the closest pose on the path to the robot
// bounded by when the path turns around (if it does) so we don't get a pose from a later
// portion of the path
auto transformation_begin =
nav2_util::geometry_utils::min_by(
global_plan_.poses.begin(), global_plan_.poses.end(),
global_plan_.poses.begin(), closest_pose_upper_bound,
[&robot_pose](const geometry_msgs::msg::PoseStamped & ps) {
return euclidean_distance(robot_pose, ps);
});

// Find points definitely outside of the costmap so we won't transform them.
auto transformation_end = std::find_if(
transformation_begin, end(global_plan_.poses),
[&](const auto & global_plan_pose) {
return euclidean_distance(robot_pose, global_plan_pose) > max_transform_dist;
});
// Find points up to max_transform_dist so we only transform them.
auto transformation_end =
nav2_util::geometry_utils::first_element_beyond(
transformation_begin, global_plan_.poses.end(), max_transform_dist);

// Lambda to transform a PoseStamped from global frame to local
auto transformGlobalPoseToLocal = [&](const auto & global_plan_pose) {
Expand Down
36 changes: 36 additions & 0 deletions nav2_util/include/nav2_util/geometry_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "geometry_msgs/msg/pose.hpp"
#include "geometry_msgs/msg/pose_stamped.hpp"
#include "geometry_msgs/msg/pose2_d.hpp"
#include "geometry_msgs/msg/point.hpp"
#include "geometry_msgs/msg/quaternion.hpp"
#include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"
Expand Down Expand Up @@ -86,6 +87,22 @@ inline double euclidean_distance(
return euclidean_distance(pos1.pose, pos2.pose);
}

/**
* @brief Get the L2 distance between 2 geometry_msgs::Pose2D
* @param pos1 First pose
* @param pos1 Second pose
* @return double L2 distance
*/
inline double euclidean_distance(
const geometry_msgs::msg::Pose2D & pos1,
const geometry_msgs::msg::Pose2D & pos2)
{
double dx = pos1.x - pos2.x;
double dy = pos1.y - pos2.y;

return hypot(dx, dy);
}

/**
* Find element in iterator with the minimum calculated value
*/
Expand All @@ -107,6 +124,25 @@ inline Iter min_by(Iter begin, Iter end, Getter getCompareVal)
return lowest_it;
}

/**
* Find first element in iterator that is greater integrated distance than comparevalue
*/
template<typename Iter, typename Getter>
inline Iter first_element_beyond(Iter begin, Iter end, Getter getCompareVal)
SteveMacenski marked this conversation as resolved.
Show resolved Hide resolved
{
if (begin == end) {
return end;
}
Getter dist = 0.0;
for (Iter it = begin; it != end - 1; it++) {
dist += euclidean_distance(*it, *(it + 1));
if (dist > getCompareVal) {
return it + 1;
}
}
return end;
}

/**
* @brief Calculate the length of the provided path, starting at the provided index
* @param path Path containing the poses that are planned
Expand Down