Skip to content

Commit dcc5db5

Browse files
Add ispathvalid maxcost (#4873)
* Add ispathvalid maxcost Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Fix problems as requested Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Set default as 253, Add considered unknown as obstacle Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Edit comment Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Update nav2_planner/src/planner_server.cpp Signed-off-by: Steve Macenski <stevenmacenski@gmail.com> --------- Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> Signed-off-by: Steve Macenski <stevenmacenski@gmail.com> Co-authored-by: Steve Macenski <stevenmacenski@gmail.com>
1 parent 4192372 commit dcc5db5

File tree

8 files changed

+56
-9
lines changed

8 files changed

+56
-9
lines changed

nav2_behavior_tree/include/nav2_behavior_tree/plugins/condition/is_path_valid_condition.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ class IsPathValidCondition : public BT::ConditionNode
6363
{
6464
return {
6565
BT::InputPort<nav_msgs::msg::Path>("path", "Path to Check"),
66-
BT::InputPort<std::chrono::milliseconds>("server_timeout")
66+
BT::InputPort<std::chrono::milliseconds>("server_timeout"),
67+
BT::InputPort<unsigned int>("max_cost", 253, "Maximum cost of the path"),
68+
BT::InputPort<bool>(
69+
"consider_unknown_as_obstacle", false,
70+
"Whether to consider unknown cost as obstacle")
6771
};
6872
}
6973

@@ -73,6 +77,8 @@ class IsPathValidCondition : public BT::ConditionNode
7377
// The timeout value while waiting for a response from the
7478
// is path valid service
7579
std::chrono::milliseconds server_timeout_;
80+
unsigned int max_cost_;
81+
bool consider_unknown_as_obstacle_;
7682
};
7783

7884
} // namespace nav2_behavior_tree

nav2_behavior_tree/nav2_tree_nodes.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
<input_port name="input_goals">A vector of goals to check if in collision</input_port>
108108
<input_port name="use_footprint">Whether to use the footprint cost or the point cost.</input_port>
109109
<input_port name="cost_threshold">The cost threshold above which a waypoint is considered in collision and should be removed.</input_port>
110+
<input_port name="consider_unknown_as_obstacle"> If unknown cost is considered valid </input_port>
110111
<output_port name="output_goals">A vector of goals containing only those that are not in collision.</output_port>
111112
</Action>
112113

@@ -283,6 +284,8 @@
283284
<Condition ID="IsPathValid">
284285
<input_port name="path"> Path to validate </input_port>
285286
<input_port name="server_timeout"> Server timeout </input_port>
287+
<input_port name="max_cost"> Maximum cost of the path </input_port>
288+
<input_port name="consider_unknown_as_obstacle"> If unknown cost is considered valid </input_port>
286289
</Condition>
287290

288291
<Condition ID="WouldAControllerRecoveryHelp">

