Skip to content

Commit 8c3a643

Browse files
author
Kemal Bektas
committed
Add system tests for cancel
Signed-off-by: Kemal Bektas <kemal.bektas@node-robotics.com>
1 parent 868dd64 commit 8c3a643

File tree

6 files changed

+104
-2
lines changed

6 files changed

+104
-2
lines changed

nav2_system_tests/src/error_codes/error_code_param.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ planner_server:
154154
expected_planner_frequency: 20.0
155155
planner_plugins: [ "unknown", "tf_error", "start_outside_map", "goal_outside_map",
156156
"start_occupied", "goal_occupied", "timeout","no_valid_path",
157-
"no_viapoints_given" ]
157+
"no_viapoints_given", "cancelled" ]
158158
unknown:
159159
plugin: "nav2_system_tests::UnknownErrorPlanner"
160160
tf_error:
@@ -173,6 +173,8 @@ planner_server:
173173
plugin: "nav2_system_tests::NoValidPathErrorPlanner"
174174
no_viapoints_given:
175175
plugin: "nav2_system_tests::NoViapointsGivenErrorPlanner"
176+
cancelled:
177+
plugin: "nav2_system_tests::CancelledPlanner"
176178

177179
smoother_server:
178180
ros__parameters:

nav2_system_tests/src/error_codes/planner/planner_error_plugin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ PLUGINLIB_EXPORT_CLASS(nav2_system_tests::NoValidPathErrorPlanner, nav2_core::Gl
2424
PLUGINLIB_EXPORT_CLASS(nav2_system_tests::TimedOutErrorPlanner, nav2_core::GlobalPlanner)
2525
PLUGINLIB_EXPORT_CLASS(nav2_system_tests::TFErrorPlanner, nav2_core::GlobalPlanner)
2626
PLUGINLIB_EXPORT_CLASS(nav2_system_tests::NoViapointsGivenErrorPlanner, nav2_core::GlobalPlanner)
27+
PLUGINLIB_EXPORT_CLASS(nav2_system_tests::CancelledPlanner, nav2_core::GlobalPlanner)

nav2_system_tests/src/error_codes/planner/planner_error_plugin.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,26 @@ class NoViapointsGivenErrorPlanner : public UnknownErrorPlanner
147147
}
148148
};
149149

150+
class CancelledPlanner : public UnknownErrorPlanner
151+
{
152+
nav_msgs::msg::Path createPlan(
153+
const geometry_msgs::msg::PoseStamped &,
154+
const geometry_msgs::msg::PoseStamped &,
155+
std::function<bool()> cancel_checker) override
156+
{
157+
auto start_time = std::chrono::steady_clock::now();
158+
while (rclcpp::ok() &&
159+
std::chrono::steady_clock::now() - start_time < std::chrono::seconds(5))
160+
{
161+
if (cancel_checker()) {
162+
throw nav2_core::PlannerCancelled("Planner Cancelled");
163+
}
164+
rclcpp::sleep_for(std::chrono::milliseconds(100));
165+
}
166+
throw nav2_core::PlannerException("Cancel is not called in time.");
167+
}
168+
};
169+
150170
} // namespace nav2_system_tests
151171

152172

nav2_system_tests/src/error_codes/planner_plugins.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@
3939
base_class_type="nav2_core::GlobalPlanner">
4040
<description>This global planner produces a no via points exception.</description>
4141
</class>
42+
<class type="nav2_system_tests::CancelledPlanner"
43+
base_class_type="nav2_core::GlobalPlanner">
44+
<description>This global planner produces a cancelled exception.</description>
45+
</class>
4246
</library>

nav2_system_tests/src/error_codes/test_error_codes.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# limitations under the License.
1515

1616
import sys
17+
import threading
1718
import time
1819

1920
from geometry_msgs.msg import PoseStamped
@@ -23,7 +24,7 @@
2324
FollowPath,
2425
SmoothPath,
2526
)
26-
from nav2_simple_commander.robot_navigator import BasicNavigator
27+
from nav2_simple_commander.robot_navigator import BasicNavigator, TaskResult
2728
from nav_msgs.msg import Path
2829
import rclpy
2930

@@ -111,6 +112,17 @@ def main(argv=sys.argv[1:]):
111112
result.error_code == error_code
112113
), 'Compute path to pose error does not match'
113114

