Skip to content

Commit 61e1e6c

Browse files
authored
test(mission_planner): add test of default_planner (autowarefoundation#9050)
Signed-off-by: kosuke55 <kosuke.tnp@gmail.com>
1 parent c2438fd commit 61e1e6c

File tree

1 file changed

+283
-16
lines changed

1 file changed

+283
-16
lines changed

planning/autoware_mission_planner/test/test_lanelet2_plugins_default_planner.cpp

+283-16
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,33 @@
1313
// limitations under the License.
1414

1515
#include <../src/lanelet2_plugins/default_planner.hpp>
16+
#include <ament_index_cpp/get_package_share_directory.hpp>
1617
#include <autoware/universe_utils/geometry/boost_geometry.hpp>
18+
#include <autoware/universe_utils/geometry/geometry.hpp>
1719
#include <autoware_test_utils/autoware_test_utils.hpp>
1820

1921
#include <boost/geometry/io/wkt/write.hpp>
2022

2123
#include <gtest/gtest.h>
2224
#include <lanelet2_core/Forward.h>
25+
#include <lanelet2_core/LaneletMap.h>
2326
#include <lanelet2_core/geometry/Polygon.h>
2427
#include <lanelet2_core/primitives/Lanelet.h>
2528
#include <lanelet2_core/primitives/LineString.h>
2629
#include <lanelet2_core/primitives/Point.h>
30+
#include <tf2/utils.h>
2731

28-
struct DefaultPlanner : protected autoware::mission_planner::lanelet2::DefaultPlanner
32+
using autoware::universe_utils::calcOffsetPose;
33+
using autoware::universe_utils::createQuaternionFromRPY;
34+
using autoware_planning_msgs::msg::LaneletRoute;
35+
using geometry_msgs::msg::Pose;
36+
using RoutePoints = std::vector<geometry_msgs::msg::Pose>;
37+
38+
// inherit DefaultPlanner to access protected methods and make wrapper to private methods
39+
struct DefaultPlanner : public autoware::mission_planner::lanelet2::DefaultPlanner
2940
{
30-
void set_front_offset(const double offset) { vehicle_info_.max_longitudinal_offset_m = offset; }
31-
void set_dummy_map() { route_handler_.setMap(autoware::test_utils::makeMapBinMsg()); }
41+
// todo(someone): create tests with various kinds of maps
42+
void set_default_test_map() { route_handler_.setMap(autoware::test_utils::makeMapBinMsg()); }
3243
[[nodiscard]] bool check_goal_inside_lanes(
3344
const lanelet::ConstLanelet & closest_lanelet_to_goal,
3445
const lanelet::ConstLanelets & path_lanelets,
@@ -37,15 +48,61 @@ struct DefaultPlanner : protected autoware::mission_planner::lanelet2::DefaultPl
3748
return check_goal_footprint_inside_lanes(
3849
closest_lanelet_to_goal, path_lanelets, goal_footprint);
3950
}
51+
bool is_goal_valid_wrapper(
52+
const geometry_msgs::msg::Pose & goal, const lanelet::ConstLanelets & path_lanelets)
53+
{
54+
return is_goal_valid(goal, path_lanelets);
55+
}
56+
57+
lanelet::ConstLanelets get_lanelets_from_ids(const std::vector<lanelet::Id> & ids)
58+
{
59+
const auto lanelet_map_ptr = route_handler_.getLaneletMapPtr();
60+
61+
lanelet::ConstLanelets lanelets;
62+
63+
for (const auto & id : ids) {
64+
lanelets.push_back(lanelet_map_ptr->laneletLayer.get(id));
65+
}
66+
return lanelets;
67+
}
68+
};
69+
70+
class DefaultPlannerTest : public ::testing::Test
71+
{
72+
protected:
73+
void SetUp() override
74+
{
75+
rclcpp::init(0, nullptr);
76+
77+
rclcpp::NodeOptions options;
78+
79+
const auto autoware_test_utils_dir =
80+
ament_index_cpp::get_package_share_directory("autoware_test_utils");
81+
const auto mission_planner_dir =
82+
ament_index_cpp::get_package_share_directory("autoware_mission_planner");
83+
options.arguments(
84+
{"--ros-args", "--params-file",
85+
autoware_test_utils_dir + "/config/test_vehicle_info.param.yaml", "--params-file",
86+
mission_planner_dir + "/config/mission_planner.param.yaml"});
87+
// NOTE: vehicle width and length set by test_vehicle_info.param.yaml are as follows
88+
// vehicle_width: 1.83, vehicle_length: 4.77
89+
90+
node_ = std::make_shared<rclcpp::Node>("test_node", options);
91+
planner_.initialize(node_.get());
92+
}
93+
94+
~DefaultPlannerTest() override { rclcpp::shutdown(); }
95+
96+
std::shared_ptr<rclcpp::Node> node_;
97+
98+
DefaultPlanner planner_;
4099
};
41100

42-
TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
101+
TEST_F(DefaultPlannerTest, checkGoalInsideLane)
43102
{
44103
// Test with dummy map such that only the lanelets provided as inputs are used for the ego lane
45-
DefaultPlanner planner;
46-
planner.set_dummy_map();
104+
planner_.set_default_test_map();
47105
// vehicle max longitudinal offset is used to retrieve additional lanelets from the map
48-
planner.set_front_offset(0.0);
49106
lanelet::LineString3d left_bound;
50107
lanelet::LineString3d right_bound;
51108
left_bound.push_back(lanelet::Point3d{lanelet::InvalId, -1, -1});
@@ -63,7 +120,7 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
63120
goal_footprint.outer().emplace_back(0.5, 0.5);
64121
goal_footprint.outer().emplace_back(0.5, 0);
65122
goal_footprint.outer().emplace_back(0, 0);
66-
EXPECT_TRUE(planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet}, goal_footprint));
123+
EXPECT_TRUE(planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet}, goal_footprint));
67124

