From bca5be3acbcdf19e29d307ad18b1765888edb4d5 Mon Sep 17 00:00:00 2001 From: Kosuke Takeuchi Date: Thu, 24 Oct 2024 18:48:45 +0900 Subject: [PATCH] test(virtual_traffic_light): add unit tests for utils (#9107) Signed-off-by: kosuke55 --- .../CMakeLists.txt | 10 + .../package.xml | 1 + .../test/test_utils.cpp | 462 ++++++++++++++++++ 3 files changed, 473 insertions(+) create mode 100644 planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/test/test_utils.cpp diff --git a/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/CMakeLists.txt b/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/CMakeLists.txt index 5c9e503afc2e3..1d1484ec9647e 100644 --- a/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/CMakeLists.txt +++ b/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/CMakeLists.txt @@ -13,3 +13,13 @@ ament_auto_add_library(${PROJECT_NAME} SHARED ) ament_auto_package(INSTALL_TO_SHARE config) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + ament_lint_auto_find_test_dependencies() + file(GLOB_RECURSE TEST_SOURCES test/*.cpp) + ament_add_ros_isolated_gtest(test_${PROJECT_NAME} + ${TEST_SOURCES} + ) + target_link_libraries(test_${PROJECT_NAME} ${PROJECT_NAME}) +endif() diff --git a/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/package.xml b/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/package.xml index 971a9aec26a06..f2400839313b4 100644 --- a/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/package.xml +++ b/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/package.xml @@ -33,6 +33,7 @@ tier4_v2x_msgs visualization_msgs + ament_cmake_ros ament_lint_auto autoware_lint_common diff --git a/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/test/test_utils.cpp b/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/test/test_utils.cpp new file mode 100644 index 0000000000000..dd01b1be7fb83 --- /dev/null +++ b/planning/behavior_velocity_planner/autoware_behavior_velocity_virtual_traffic_light_module/test/test_utils.cpp @@ -0,0 +1,462 @@ +// Copyright 2024 TIER IV, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "../src/utils.hpp" + +#include +#include + +#include + +#include + +using autoware::behavior_velocity_planner::virtual_traffic_light::calcCenter; +using autoware::behavior_velocity_planner::virtual_traffic_light::calcHeadPose; +using autoware::behavior_velocity_planner::virtual_traffic_light::convertToGeomPoint; +using autoware::behavior_velocity_planner::virtual_traffic_light::createKeyValue; +using autoware::behavior_velocity_planner::virtual_traffic_light::findLastCollisionBeforeEndLine; +using autoware::behavior_velocity_planner::virtual_traffic_light::insertStopVelocityAtCollision; +using autoware::behavior_velocity_planner::virtual_traffic_light::insertStopVelocityFromStart; +using autoware::behavior_velocity_planner::virtual_traffic_light::SegmentIndexWithPoint; +using autoware::behavior_velocity_planner::virtual_traffic_light::toAutowarePoints; + +tier4_planning_msgs::msg::PathWithLaneId generateStraightPath() +{ + tier4_planning_msgs::msg::PathWithLaneId path; + for (size_t i = 0; i < 10; ++i) { + tier4_planning_msgs::msg::PathPointWithLaneId point; + point.point.pose.position.x = static_cast(i); + point.point.pose.position.y = 0; + point.point.pose.position.z = 0; + point.point.longitudinal_velocity_mps = 10.0; + path.points.push_back(point); + } + return path; +} + +TEST(VirtualTrafficLightTest, CreateKeyValue) +{ + auto key_value = createKeyValue("test_key", "test_value"); + EXPECT_EQ(key_value.key, "test_key"); + EXPECT_EQ(key_value.value, "test_value"); +} + +TEST(VirtualTrafficLightTest, ToAutowarePoints) +{ + // lanelet::ConstLineString3d line_string + { + lanelet::LineString3d line_string; + line_string.push_back(lanelet::Point3d(1, 1.0, 2.0, 3.0)); + line_string.push_back(lanelet::Point3d(2, 4.0, 5.0, 6.0)); + + const auto result = toAutowarePoints(line_string); + ASSERT_EQ(result.size(), 2); + EXPECT_DOUBLE_EQ(result[0].x(), 1.0); + EXPECT_DOUBLE_EQ(result[0].y(), 2.0); + EXPECT_DOUBLE_EQ(result[0].z(), 3.0); + EXPECT_DOUBLE_EQ(result[1].x(), 4.0); + EXPECT_DOUBLE_EQ(result[1].y(), 5.0); + EXPECT_DOUBLE_EQ(result[1].z(), 6.0); + } + + // lanelet::Optional line_string + { + lanelet::LineString3d line_string; + line_string = lanelet::LineString3d(); + line_string.push_back(lanelet::Point3d(1, 1.0, 2.0, 3.0)); + line_string.push_back(lanelet::Point3d(2, 4.0, 5.0, 6.0)); + lanelet::Optional line_string_opt = line_string; + + const auto result = toAutowarePoints(line_string_opt); + ASSERT_TRUE(result.has_value()); + ASSERT_EQ(result.value().size(), 2); + EXPECT_DOUBLE_EQ(result.value()[0].x(), 1.0); + EXPECT_DOUBLE_EQ(result.value()[0].y(), 2.0); + EXPECT_DOUBLE_EQ(result.value()[0].z(), 3.0); + EXPECT_DOUBLE_EQ(result.value()[1].x(), 4.0); + EXPECT_DOUBLE_EQ(result.value()[1].y(), 5.0); + EXPECT_DOUBLE_EQ(result.value()[1].z(), 6.0); + + // nullopt + const lanelet::Optional line_string_nullopt = {}; + const auto result_nullopt = toAutowarePoints(line_string_nullopt); + ASSERT_FALSE(result_nullopt.has_value()); + } + + // lanelet::ConstLineStrings3d line_strings + { + lanelet::LineString3d line_string1; + line_string1.push_back(lanelet::Point3d(1, 1.0, 2.0, 3.0)); + line_string1.push_back(lanelet::Point3d(2, 4.0, 5.0, 6.0)); + + lanelet::LineString3d line_string2; + line_string2.push_back(lanelet::Point3d(3, 7.0, 8.0, 9.0)); + line_string2.push_back(lanelet::Point3d(4, 10.0, 11.0, 12.0)); + + lanelet::ConstLineStrings3d line_strings; + line_strings.push_back(line_string1); + line_strings.push_back(line_string2); + + const auto result = toAutowarePoints(line_strings); + ASSERT_EQ(result.size(), 2); + ASSERT_EQ(result[0].size(), 2); + ASSERT_EQ(result[1].size(), 2); + EXPECT_DOUBLE_EQ(result[0][0].x(), 1.0); + EXPECT_DOUBLE_EQ(result[0][0].y(), 2.0); + EXPECT_DOUBLE_EQ(result[0][0].z(), 3.0); + EXPECT_DOUBLE_EQ(result[0][1].x(), 4.0); + EXPECT_DOUBLE_EQ(result[0][1].y(), 5.0); + EXPECT_DOUBLE_EQ(result[0][1].z(), 6.0); + EXPECT_DOUBLE_EQ(result[1][0].x(), 7.0); + EXPECT_DOUBLE_EQ(result[1][0].y(), 8.0); + EXPECT_DOUBLE_EQ(result[1][0].z(), 9.0); + EXPECT_DOUBLE_EQ(result[1][1].x(), 10.0); + EXPECT_DOUBLE_EQ(result[1][1].y(), 11.0); + EXPECT_DOUBLE_EQ(result[1][1].z(), 12.0); + } +} + +TEST(VirtualTrafficLightTest, CalcCenter) +{ + autoware::universe_utils::LineString3d line_string; + line_string.emplace_back(1.0, 2.0, 3.0); + line_string.emplace_back(4.0, 5.0, 6.0); + + auto center = calcCenter(line_string); + EXPECT_DOUBLE_EQ(center.x(), 2.5); + EXPECT_DOUBLE_EQ(center.y(), 3.5); + EXPECT_DOUBLE_EQ(center.z(), 4.5); +} + +TEST(VirtualTrafficLightTest, CalcHeadPose) +{ + geometry_msgs::msg::Pose base_link_pose; + base_link_pose.position.x = 1.0; + base_link_pose.position.y = 2.0; + base_link_pose.position.z = 3.0; + + double base_link_to_front = 1.0; + auto head_pose = calcHeadPose(base_link_pose, base_link_to_front); + + EXPECT_DOUBLE_EQ(head_pose.position.x, 2.0); + EXPECT_DOUBLE_EQ(head_pose.position.y, 2.0); + EXPECT_DOUBLE_EQ(head_pose.position.z, 3.0); +} + +TEST(VirtualTrafficLightTest, ConvertToGeomPoint) +{ + autoware::universe_utils::Point3d point(1.0, 2.0, 3.0); + auto geom_point = convertToGeomPoint(point); + + EXPECT_DOUBLE_EQ(geom_point.x, 1.0); + EXPECT_DOUBLE_EQ(geom_point.y, 2.0); + EXPECT_DOUBLE_EQ(geom_point.z, 0.0); // z is not set in convertToGeomPoint +} + +TEST(VirtualTrafficLightTest, InsertStopVelocityFromStart) +{ + tier4_planning_msgs::msg::PathWithLaneId path; + tier4_planning_msgs::msg::PathPointWithLaneId point; + point.point.longitudinal_velocity_mps = 10.0; + path.points.push_back(point); + + insertStopVelocityFromStart(&path); + for (const auto & p : path.points) { + EXPECT_DOUBLE_EQ(p.point.longitudinal_velocity_mps, 0.0); + } +} + +TEST(VirtualTrafficLightTest, InsertStopVelocityAtCollision) +{ + // 1) insert stop velocity at first point + { + std::cout << "----- insert stop velocity at first point -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.0; + SegmentIndexWithPoint collision; + collision.index = 0; + collision.point.x = 0.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 0); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 0.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } + + // 2) insert stop velocity at middle point + { + std::cout << "----- insert stop velocity at middle point -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.0; + SegmentIndexWithPoint collision; + collision.index = 5; + collision.point.x = 5.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 5); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 5.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } + + // 3) insert stop velocity at last + // NOTE: autoware::motion_utils::calcLongitudinalOffsetToSegment() return std::nan(""); + // so cannot insert stop velocity at last point. + // todo(someone): We need to review whether this is the correct specification. + { + std::cout << "----- insert stop velocity at last -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.0; + SegmentIndexWithPoint collision; + collision.index = 9; + collision.point.x = 9.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_FALSE(result.has_value()); + } + + // 4) insert stop velocity at middle point with offset 0.01 + { + std::cout << "----- insert stop velocity at middle point with offset 0.01 -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.01; + SegmentIndexWithPoint collision; + collision.index = 5; + collision.point.x = 5.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 6); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 5.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } + + // 5) insert stop velocity at middle point with offset 0.5 + { + std::cout << "----- insert stop velocity at middle point with offset 0.4 -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.4; + SegmentIndexWithPoint collision; + collision.index = 5; + collision.point.x = 5.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 6); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 5.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } + + // 6) insert stop velocity at middle point with offset 1.0 + { + std::cout << "----- insert stop velocity at middle point with offset 1.0 -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 1.0; + SegmentIndexWithPoint collision; + collision.index = 5; + collision.point.x = 5.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 6); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 5.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } +} + +TEST(VirtualTrafficLightTest, insertStopVelocityAtCollision) +{ + // 1) insert stop velocity at first point + { + std::cout << "----- insert stop velocity at first point -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.0; + SegmentIndexWithPoint collision; + collision.index = 0; + collision.point.x = 0.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 0); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 0.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } + + // 2) insert stop velocity at middle point + { + std::cout << "----- insert stop velocity at middle point -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.0; + SegmentIndexWithPoint collision; + collision.index = 5; + collision.point.x = 5.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 5); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 5.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } + + // 3) insert stop velocity at last + // NOTE: autoware::motion_utils::calcLongitudinalOffsetToSegment() return std::nan(""); + // so cannot insert stop velocity at last point. + // todo(someone): We need to review whether this is the correct specification. + { + std::cout << "----- insert stop velocity at last -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.0; + SegmentIndexWithPoint collision; + collision.index = 9; + collision.point.x = 9.0; + collision.point.y = 0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_FALSE(result.has_value()); + } + + // 4) insert stop velocity at middle with offset + { + std::cout << "----- insert stop velocity at middle point with 0.5 offset -----" << std::endl; + auto path = generateStraightPath(); + const double offset = 0.5; + SegmentIndexWithPoint collision; + collision.index = 5; + collision.point.x = 5.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 6); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 5.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } + + // 5) insert stop velocity at middle with negative offset + { + std::cout << "----- insert stop velocity at middle point with -0.5 offset -----" << std::endl; + auto path = generateStraightPath(); + const double offset = -0.5; + SegmentIndexWithPoint collision; + collision.index = 5; + collision.point.x = 5.0; + collision.point.y = 0.0; + const auto result = insertStopVelocityAtCollision(collision, offset, &path); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value(), 5); + const auto & point = path.points.at(result.value()); + EXPECT_DOUBLE_EQ(point.point.longitudinal_velocity_mps, 0.0); + EXPECT_DOUBLE_EQ(point.point.pose.position.x, 5.0 + offset); + EXPECT_DOUBLE_EQ(point.point.pose.position.y, 0); + } +} + +TEST(VirtualTrafficLightTest, FindLastCollisionBeforeEndLine) +{ + // LineString3d + // 1) find first collision point + { + std::cout << "----- find first collision point -----" << std::endl; + autoware::universe_utils::LineString3d target_line; + target_line.emplace_back(0.0, -1.0, 0.0); + target_line.emplace_back(0.0, 1.0, 0.0); + + const auto path = generateStraightPath(); + + const auto result = + findLastCollisionBeforeEndLine(path.points, target_line, path.points.size() - 1); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value().index, 1); + } + + // 2-1) find middle collision point + { + std::cout << "----- find middle collision point -----" << std::endl; + + autoware::universe_utils::LineString3d target_line; + target_line.emplace_back(5.0, -1.0, 0.0); + target_line.emplace_back(5.0, 1.0, 0.0); + + const auto path = generateStraightPath(); + + // target line intersects with p5-p6 + const auto result = + findLastCollisionBeforeEndLine(path.points, target_line, path.points.size() - 1); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value().index, 6); + } + + // 2-2) find middle collision point + { + std::cout << "----- find middle collision point -----" << std::endl; + + autoware::universe_utils::LineString3d target_line; + target_line.emplace_back(4.5, -1.0, 0.0); + target_line.emplace_back(4.5, 1.0, 0.0); + + const auto path = generateStraightPath(); + + // target line intersects with p4-p5 + const auto result = + findLastCollisionBeforeEndLine(path.points, target_line, path.points.size() - 1); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value().index, 5); + } + + // std::vector + // 3) find middle collision point with multi target lines + { + std::cout << "----- find collision point with multi target lines -----" << std::endl; + + std::vector target_lines; + { + autoware::universe_utils::LineString3d target_line1; + + target_line1.emplace_back(3.5, -1.0, 0.0); + target_line1.emplace_back(3.5, 1.0, 0.0); + + autoware::universe_utils::LineString3d target_line2; + target_line2.emplace_back(6.5, -1.0, 0.0); + target_line2.emplace_back(6.5, 1.0, 0.0); + + target_lines.push_back(target_line1); + target_lines.push_back(target_line2); + + const auto path = generateStraightPath(); + + // NOTE: the name of this function is findLastCollisionBeforeEndLine, but it returns the + // collision with the first line added to multiple lines + // the first target line intersects with p3-p4 + const auto result = + findLastCollisionBeforeEndLine(path.points, target_lines, path.points.size() - 1); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(result.value().index, 4); + } + } +}