115+
def cancel_task():
116+
time.sleep(1)
117+
navigator.goal_handle.cancel_goal_async()
118+
119+
# Check compute path to pose cancel
120+
threading.Thread(target=cancel_task).start()
121+
result = navigator._getPathImpl(initial_pose, goal_pose, 'cancelled')
122+
assert (
123+
navigator.getResult() == TaskResult.CANCELED
124+
), 'Compute path to pose cancel failed'
125+
114126
# Check compute path through error codes
115127
goal_pose1 = goal_pose
116128
goal_poses = [goal_pose, goal_pose1]
@@ -133,6 +145,12 @@ def main(argv=sys.argv[1:]):
133145
assert (
134146
result.error_code == error_code
135147
), 'Compute path through pose error does not match'
148+
# Check compute path to pose cancel
149+
threading.Thread(target=cancel_task).start()
150+
result = navigator._getPathThroughPosesImpl(initial_pose, goal_poses, 'cancelled')
151+
assert (
152+
navigator.getResult() == TaskResult.CANCELED
153+
), 'Compute path through poses cancel failed'
136154

137155
# Check compute path to pose error codes
138156
pose = PoseStamped()

nav2_system_tests/src/planning/test_planner_plugins.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,36 @@ void testSmallPathValidityAndNoOrientation(std::string plugin, double length)
118118
obj.reset();
119119
}
120120

121+
void testCancel(std::string plugin)
122+
{
123+
auto obj = std::make_shared<nav2_system_tests::NavFnPlannerTester>();
124+
rclcpp_lifecycle::State state;
125+
obj->set_parameter(rclcpp::Parameter("GridBased.plugin", plugin));
126+
obj->declare_parameter("GridBased.terminal_checking_interval", rclcpp::ParameterValue(1));
127+
obj->onConfigure(state);
128+
129+
geometry_msgs::msg::PoseStamped start;
130+
geometry_msgs::msg::PoseStamped goal;
131+
132+
start.pose.position.x = 0.0;
133+
start.pose.position.y = 0.0;
134+
start.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(M_PI_2);
135+
start.header.frame_id = "map";
136+
137+
goal.pose.position.x = 0.5;
138+
goal.pose.position.y = 0.6;
139+
goal.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(-M_PI);
140+
goal.header.frame_id = "map";
141+
142+
auto always_cancelled = []() {return true;};
143+
144+
EXPECT_THROW(
145+
obj->getPlan(start, goal, "GridBased", always_cancelled),
146+
nav2_core::PlannerCancelled);
147+
// obj->onCleanup(state);
148+
obj.reset();
149+
}
150+
121151
TEST(testPluginMap, Failures)
122152
{
123153
auto obj = std::make_shared<nav2_system_tests::NavFnPlannerTester>();
@@ -147,6 +177,7 @@ TEST(testPluginMap, Failures)
147177
obj->onCleanup(state);
148178
}
149179

180+
150181
TEST(testPluginMap, Smac2dEqualStartGoal)
151182
{
152183
testSmallPathValidityAndOrientation("nav2_smac_planner/SmacPlanner2D", 0.0);
@@ -297,6 +328,32 @@ TEST(testPluginMap, ThetaStarAboveCostmapResolutionN)
297328
testSmallPathValidityAndNoOrientation("nav2_theta_star_planner/ThetaStarPlanner", 1.5);
298329
}
299330

331+
TEST(testPluginMap, NavFnCancel)
332+
{
333+
testCancel("nav2_navfn_planner/NavfnPlanner");
334+
}
335+
336+
TEST(testPluginMap, ThetaStarCancel)
337+
{
338+
testCancel("nav2_theta_star_planner/ThetaStarPlanner");
339+
}
340+
341+
TEST(testPluginMap, Smac2dCancel)
342+
{
343+
testCancel("nav2_smac_planner/SmacPlanner2D");
344+
}
345+
346+
TEST(testPluginMap, SmacLatticeCancel)
347+
{
348+
testCancel("nav2_smac_planner/SmacPlannerLattice");
349+
}
350+
351+
TEST(testPluginMap, SmacHybridAStarCancel)
352+
{
353+
testCancel("nav2_smac_planner/SmacPlannerHybrid");
354+
}
355+
356+
300357
int main(int argc, char ** argv)
301358
{
302359
::testing::InitGoogleTest(&argc, argv);

0 commit comments

Comments
 (0)