nav2_behavior_tree/plugins/condition/is_path_valid_condition.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ namespace nav2_behavior_tree
2323
IsPathValidCondition::IsPathValidCondition(
2424
const std::string & condition_name,
2525
const BT::NodeConfiguration & conf)
26-
: BT::ConditionNode(condition_name, conf)
26+
: BT::ConditionNode(condition_name, conf),
27+
max_cost_(253), consider_unknown_as_obstacle_(false)
2728
{
2829
node_ = config().blackboard->get<rclcpp::Node::SharedPtr>("node");
2930
client_ = node_->create_client<nav2_msgs::srv::IsPathValid>("is_path_valid");
@@ -34,6 +35,8 @@ IsPathValidCondition::IsPathValidCondition(
3435
void IsPathValidCondition::initialize()
3536
{
3637
getInput<std::chrono::milliseconds>("server_timeout", server_timeout_);
38+
getInput<unsigned int>("max_cost", max_cost_);
39+
getInput<bool>("consider_unknown_as_obstacle", consider_unknown_as_obstacle_);
3740
}
3841

3942
BT::NodeStatus IsPathValidCondition::tick()
@@ -48,6 +51,8 @@ BT::NodeStatus IsPathValidCondition::tick()
4851
auto request = std::make_shared<nav2_msgs::srv::IsPathValid::Request>();
4952

5053
request->path = path;
54+
request->max_cost = max_cost_;
55+
request->consider_unknown_as_obstacle = consider_unknown_as_obstacle_;
5156
auto result = client_->async_send_request(request);
5257

5358
if (rclcpp::spin_until_future_complete(node_, result, server_timeout_) ==

nav2_msgs/srv/IsPathValid.srv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#Determine if the current path is still valid
22

33
nav_msgs/Path path
4+
uint8 max_cost 253
5+
bool consider_unknown_as_obstacle false
46
---
57
bool is_valid
68
int32[] invalid_pose_indices

nav2_planner/src/planner_server.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,13 +699,19 @@ void PlannerServer::isPathValid(
699699
position.x, position.y, theta, footprint));
700700
}
701701

702+
if (cost == nav2_costmap_2d::NO_INFORMATION && request->consider_unknown_as_obstacle) {
703+
cost = nav2_costmap_2d::LETHAL_OBSTACLE;
704+
} else if (cost == nav2_costmap_2d::NO_INFORMATION) {
705+
cost = nav2_costmap_2d::FREE_SPACE;
706+
}
707+
702708
if (use_radius &&
703-
(cost == nav2_costmap_2d::LETHAL_OBSTACLE ||
709+
(cost >= request->max_cost || cost == nav2_costmap_2d::LETHAL_OBSTACLE ||
704710
cost == nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE))
705711
{
706712
response->is_valid = false;
707713
break;
708-
} else if (cost == nav2_costmap_2d::LETHAL_OBSTACLE) {
714+
} else if (cost == nav2_costmap_2d::LETHAL_OBSTACLE || cost >= request->max_cost) {
709715
response->is_valid = false;
710716
break;
711717
}

nav2_system_tests/src/planning/planner_tester.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,12 +397,16 @@ TaskStatus PlannerTester::createPlan(
397397
return TaskStatus::FAILED;
398398
}
399399

400-
bool PlannerTester::isPathValid(nav_msgs::msg::Path & path)
400+
bool PlannerTester::isPathValid(
401+
nav_msgs::msg::Path & path, unsigned int max_cost,
402+
bool consider_unknown_as_obstacle)
401403
{
402404
planner_tester_->setCostmap(costmap_.get());
403405
// create a fake service request
404406
auto request = std::make_shared<nav2_msgs::srv::IsPathValid::Request>();
405407
request->path = path;
408+
request->max_cost = max_cost;
409+
request->consider_unknown_as_obstacle = consider_unknown_as_obstacle;
406410
auto result = path_valid_client_->async_send_request(request);
407411

408412
RCLCPP_INFO(this->get_logger(), "Waiting for service complete");

nav2_system_tests/src/planning/planner_tester.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ class PlannerTester : public rclcpp::Node
158158
const unsigned int number_tests,
159159
const float acceptable_fail_ratio);
160160

161-
bool isPathValid(nav_msgs::msg::Path & path);
161+
bool isPathValid(
162+
nav_msgs::msg::Path & path, unsigned int max_cost,
163+
bool consider_unknown_as_obstacle);
162164

163165
private:
164166
void setCostmap();

nav2_system_tests/src/planning/test_planner_is_path_valid.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ TEST(testIsPathValid, testIsPathValid)
3232
planner_tester->loadSimpleCostmap(TestCostmap::top_left_obstacle);
3333

3434
nav_msgs::msg::Path path;
35+
unsigned int max_cost = 253;
36+
bool consider_unknown_as_obstacle = false;
3537

3638
// empty path
37-
bool is_path_valid = planner_tester->isPathValid(path);
39+
bool is_path_valid = planner_tester->isPathValid(path, max_cost, consider_unknown_as_obstacle);
3840
EXPECT_FALSE(is_path_valid);
3941

4042
// invalid path
@@ -46,7 +48,7 @@ TEST(testIsPathValid, testIsPathValid)
4648
path.poses.push_back(pose);
4749
}
4850
}
49-
is_path_valid = planner_tester->isPathValid(path);
51+
is_path_valid = planner_tester->isPathValid(path, max_cost, consider_unknown_as_obstacle);
5052
EXPECT_FALSE(is_path_valid);
5153

5254
// valid path
@@ -57,8 +59,25 @@ TEST(testIsPathValid, testIsPathValid)
5759
pose.pose.position.y = i;
5860
path.poses.push_back(pose);
5961
}
60-
is_path_valid = planner_tester->isPathValid(path);
62+
is_path_valid = planner_tester->isPathValid(path, max_cost, consider_unknown_as_obstacle);
6163
EXPECT_TRUE(is_path_valid);
64+
65+
// valid path, but contains NO_INFORMATION(255)
66+
path.poses.clear();
67+
consider_unknown_as_obstacle = true;
68+
for (float i = 0; i < 10; i += 1.0) {
69+
geometry_msgs::msg::PoseStamped pose;
70+
pose.pose.position.x = 1.0;
71+
pose.pose.position.y = i;
72+
path.poses.push_back(pose);
73+
}
74+
is_path_valid = planner_tester->isPathValid(path, max_cost, consider_unknown_as_obstacle);
75+
EXPECT_FALSE(is_path_valid);
76+
77+
// valid path but higher than max cost
78+
max_cost = 0;
79+
is_path_valid = planner_tester->isPathValid(path, max_cost, consider_unknown_as_obstacle);
80+
EXPECT_FALSE(is_path_valid);
6281
}
6382

6483
int main(int argc, char ** argv)

0 commit comments

Comments
 (0)