Skip to content

Commit 6ff2121

Browse files
authored
test(detection_area): refactor and add unit tests (#9087)
Signed-off-by: Maxime CLEMENT <maxime.clement@tier4.jp>
1 parent ae24913 commit 6ff2121

File tree

7 files changed

+448
-166
lines changed

7 files changed

+448
-166
lines changed

planning/behavior_velocity_planner/autoware_behavior_velocity_detection_area_module/CMakeLists.txt

+10-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,16 @@ autoware_package()
66
pluginlib_export_plugin_description_file(autoware_behavior_velocity_planner plugins.xml)
77

88
ament_auto_add_library(${PROJECT_NAME} SHARED
9-
src/debug.cpp
10-
src/manager.cpp
11-
src/scene.cpp
9+
DIRECTORY src
1210
)
1311

12+
if(BUILD_TESTING)
13+
find_package(ament_lint_auto REQUIRED)
14+
ament_lint_auto_find_test_dependencies()
15+
ament_add_ros_isolated_gtest(test_${PROJECT_NAME}
16+
test/test_utils.cpp
17+
)
18+
target_link_libraries(test_${PROJECT_NAME} ${PROJECT_NAME})
19+
endif()
20+
1421
ament_auto_package(INSTALL_TO_SHARE config)

planning/behavior_velocity_planner/autoware_behavior_velocity_detection_area_module/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<depend>tf2_geometry_msgs</depend>
3434
<depend>visualization_msgs</depend>
3535

36+
<test_depend>ament_cmake_ros</test_depend>
3637
<test_depend>ament_lint_auto</test_depend>
3738
<test_depend>autoware_lint_common</test_depend>
3839

planning/behavior_velocity_planner/autoware_behavior_velocity_detection_area_module/src/scene.cpp

+17-152
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,28 @@
1414

1515
#include "scene.hpp"
1616

17+
#include "utils.hpp"
18+
1719
#include <autoware/behavior_velocity_planner_common/utilization/arc_lane_util.hpp>
1820
#include <autoware/behavior_velocity_planner_common/utilization/util.hpp>
1921
#include <autoware/motion_utils/trajectory/trajectory.hpp>
20-
#ifdef ROS_DISTRO_GALACTIC
21-
#include <tf2_eigen/tf2_eigen.h>
22-
#else
2322
#include <tf2_eigen/tf2_eigen.hpp>
24-
#endif
2523

2624
#include <lanelet2_core/geometry/Polygon.h>
2725

28-
#include <algorithm>
2926
#include <memory>
3027
#include <utility>
3128
#include <vector>
3229

3330
namespace autoware::behavior_velocity_planner
3431
{
35-
namespace bg = boost::geometry;
3632
using autoware::motion_utils::calcLongitudinalOffsetPose;
3733
using autoware::motion_utils::calcSignedArcLength;
3834

3935
DetectionAreaModule::DetectionAreaModule(
4036
const int64_t module_id, const int64_t lane_id,
4137
const lanelet::autoware::DetectionArea & detection_area_reg_elem,
42-
const PlannerParam & planner_param, const rclcpp::Logger logger,
38+
const PlannerParam & planner_param, const rclcpp::Logger & logger,
4339
const rclcpp::Clock::SharedPtr clock)
4440
: SceneModuleInterface(module_id, logger, clock),
4541
lane_id_(lane_id),
@@ -51,13 +47,6 @@ DetectionAreaModule::DetectionAreaModule(
5147
velocity_factor_.init(PlanningBehavior::USER_DEFINED_DETECTION_AREA);
5248
}
5349

54-
LineString2d DetectionAreaModule::getStopLineGeometry2d() const
55-
{
56-
const lanelet::ConstLineString3d stop_line = detection_area_reg_elem_.stopLine();
57-
return planning_utils::extendLine(
58-
stop_line[0], stop_line[1], planner_data_->stop_line_extend_length);
59-
}
60-
6150
bool DetectionAreaModule::modifyPathVelocity(PathWithLaneId * path, StopReason * stop_reason)
6251
{
6352
// Store original path
@@ -69,14 +58,16 @@ bool DetectionAreaModule::modifyPathVelocity(PathWithLaneId * path, StopReason *
6958
*stop_reason = planning_utils::initializeStopReason(StopReason::DETECTION_AREA);
7059

7160
// Find obstacles in detection area
72-
const auto obstacle_points = getObstaclePoints();
61+
const auto obstacle_points = detection_area::get_obstacle_points(
62+
detection_area_reg_elem_.detectionAreas(), *planner_data_->no_ground_pointcloud);
7363
debug_data_.obstacle_points = obstacle_points;
7464
if (!obstacle_points.empty()) {
7565
last_obstacle_found_time_ = std::make_shared<const rclcpp::Time>(clock_->now());
7666
}
7767

7868
// Get stop line geometry
79-
const auto stop_line = getStopLineGeometry2d();
69+
const auto stop_line = detection_area::get_stop_line_geometry2d(
70+
detection_area_reg_elem_, planner_data_->stop_line_extend_length);
8071

8172
// Get self pose
8273
const auto & self_pose = planner_data_->current_odometry->pose;
@@ -118,7 +109,8 @@ bool DetectionAreaModule::modifyPathVelocity(PathWithLaneId * path, StopReason *
118109
setDistance(stop_dist);
119110

120111
// Check state
121-
setSafe(canClearStopState());
112+
setSafe(detection_area::can_clear_stop_state(
113+
last_obstacle_found_time_, clock_->now(), planner_param_.state_clear_time));
122114
if (isActivated()) {
123115
state_ = State::GO;
124116
last_obstacle_found_time_ = {};
@@ -165,7 +157,14 @@ bool DetectionAreaModule::modifyPathVelocity(PathWithLaneId * path, StopReason *
165157

166158
// Ignore objects if braking distance is not enough
167159
if (planner_param_.use_pass_judge_line) {
168-
if (state_ != State::STOP && !hasEnoughBrakingDistance(self_pose, stop_point->second)) {
160+
const auto current_velocity = planner_data_->current_velocity->twist.linear.x;
161+
const double pass_judge_line_distance = planning_utils::calcJudgeLineDistWithAccLimit(
162+
current_velocity, planner_data_->current_acceleration->accel.accel.linear.x,
163+
planner_data_->delay_response_time);
164+
if (
165+
state_ != State::STOP &&
166+
!detection_area::has_enough_braking_distance(
167+
self_pose, stop_point->second, pass_judge_line_distance, current_velocity)) {
169168
RCLCPP_WARN_THROTTLE(
170169
logger_, *clock_, std::chrono::milliseconds(1000).count(),
171170
"[detection_area] vehicle is over stop border");
@@ -206,138 +205,4 @@ bool DetectionAreaModule::modifyPathVelocity(PathWithLaneId * path, StopReason *
206205

207206
return true;
208207
}
209-
210-
// calc smallest enclosing circle with average O(N) algorithm
211-
// reference:
212-
// https://erickimphotography.com/blog/wp-content/uploads/2018/09/Computational-Geometry-Algorithms-and-Applications-3rd-Ed.pdf
213-
std::pair<lanelet::BasicPoint2d, double> calcSmallestEnclosingCircle(
214-
const lanelet::ConstPolygon2d & poly)
215-
{
216-
// The `eps` is used to avoid precision bugs in circle inclusion checks.
217-
// If the value of `eps` is too small, this function doesn't work well. More than 1e-10 is
218-
// recommended.
219-
const double eps = 1e-5;
220-
lanelet::BasicPoint2d center(0.0, 0.0);
221-
double radius_squared = 0.0;
222-
223-
auto cross = [](const lanelet::BasicPoint2d & p1, const lanelet::BasicPoint2d & p2) -> double {
224-
return p1.x() * p2.y() - p1.y() * p2.x();
225-
};
226-
227-
auto make_circle_3 = [&](
228-
const lanelet::BasicPoint2d & p1, const lanelet::BasicPoint2d & p2,
229-
const lanelet::BasicPoint2d & p3) -> void {
230-
// reference for circumcenter vector https://en.wikipedia.org/wiki/Circumscribed_circle
231-
const double A = (p2 - p3).squaredNorm();
232-
const double B = (p3 - p1).squaredNorm();
233-
const double C = (p1 - p2).squaredNorm();
234-
const double S = cross(p2 - p1, p3 - p1);
235-
if (std::abs(S) < eps) return;
236-
center = (A * (B + C - A) * p1 + B * (C + A - B) * p2 + C * (A + B - C) * p3) / (4 * S * S);
237-
radius_squared = (center - p1).squaredNorm() + eps;
238-
};
239-
240-
auto make_circle_2 =
241-
[&](const lanelet::BasicPoint2d & p1, const lanelet::BasicPoint2d & p2) -> void {
242-
center = (p1 + p2) * 0.5;
243-
radius_squared = (center - p1).squaredNorm() + eps;
244-
};
245-
246-
auto in_circle = [&](const lanelet::BasicPoint2d & p) -> bool {
247-
return (center - p).squaredNorm() <= radius_squared;
248-
};
249-
250-
// mini disc
251-
for (size_t i = 1; i < poly.size(); i++) {
252-
const auto p1 = poly[i].basicPoint2d();
253-
if (in_circle(p1)) continue;
254-
255-
// mini disc with point
256-
const auto p0 = poly[0].basicPoint2d();
257-
make_circle_2(p0, p1);
258-
for (size_t j = 0; j < i; j++) {
259-
const auto p2 = poly[j].basicPoint2d();
260-
if (in_circle(p2)) continue;
261-
262-
// mini disc with two points
263-
make_circle_2(p1, p2);
264-
for (size_t k = 0; k < j; k++) {
265-
const auto p3 = poly[k].basicPoint2d();
266-
if (in_circle(p3)) continue;
267-
268-
// mini disc with tree points
269-
make_circle_3(p1, p2, p3);
270-
}
271-
}
272-
}
273-
274-
return std::make_pair(center, radius_squared);
275-
}
276-
277-
std::vector<geometry_msgs::msg::Point> DetectionAreaModule::getObstaclePoints() const
278-
{
279-
std::vector<geometry_msgs::msg::Point> obstacle_points;
280-
281-
const auto detection_areas = detection_area_reg_elem_.detectionAreas();
282-
const auto & points = *(planner_data_->no_ground_pointcloud);
283-
284-
for (const auto & detection_area : detection_areas) {
285-
const auto poly = lanelet::utils::to2D(detection_area);
286-
const auto circle = calcSmallestEnclosingCircle(poly);
287-
for (const auto p : points) {
288-
const double squared_dist = (circle.first.x() - p.x) * (circle.first.x() - p.x) +
289-
(circle.first.y() - p.y) * (circle.first.y() - p.y);
290-
if (squared_dist <= circle.second) {
291-
if (bg::within(Point2d{p.x, p.y}, poly.basicPolygon())) {
292-
obstacle_points.push_back(autoware::universe_utils::createPoint(p.x, p.y, p.z));
293-
// get all obstacle point becomes high computation cost so skip if any point is found
294-
break;
295-
}
296-
}
297-
}
298-
}
299-
300-
return obstacle_points;
301-
}
302-
303-
bool DetectionAreaModule::canClearStopState() const
304-
{
305-
// vehicle can clear stop state if the obstacle has never appeared in detection area
306-
if (!last_obstacle_found_time_) {
307-
return true;
308-
}
309-
310-
// vehicle can clear stop state if the certain time has passed since the obstacle disappeared
311-
const auto elapsed_time = clock_->now() - *last_obstacle_found_time_;
312-
if (elapsed_time.seconds() >= planner_param_.state_clear_time) {
313-
return true;
314-
}
315-
316-
// rollback in simulation mode
317-
if (elapsed_time.seconds() < 0.0) {
318-
return true;
319-
}
320-
321-
return false;
322-
}
323-
324-
bool DetectionAreaModule::hasEnoughBrakingDistance(
325-
const geometry_msgs::msg::Pose & self_pose, const geometry_msgs::msg::Pose & line_pose) const
326-
{
327-
// get vehicle info and compute pass_judge_line_distance
328-
const auto current_velocity = planner_data_->current_velocity->twist.linear.x;
329-
const double max_acc = planner_data_->max_stop_acceleration_threshold;
330-
const double delay_response_time = planner_data_->delay_response_time;
331-
const double pass_judge_line_distance =
332-
planning_utils::calcJudgeLineDistWithAccLimit(current_velocity, max_acc, delay_response_time);
333-
334-
// prevent from being judged as not having enough distance when the current velocity is zero
335-
// and the vehicle crosses the stop line
336-
if (current_velocity < 1e-3) {
337-
return true;
338-
}
339-
340-
return arc_lane_utils::calcSignedDistance(self_pose, line_pose.position) >
341-
pass_judge_line_distance;
342-
}
343208
} // namespace autoware::behavior_velocity_planner

planning/behavior_velocity_planner/autoware_behavior_velocity_detection_area_module/src/scene.hpp

+1-11
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,10 @@ class DetectionAreaModule : public SceneModuleInterface
6363
double distance_to_judge_over_stop_line;
6464
};
6565

66-
public:
6766
DetectionAreaModule(
6867
const int64_t module_id, const int64_t lane_id,
6968
const lanelet::autoware::DetectionArea & detection_area_reg_elem,
70-
const PlannerParam & planner_param, const rclcpp::Logger logger,
69+
const PlannerParam & planner_param, const rclcpp::Logger & logger,
7170
const rclcpp::Clock::SharedPtr clock);
7271

7372
bool modifyPathVelocity(PathWithLaneId * path, StopReason * stop_reason) override;
@@ -76,15 +75,6 @@ class DetectionAreaModule : public SceneModuleInterface
7675
autoware::motion_utils::VirtualWalls createVirtualWalls() override;
7776

7877
private:
79-
LineString2d getStopLineGeometry2d() const;
80-
81-
std::vector<geometry_msgs::msg::Point> getObstaclePoints() const;
82-
83-
bool canClearStopState() const;
84-
85-
bool hasEnoughBrakingDistance(
86-
const geometry_msgs::msg::Pose & self_pose, const geometry_msgs::msg::Pose & line_pose) const;
87-
8878
// Lane id
8979
int64_t lane_id_;
9080

0 commit comments

Comments
 (0)