-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Staticial replanning #3100
base: main
Are you sure you want to change the base?
Staticial replanning #3100
Changes from 8 commits
8cfe20f
beeb427
f697654
7a14c46
10445f1
146ca55
c1a499f
5108c97
827a0ba
8ba8848
b7a13d3
ef0102b
21d36bf
2672bd1
9e6be2e
5f2eede
9c08a05
6a5165b
e63eae1
02a8dab
84cd1d8
1dd5d27
d40dcd6
b15367f
35df8e6
252d844
e8047ce
ffa0061
ee06ded
5cba027
232d665
289a686
e1830c9
aab082e
c9bab4d
72b5348
42b5bc8
ca48a4d
6fdcfc1
d4886a7
676fe71
34524ed
11285ea
074e3e1
7a6b11d
344ac1c
2b34405
1022f02
7a18064
3360f18
12b45f5
79c73f6
c5e4d1b
78ed712
908a765
f424310
8ce0ead
72da017
7eeb91e
9cbaf1a
48ca6e1
278f896
5ae4b73
f896415
e853746
c6bd5c5
f2713f7
b45381d
1b24e28
810f076
83f8b4f
c1f837d
8df3c5d
92dd352
53a6af5
3727175
bd715a5
185b7af
81811e2
b908b53
b1922b6
a96301c
5fe3345
95fbd23
4b54dfd
5d85e3f
aeec74a
e7d4d98
9b74dd0
338e93e
a94fdc4
c8053e3
5161f7d
80bd879
607019c
d81cc62
ad5aa20
ae268d8
61a967c
6d325e3
9b4bdde
a13d642
95c951d
ab5dcd9
1f74b4d
94fde9e
cb391ed
1a5313a
c415c76
806bc68
6202f57
5c27a3e
7c88750
6143295
c119017
fe776fb
bd3afbc
03876ea
5e16d10
fe9519d
7f41234
6b02da4
e32431c
d50a2d1
6664b93
dad593f
444b506
5f08d1f
f3b3dc6
0903d22
acb0458
27adc55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
#Determine if the current path is still valid | ||
|
||
nav_msgs/Path path | ||
bool consider_cost_change | ||
--- | ||
bool is_valid | ||
int32[] invalid_pose_indices |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
#include <string> | ||
#include <vector> | ||
#include <utility> | ||
#include <numeric> | ||
|
||
#include "builtin_interfaces/msg/duration.hpp" | ||
#include "nav2_util/costmap.hpp" | ||
|
@@ -52,6 +53,12 @@ PlannerServer::PlannerServer(const rclcpp::NodeOptions & options) | |
declare_parameter("planner_plugins", default_ids_); | ||
declare_parameter("expected_planner_frequency", 1.0); | ||
|
||
nav2_util::declare_parameter_if_not_declared( | ||
this, "z_score", rclcpp::ParameterValue(2.55)); | ||
|
||
|
||
get_parameter("z_score", z_score_); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the parameter / variable name, it would be nice to have some more context to what this is used for. While it is a Z-score, that's not really telling a user why its there / where its used. Considering the use of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also parameter guide stuff :-) Though, I think this should be broken out into another object. It doesn't seem very natural to have this implementation in the planner_server itself - maybe a pluginable interface at some point in the future? But at least for now, needs to be in a |
||
|
||
get_parameter("planner_plugins", planner_ids_); | ||
if (planner_ids_ == default_ids_) { | ||
for (size_t i = 0; i < default_ids_.size(); ++i) { | ||
|
@@ -541,13 +548,15 @@ void PlannerServer::isPathValid( | |
return; | ||
} | ||
|
||
// Find the closest point to the robot to evaluate from | ||
// TODO add orientation element like `truncate_path_local_action` BT node for looping paths | ||
geometry_msgs::msg::PoseStamped current_pose; | ||
unsigned int closest_point_index = 0; | ||
if (costmap_ros_->getRobotPose(current_pose)) { | ||
float current_distance = std::numeric_limits<float>::max(); | ||
float closest_distance = current_distance; | ||
geometry_msgs::msg::Point current_point = current_pose.pose.position; | ||
for (unsigned int i = 0; i < request->path.poses.size(); ++i) { | ||
for (unsigned int i = 0; i != request->path.poses.size(); ++i) { | ||
geometry_msgs::msg::Point path_point = request->path.poses[i].pose.position; | ||
|
||
current_distance = nav2_util::geometry_utils::euclidean_distance( | ||
|
@@ -559,26 +568,68 @@ void PlannerServer::isPathValid( | |
closest_distance = current_distance; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* The lethal check starts at the closest point to avoid points that have already been passed | ||
* and may have become occupied | ||
*/ | ||
unsigned int mx = 0; | ||
unsigned int my = 0; | ||
for (unsigned int i = closest_point_index; i < request->path.poses.size(); ++i) { | ||
costmap_->worldToMap( | ||
request->path.poses[i].pose.position.x, | ||
request->path.poses[i].pose.position.y, mx, my); | ||
unsigned int cost = costmap_->getCost(mx, my); | ||
|
||
if (cost == nav2_costmap_2d::LETHAL_OBSTACLE || | ||
cost == nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE) | ||
{ | ||
response->is_valid = false; | ||
} | ||
// Checking path for collisions starting at the closest point to avoid those already passed | ||
std::vector<unsigned int> current_costs; | ||
current_costs.reserve(request->path.costs.size() - closest_point_index - 1); | ||
|
||
unsigned int mx = 0; | ||
unsigned int my = 0; | ||
for (unsigned int i = closest_point_index; i != request->path.poses.size(); ++i) { | ||
costmap_->worldToMap( | ||
request->path.poses[i].pose.position.x, | ||
request->path.poses[i].pose.position.y, mx, my); | ||
unsigned int cost = costmap_->getCost(mx, my); | ||
current_costs.push_back(cost); | ||
|
||
if (cost == nav2_costmap_2d::LETHAL_OBSTACLE || | ||
cost == nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE) | ||
{ | ||
response->is_valid = false; | ||
return; | ||
} | ||
} | ||
|
||
// Check using a statistical test if the cost changes are 'significant' enough | ||
// to warrant replanning, due to changes in cost within the environment, | ||
// when larger than the minimum sample size for the test | ||
if (!request->consider_cost_change || request->path.costs.size() < 30) { | ||
return; | ||
} | ||
|
||
std::vector<unsigned int> original_costs( | ||
request->path.costs.begin() + closest_point_index, request->path.costs.end()); | ||
|
||
float mean_orginal = 0; | ||
float mean_current = 0; | ||
for (unsigned int i = 0; i != original_costs.size(); ++i) { | ||
mean_orginal += static_cast<float>(original_costs[i]); | ||
mean_current += static_cast<float>(current_costs[i]); | ||
} | ||
mean_orginal /= static_cast<float>(original_costs.size()); | ||
mean_current /= static_cast<float>(current_costs.size()); | ||
|
||
float var_orginal = 0; | ||
float var_current = 0; | ||
for (unsigned int i = 0; i != original_costs.size(); ++i) { | ||
var_orginal += std::pow(static_cast<float>(original_costs[i]) - static_cast<float>(mean_orginal), 2); | ||
var_current += std::pow(static_cast<float>(current_costs[i]) - static_cast<float>(mean_current), 2); | ||
} | ||
var_orginal /= static_cast<float>(original_costs.size() - 1); | ||
var_current /= static_cast<float>(current_costs.size() - 1); | ||
|
||
// Conduct a two sample Z-test, with the null hypothesis is that both path cost samples | ||
// come from the same distribution (e.g. there is not a statistically significant change) | ||
// Thus, the difference in population mean is 0 and the sample sizes are the same | ||
float z = (mean_current - mean_orginal) / std::sqrt((var_current + var_orginal) / current_costs.size()); | ||
|
||
// TODO try single tail or tune strictness? Parameterize? | ||
// 1.65 95% single tail; 2.55 for 99% dual, 2.33 99% single; 90% 1.65 dual, 90% 1.2 single. | ||
if (z > z_score_) { // critical z score for 95% level | ||
RCLCPP_DEBUG_STREAM(get_logger(), "Z-test triggered new global plan. The z score was: " << z << "and the threshold was" << z_score_); | ||
response->is_valid = false; | ||
} | ||
} | ||
|
||
rcl_interfaces::msg::SetParametersResult | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add to groot XML for people using it to build trees to have the option exposed