68125
// the footprint touches the border of the lanelet
69126
goal_footprint.clear();
@@ -72,7 +129,7 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
72129
goal_footprint.outer().emplace_back(1, 1);
73130
goal_footprint.outer().emplace_back(1, 0);
74131
goal_footprint.outer().emplace_back(0, 0);
75-
EXPECT_TRUE(planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet}, goal_footprint));
132+
EXPECT_TRUE(planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet}, goal_footprint));
76133

77134
// add lanelets such that the footprint touches the linestring shared by the combined lanelets
78135
lanelet::LineString3d next_left_bound;
@@ -83,7 +140,7 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
83140
next_right_bound.push_back(lanelet::Point3d{lanelet::InvalId, 2, 1});
84141
lanelet::ConstLanelet next_lanelet{lanelet::InvalId, next_left_bound, next_right_bound};
85142
EXPECT_TRUE(
86-
planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
143+
planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
87144

88145
// the footprint is inside the other lanelet
89146
goal_footprint.clear();
@@ -93,7 +150,7 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
93150
goal_footprint.outer().emplace_back(1.6, -0.5);
94151
goal_footprint.outer().emplace_back(1.1, -0.5);
95152
EXPECT_TRUE(
96-
planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
153+
planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
97154

98155
// the footprint is completely outside of the lanelets
99156
goal_footprint.clear();
@@ -103,7 +160,7 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
103160
goal_footprint.outer().emplace_back(1.6, 1.5);
104161
goal_footprint.outer().emplace_back(1.1, 1.5);
105162
EXPECT_FALSE(
106-
planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
163+
planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
107164

108165
// the footprint is outside of the lanelets but touches an edge
109166
goal_footprint.clear();
@@ -113,7 +170,7 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
113170
goal_footprint.outer().emplace_back(1.6, 1.0);
114171
goal_footprint.outer().emplace_back(1.1, 1.0);
115172
EXPECT_FALSE(
116-
planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
173+
planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
117174

118175
// the footprint is outside of the lanelets but share a point
119176
goal_footprint.clear();
@@ -123,7 +180,7 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
123180
goal_footprint.outer().emplace_back(3.0, 1.0);
124181
goal_footprint.outer().emplace_back(2.0, 1.0);
125182
EXPECT_FALSE(
126-
planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
183+
planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
127184

128185
// ego footprint that overlaps both lanelets
129186
goal_footprint.clear();
@@ -133,7 +190,7 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
133190
goal_footprint.outer().emplace_back(1.5, -0.5);
134191
goal_footprint.outer().emplace_back(-0.5, -0.5);
135192
EXPECT_TRUE(
136-
planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
193+
planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
137194

138195
// ego footprint that goes further than the next lanelet
139196
goal_footprint.clear();
@@ -143,5 +200,215 @@ TEST(TestLanelet2PluginsDefaultPlanner, checkGoalInsideLane)
143200
goal_footprint.outer().emplace_back(2.5, -0.5);
144201
goal_footprint.outer().emplace_back(-0.5, -0.5);
145202
EXPECT_FALSE(
146-
planner.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
203+
planner_.check_goal_inside_lanes(goal_lanelet, {goal_lanelet, next_lanelet}, goal_footprint));
204+
}
205+
206+
TEST_F(DefaultPlannerTest, isValidGoal)
207+
{
208+
planner_.set_default_test_map();
209+
210+
std::vector<lanelet::Id> path_lanelet_ids = {9102, 9540, 9546, 9178, 52, 124};
211+
const auto path_lanelets = planner_.get_lanelets_from_ids(path_lanelet_ids);
212+
213+
const double yaw_threshold = 0.872665; // 50 degrees
214+
215+
/**
216+
* 1) goal pose within the lanelet
217+
*/
218+
// goal pose within the lanelet
219+
Pose goal_pose;
220+
goal_pose.position.x = 3810.24951171875;
221+
goal_pose.position.y = 73769.2578125;
222+
goal_pose.position.z = 0.0;
223+
goal_pose.orientation.x = 0.0;
224+
goal_pose.orientation.y = 0.0;
225+
goal_pose.orientation.z = 0.23908402523702438;
226+
goal_pose.orientation.w = 0.9709988820160721;
227+
const double yaw = tf2::getYaw(goal_pose.orientation);
228+
EXPECT_TRUE(planner_.is_goal_valid_wrapper(goal_pose, path_lanelets));
229+
230+
// move 1m to the right to make the goal outside of the lane
231+
Pose right_offset_goal_pose = calcOffsetPose(goal_pose, 0.0, 1.0, 0.0);
232+
EXPECT_FALSE(planner_.is_goal_valid_wrapper(right_offset_goal_pose, path_lanelets));
233+
234+
// move 1m to the left to make the goal outside of the lane
235+
Pose left_offset_goal_pose = calcOffsetPose(goal_pose, 0.0, -1.0, 0.0);
236+
EXPECT_FALSE(planner_.is_goal_valid_wrapper(left_offset_goal_pose, path_lanelets));
237+
238+
// rotate to the right
239+
Pose right_rotated_goal_pose = goal_pose;
240+
right_rotated_goal_pose.orientation = createQuaternionFromRPY(0.0, 0.0, yaw + yaw_threshold);
241+
EXPECT_FALSE(planner_.is_goal_valid_wrapper(right_rotated_goal_pose, path_lanelets));
242+
243+
// rotate to the left
244+
Pose left_rotated_goal_pose = goal_pose;
245+
left_rotated_goal_pose.orientation = createQuaternionFromRPY(0.0, 0.0, yaw - yaw_threshold);
246+
EXPECT_FALSE(planner_.is_goal_valid_wrapper(left_rotated_goal_pose, path_lanelets));
247+
248+
/**
249+
* 2) goal pose on the road shoulder
250+
*/
251+
std::vector<lanelet::Id> path_lanelet_to_road_shoulder_ids = {9102, 9540, 9546};
252+
lanelet::Id target_road_shoulder_id = 10304; // left road shoulder of 9546
253+
const auto path_lanelets_to_road_shoulder =
254+
planner_.get_lanelets_from_ids(path_lanelet_to_road_shoulder_ids);
255+
const auto target_road_shoulder =
256+
planner_.get_lanelets_from_ids({target_road_shoulder_id}).front();
257+
258+
Pose goal_pose_on_road_shoulder;
259+
goal_pose_on_road_shoulder.position.x = 3742.3825513144147;
260+
goal_pose_on_road_shoulder.position.y = 73737.75783925217;
261+
goal_pose_on_road_shoulder.position.z = 0.0;
262+
goal_pose_on_road_shoulder.orientation.x = 0.0;
263+
goal_pose_on_road_shoulder.orientation.y = 0.0;
264+
goal_pose_on_road_shoulder.orientation.z = 0.23721495449671745;
265+
goal_pose_on_road_shoulder.orientation.w = 0.9714571865826721;
266+
EXPECT_TRUE(
267+
planner_.is_goal_valid_wrapper(goal_pose_on_road_shoulder, path_lanelets_to_road_shoulder));
268+
269+
// put goal on the left bound of the road shoulder
270+
// if the goal is on the road shoulder, the footprint can be outside of the lane, and only the
271+
// angle is checked
272+
const auto left_bound = target_road_shoulder.leftBound();
273+
Pose goal_pose_on_road_shoulder_left_bound = goal_pose_on_road_shoulder;
274+
goal_pose_on_road_shoulder_left_bound.position.x = left_bound.front().x();
275+
goal_pose_on_road_shoulder_left_bound.position.y = left_bound.front().y();
276+
EXPECT_TRUE(planner_.is_goal_valid_wrapper(
277+
goal_pose_on_road_shoulder_left_bound, path_lanelets_to_road_shoulder));
278+
279+
// move goal pose outside of the road shoulder
280+
Pose goal_pose_outside_road_shoulder =
281+
calcOffsetPose(goal_pose_on_road_shoulder_left_bound, 0.0, 0.1, 0.0);
282+
EXPECT_FALSE(planner_.is_goal_valid_wrapper(
283+
goal_pose_outside_road_shoulder, path_lanelets_to_road_shoulder));
284+
285+
// rotate goal to the right
286+
Pose right_rotated_goal_pose_on_road_shoulder = goal_pose_on_road_shoulder;
287+
right_rotated_goal_pose_on_road_shoulder.orientation =
288+
createQuaternionFromRPY(0.0, 0.0, yaw + yaw_threshold);
289+
EXPECT_FALSE(planner_.is_goal_valid_wrapper(
290+
right_rotated_goal_pose_on_road_shoulder, path_lanelets_to_road_shoulder));
291+
292+
/**
293+
* todo(someone): add more test for parking area
294+
*/
295+
}
296+
297+
TEST_F(DefaultPlannerTest, plan)
298+
{
299+
planner_.set_default_test_map();
300+
301+
/**
302+
* 1) goal pose within the lanelet
303+
*/
304+
RoutePoints route_points;
305+
Pose start_pose;
306+
start_pose.position.x = 3717.239501953125;
307+
start_pose.position.y = 73720.84375;
308+
start_pose.position.z = 0.0;
309+
start_pose.orientation.x = 0.00012620055018808463;
310+
start_pose.orientation.y = -0.0005077247816171834;
311+
start_pose.orientation.z = 0.2412209576008544;
312+
313+
Pose goal_pose;
314+
goal_pose.position.x = 3810.24951171875;
315+
goal_pose.position.y = 73769.2578125;
316+
goal_pose.position.z = 0.0;
317+
goal_pose.orientation.x = 0.0;
318+
goal_pose.orientation.y = 0.0;
319+
goal_pose.orientation.z = 0.23908402523702438;
320+
goal_pose.orientation.w = 0.9709988820160721;
321+
322+
route_points.push_back(start_pose);
323+
route_points.push_back(goal_pose);
324+
const auto route = planner_.plan(route_points);
325+
326+
EXPECT_EQ(route.start_pose.position.x, start_pose.position.x);
327+
EXPECT_EQ(route.start_pose.position.y, start_pose.position.y);
328+
EXPECT_EQ(route.goal_pose.position.x, goal_pose.position.x);
329+
EXPECT_EQ(route.goal_pose.position.y, goal_pose.position.y);
330+
std::vector<lanelet::Id> path_lanelet_ids = {9102, 9540, 9546, 9178, 52, 124};
331+
EXPECT_EQ(route.segments.size(), path_lanelet_ids.size());
332+
for (size_t i = 0; i < route.segments.size(); i++) {
333+
EXPECT_EQ(route.segments[i].preferred_primitive.id, path_lanelet_ids[i]);
334+
const auto & primitives = route.segments[i].primitives;
335+
EXPECT_TRUE(std::find_if(primitives.begin(), primitives.end(), [&](const auto & primitive) {
336+
return primitive.id == path_lanelet_ids[i];
337+
}) != primitives.end());
338+
}
339+
340+
/**
341+
* 2) goal pose on the road shoulder
342+
*/
343+
Pose goal_pose_on_road_shoulder;
344+
goal_pose_on_road_shoulder.position.x = 3742.3825513144147;
345+
goal_pose_on_road_shoulder.position.y = 73737.75783925217;
346+
goal_pose_on_road_shoulder.position.z = 0.0;
347+
goal_pose_on_road_shoulder.orientation.x = 0.0;
348+
goal_pose_on_road_shoulder.orientation.y = 0.0;
349+
goal_pose_on_road_shoulder.orientation.z = 0.23721495449671745;
350+
goal_pose_on_road_shoulder.orientation.w = 0.9714571865826721;
351+
352+
RoutePoints route_points_to_road_shoulder;
353+
route_points_to_road_shoulder.push_back(start_pose);
354+
route_points_to_road_shoulder.push_back(goal_pose_on_road_shoulder);
355+
const auto route_to_road_shoulder = planner_.plan(route_points_to_road_shoulder);
356+
357+
EXPECT_EQ(route_to_road_shoulder.start_pose.position.x, start_pose.position.x);
358+
EXPECT_EQ(route_to_road_shoulder.start_pose.position.y, start_pose.position.y);
359+
EXPECT_EQ(route_to_road_shoulder.goal_pose.position.x, goal_pose_on_road_shoulder.position.x);
360+
EXPECT_EQ(route_to_road_shoulder.goal_pose.position.y, goal_pose_on_road_shoulder.position.y);
361+
std::vector<lanelet::Id> path_lanelet_to_road_shoulder_ids = {9102, 9540, 9546};
362+
EXPECT_EQ(route_to_road_shoulder.segments.size(), path_lanelet_to_road_shoulder_ids.size());
363+
for (size_t i = 0; i < route_to_road_shoulder.segments.size(); i++) {
364+
EXPECT_EQ(
365+
route_to_road_shoulder.segments[i].preferred_primitive.id,
366+
path_lanelet_to_road_shoulder_ids[i]);
367+
const auto & primitives = route_to_road_shoulder.segments[i].primitives;
368+
EXPECT_TRUE(std::find_if(primitives.begin(), primitives.end(), [&](const auto & primitive) {
369+
return primitive.id == path_lanelet_to_road_shoulder_ids[i];
370+
}) != primitives.end());
371+
}
372+
}
373+
374+
// `visualize` function is used for user too, so it is more important than debug functions
375+
TEST_F(DefaultPlannerTest, visualize)
376+
{
377+
DefaultPlanner planner;
378+
planner_.set_default_test_map();
379+
const LaneletRoute route = autoware::test_utils::makeBehaviorNormalRoute();
380+
const auto marker_array = planner_.visualize(route);
381+
// clang-format off
382+
const std::vector<std::string> expected_ns = {
383+
// 1) lanelet::visualization::laneletsBoundaryAsMarkerArray
384+
// center line is not set in the test lanelets,
385+
// so "center_lane_line" and "center_line_arrows" are not visualized
386+
"left_lane_bound", "right_lane_bound", "lane_start_bound",
387+
// 2) lanelet::visualization::laneletsAsMarkerArray
388+
"route_lanelets",
389+
// 3) lanelet::visualization::laneletsAsMarkerArray
390+
"goal_lanelets"};
391+
// clang-format on
392+
for (const auto & marker : marker_array.markers) {
393+
EXPECT_TRUE(std::find(expected_ns.begin(), expected_ns.end(), marker.ns) != expected_ns.end());
394+
}
395+
}
396+
397+
TEST_F(DefaultPlannerTest, visualizeDebugFootrprint)
398+
{
399+
DefaultPlanner planner;
400+
planner_.set_default_test_map();
401+
402+
autoware::universe_utils::LinearRing2d footprint;
403+
footprint.push_back({1.0, 1.0});
404+
footprint.push_back({1.0, -1.0});
405+
footprint.push_back({0.0, -1.0});
406+
footprint.push_back({-1.0, -1.0});
407+
footprint.push_back({-1.0, 1.0});
408+
footprint.push_back({0.0, 1.0});
409+
footprint.push_back({1.0, 1.0});
410+
411+
const auto marker_array = planner_.visualize_debug_footprint(footprint);
412+
EXPECT_EQ(marker_array.markers.size(), 1);
413+
EXPECT_EQ(marker_array.markers[0].points.size(), 7);
147414
}

0 commit comments

Comments
 (0)