Skip to content

Commit 83ead41

Browse files
authored
feat(intersection): extract occlusion contour as polygon (#4442)
Signed-off-by: Mamoru Sobue <mamoru.sobue@tier4.jp>
1 parent b8aad73 commit 83ead41

File tree

8 files changed

+80
-75
lines changed

8 files changed

+80
-75
lines changed

planning/behavior_velocity_intersection_module/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ find_package(autoware_cmake REQUIRED)
55
autoware_package()
66
pluginlib_export_plugin_description_file(behavior_velocity_planner plugins.xml)
77

8+
find_package(OpenCV REQUIRED)
9+
810
ament_auto_add_library(${PROJECT_NAME} SHARED
911
src/debug.cpp
1012
src/manager.cpp
@@ -13,4 +15,8 @@ ament_auto_add_library(${PROJECT_NAME} SHARED
1315
src/util.cpp
1416
)
1517

18+
target_link_libraries(${PROJECT_NAME}
19+
${OpenCV_LIBRARIES}
20+
)
21+
1622
ament_auto_package(INSTALL_TO_SHARE config)

planning/behavior_velocity_intersection_module/config/intersection.param.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
min_vehicle_brake_for_rss: -2.5 # [m/s^2]
4747
max_vehicle_velocity_for_rss: 16.66 # [m/s] == 60kmph
4848
denoise_kernel: 1.0 # [m]
49-
pub_debug_grid: false
49+
possible_object_bbox: [1.0, 2.0] # [m x m]
5050

5151
enable_rtc: # If set to true, the scene modules require approval from the rtc (request to cooperate) function. If set to false, the modules can be executed without requiring rtc approval
5252
intersection: true

planning/behavior_velocity_intersection_module/package.xml

-5
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,9 @@
2020
<depend>autoware_auto_perception_msgs</depend>
2121
<depend>autoware_auto_planning_msgs</depend>
2222
<depend>behavior_velocity_planner_common</depend>
23-
<depend>cv_bridge</depend>
2423
<depend>geometry_msgs</depend>
25-
<depend>grid_map_cv</depend>
26-
<depend>grid_map_ros</depend>
2724
<depend>interpolation</depend>
2825
<depend>lanelet2_extension</depend>
29-
<depend>libboost-dev</depend>
30-
<depend>libopencv-dev</depend>
3126
<depend>magic_enum</depend>
3227
<depend>motion_utils</depend>
3328
<depend>nav_msgs</depend>

planning/behavior_velocity_intersection_module/src/debug.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,14 @@ visualization_msgs::msg::MarkerArray IntersectionModule::createDebugMarkerArray(
221221
&debug_marker_array, now);
222222
}
223223

224+
for (size_t j = 0; j < debug_data_.occlusion_polygons.size(); ++j) {
225+
const auto & p = debug_data_.occlusion_polygons.at(j);
226+
appendMarkerArray(
227+
debug::createPolygonMarkerArray(
228+
p, "occlusion_polygons", lane_id_ + j, now, 0.3, 0.0, 0.0, 1.0, 0.0, 0.0),
229+
&debug_marker_array, now);
230+
}
231+
224232
return debug_marker_array;
225233
}
226234

planning/behavior_velocity_intersection_module/src/manager.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ IntersectionModuleManager::IntersectionModuleManager(rclcpp::Node & node)
113113
ip.occlusion.max_vehicle_velocity_for_rss =
114114
node.declare_parameter<double>(ns + ".occlusion.max_vehicle_velocity_for_rss");
115115
ip.occlusion.denoise_kernel = node.declare_parameter<double>(ns + ".occlusion.denoise_kernel");
116-
ip.occlusion.pub_debug_grid = node.declare_parameter<bool>(ns + ".occlusion.pub_debug_grid");
116+
ip.occlusion.possible_object_bbox =
117+
node.declare_parameter<std::vector<double>>(ns + ".occlusion.possible_object_bbox");
117118
}
118119

119120
void IntersectionModuleManager::launchNewModules(

planning/behavior_velocity_intersection_module/src/scene_intersection.cpp

+61-64
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,17 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include <grid_map_cv/grid_map_cv.hpp>
16-
#include <grid_map_ros/grid_map_ros.hpp>
17-
#include <lanelet2_extension/regulatory_elements/road_marking.hpp>
18-
#include <lanelet2_extension/utility/message_conversion.hpp>
19-
#include <lanelet2_extension/utility/query.hpp>
20-
#include <lanelet2_extension/utility/utilities.hpp>
21-
22-
#if __has_include(<cv_bridge/cv_bridge.hpp>)
23-
#include <cv_bridge/cv_bridge.hpp>
24-
#else
25-
#include <cv_bridge/cv_bridge.h>
26-
#endif
27-
// #include <sensor_msgs/image_encodings.h>
28-
// #include <opencv2/highgui/highgui.hpp>
2915
#include "scene_intersection.hpp"
16+
3017
#include "util.hpp"
3118

3219
#include <behavior_velocity_planner_common/utilization/boost_geometry_helper.hpp>
3320
#include <behavior_velocity_planner_common/utilization/path_utilization.hpp>
3421
#include <behavior_velocity_planner_common/utilization/util.hpp>
22+
#include <lanelet2_extension/regulatory_elements/road_marking.hpp>
23+
#include <lanelet2_extension/utility/message_conversion.hpp>
24+
#include <lanelet2_extension/utility/query.hpp>
25+
#include <lanelet2_extension/utility/utilities.hpp>
3526
#include <magic_enum.hpp>
3627
#include <opencv2/imgproc.hpp>
3728

@@ -93,10 +84,6 @@ IntersectionModule::IntersectionModule(
9384
planner_param_.collision_detection.state_transit_margin_time);
9485
before_creep_state_machine_.setMarginTime(planner_param_.occlusion.before_creep_stop_time);
9586
before_creep_state_machine_.setState(StateMachine::State::STOP);
96-
if (enable_occlusion_detection) {
97-
occlusion_grid_pub_ = node_.create_publisher<grid_map_msgs::msg::GridMap>(
98-
"~/debug/intersection/occlusion_grid", rclcpp::QoS(1).transient_local());
99-
}
10087
stuck_private_area_timeout_.setMarginTime(planner_param_.stuck_vehicle.timeout_private_area);
10188
stuck_private_area_timeout_.setState(StateMachine::State::STOP);
10289
}
@@ -1176,7 +1163,7 @@ bool IntersectionModule::isOcclusionCleared(
11761163
}
11771164
}
11781165
for (const auto & poly : attention_area_cv_polygons) {
1179-
cv::fillPoly(attention_mask, poly, cv::Scalar(255), cv::LINE_AA);
1166+
cv::fillPoly(attention_mask, poly, cv::Scalar(255), cv::LINE_4);
11801167
}
11811168
// (1.1)
11821169
// reset adjacent_lanelets area to 0 on attention_mask
@@ -1201,8 +1188,8 @@ bool IntersectionModule::isOcclusionCleared(
12011188
for (const auto & common_area : common_areas) {
12021189
std::vector<cv::Point> adjacent_lane_cv_polygon;
12031190
for (const auto & p : common_area.outer()) {
1204-
const int idx_x = static_cast<int>((p.x() - origin.x) / resolution);
1205-
const int idx_y = static_cast<int>((p.y() - origin.y) / resolution);
1191+
const int idx_x = std::floor<int>((p.x() - origin.x) / resolution);
1192+
const int idx_y = std::floor<int>((p.y() - origin.y) / resolution);
12061193
adjacent_lane_cv_polygon.emplace_back(idx_x, height - 1 - idx_y);
12071194
}
12081195
adjacent_lane_cv_polygons.push_back(adjacent_lane_cv_polygon);
@@ -1231,7 +1218,7 @@ bool IntersectionModule::isOcclusionCleared(
12311218
cv::bitwise_and(attention_mask, unknown_mask, occlusion_mask_raw);
12321219
// (3.1) apply morphologyEx
12331220
cv::Mat occlusion_mask;
1234-
const int morph_size = std::ceil(planner_param_.occlusion.denoise_kernel / resolution);
1221+
const int morph_size = static_cast<int>(planner_param_.occlusion.denoise_kernel / resolution);
12351222
cv::morphologyEx(
12361223
occlusion_mask_raw, occlusion_mask, cv::MORPH_OPEN,
12371224
cv::getStructuringElement(cv::MORPH_RECT, cv::Size(morph_size, morph_size)));
@@ -1337,59 +1324,70 @@ bool IntersectionModule::isOcclusionCleared(
13371324
}
13381325
}
13391326

1340-
// clean-up and find nearest risk
1327+
const auto & possible_object_bbox = planner_param_.occlusion.possible_object_bbox;
1328+
const double possible_object_bbox_x = possible_object_bbox.at(0) / resolution;
1329+
const double possible_object_bbox_y = possible_object_bbox.at(1) / resolution;
1330+
const double possible_object_area = possible_object_bbox_x * possible_object_bbox_y;
1331+
std::vector<std::vector<cv::Point>> contours;
1332+
cv::findContours(occlusion_mask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
1333+
std::vector<std::vector<cv::Point>> valid_contours;
1334+
for (const auto & contour : contours) {
1335+
std::vector<cv::Point> valid_contour;
1336+
for (const auto & p : contour) {
1337+
if (distance_grid.at<unsigned char>(p.y, p.x) == undef_pixel) {
1338+
continue;
1339+
}
1340+
valid_contour.push_back(p);
1341+
}
1342+
if (valid_contour.size() <= 2) {
1343+
continue;
1344+
}
1345+
std::vector<cv::Point> approx_contour;
1346+
cv::approxPolyDP(
1347+
valid_contour, approx_contour,
1348+
std::round(std::min(possible_object_bbox_x, possible_object_bbox_y) / std::sqrt(2.0)), true);
1349+
if (approx_contour.size() <= 1) continue;
1350+
// check area
1351+
const double poly_area = cv::contourArea(approx_contour);
1352+
if (poly_area < possible_object_area) continue;
1353+
1354+
valid_contours.push_back(approx_contour);
1355+
geometry_msgs::msg::Polygon polygon_msg;
1356+
geometry_msgs::msg::Point32 point_msg;
1357+
for (const auto & p : approx_contour) {
1358+
const double glob_x = (p.x + 0.5) * resolution + origin.x;
1359+
const double glob_y = (height - 0.5 - p.y) * resolution + origin.y;
1360+
point_msg.x = glob_x;
1361+
point_msg.y = glob_y;
1362+
point_msg.z = origin.z;
1363+
polygon_msg.points.push_back(point_msg);
1364+
}
1365+
debug_data_.occlusion_polygons.push_back(polygon_msg);
1366+
}
1367+
13411368
const int min_cost_thr = dist2pixel(occlusion_dist_thr);
13421369
int min_cost = undef_pixel - 1;
1343-
int max_cost = 0;
1344-
std::optional<int> min_cost_projection_ind = std::nullopt;
13451370
geometry_msgs::msg::Point nearest_occlusion_point;
1346-
for (int i = 0; i < width; ++i) {
1347-
for (int j = 0; j < height; ++j) {
1348-
const int pixel = static_cast<int>(distance_grid.at<unsigned char>(height - 1 - j, i));
1349-
const bool occluded = (occlusion_mask.at<unsigned char>(height - 1 - j, i) == 255);
1371+
for (const auto & occlusion_contour : valid_contours) {
1372+
for (const auto & p : occlusion_contour) {
1373+
const int pixel = static_cast<int>(distance_grid.at<unsigned char>(p.y, p.x));
1374+
const bool occluded = (occlusion_mask.at<unsigned char>(p.y, p.x) == 255);
13501375
if (pixel == undef_pixel || !occluded) {
1351-
// ignore outside of cropped
1352-
// some cell maybe undef still
1353-
distance_grid.at<unsigned char>(height - 1 - j, i) = 0;
13541376
continue;
13551377
}
1356-
if (max_cost < pixel) {
1357-
max_cost = pixel;
1358-
}
1359-
const int projection_ind = projection_ind_grid.at<int>(height - 1 - j, i);
13601378
if (pixel < min_cost) {
1361-
assert(projection_ind >= 0);
13621379
min_cost = pixel;
1363-
min_cost_projection_ind = projection_ind;
1364-
nearest_occlusion_point.x = origin.x + i * resolution;
1365-
nearest_occlusion_point.y = origin.y + j * resolution;
1366-
nearest_occlusion_point.z = origin.z + distance_max * pixel / max_cost_pixel;
1380+
nearest_occlusion_point.x = origin.x + p.x * resolution;
1381+
nearest_occlusion_point.y = origin.y + (height - 1 - p.y) * resolution;
1382+
nearest_occlusion_point.z = origin.z;
13671383
}
13681384
}
13691385
}
1370-
debug_data_.nearest_occlusion_point = nearest_occlusion_point;
1371-
1372-
if (planner_param_.occlusion.pub_debug_grid) {
1373-
cv::Mat distance_grid_heatmap;
1374-
cv::applyColorMap(distance_grid, distance_grid_heatmap, cv::COLORMAP_JET);
1375-
grid_map::GridMap occlusion_grid({"elevation"});
1376-
occlusion_grid.setFrameId("map");
1377-
occlusion_grid.setGeometry(
1378-
grid_map::Length(width * resolution, height * resolution), resolution,
1379-
grid_map::Position(origin.x + width * resolution / 2, origin.y + height * resolution / 2));
1380-
cv::rotate(distance_grid, distance_grid, cv::ROTATE_90_COUNTERCLOCKWISE);
1381-
cv::rotate(distance_grid_heatmap, distance_grid_heatmap, cv::ROTATE_90_COUNTERCLOCKWISE);
1382-
grid_map::GridMapCvConverter::addLayerFromImage<unsigned char, 1>(
1383-
distance_grid, "elevation", occlusion_grid, origin.z /* elevation for 0 */,
1384-
origin.z + distance_max /* elevation for 255 */);
1385-
grid_map::GridMapCvConverter::addColorLayerFromImage<unsigned char, 3>(
1386-
distance_grid_heatmap, "color", occlusion_grid);
1387-
occlusion_grid_pub_->publish(grid_map::GridMapRosConverter::toMessage(occlusion_grid));
1388-
}
13891386

1390-
if (min_cost > min_cost_thr || !min_cost_projection_ind.has_value()) {
1387+
if (min_cost > min_cost_thr) {
13911388
return true;
13921389
} else {
1390+
debug_data_.nearest_occlusion_point = nearest_occlusion_point;
13931391
return false;
13941392
}
13951393
}
@@ -1418,9 +1416,8 @@ bool IntersectionModule::checkFrontVehicleDeceleration(
14181416
// get the nearest centerpoint to object
14191417
std::vector<double> dist_obj_center_points;
14201418
for (const auto & p : center_points)
1421-
dist_obj_center_points.push_back(tier4_autoware_utils::calcDistance2d(object_pose.position, p));
1422-
const int obj_closest_centerpoint_idx = std::distance(
1423-
dist_obj_center_points.begin(),
1419+
dist_obj_center_points.push_back(tier4_autoware_utils::calcDistance2d(object_pose.position,
1420+
p)); const int obj_closest_centerpoint_idx = std::distance( dist_obj_center_points.begin(),
14241421
std::min_element(dist_obj_center_points.begin(), dist_obj_center_points.end()));
14251422
// find two center_points whose distances from `closest_centerpoint` cross stopping_distance
14261423
double acc_dist_prev = 0.0, acc_dist = 0.0;

planning/behavior_velocity_intersection_module/src/scene_intersection.hpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@
2020
#include <behavior_velocity_planner_common/scene_module_interface.hpp>
2121
#include <behavior_velocity_planner_common/utilization/boost_geometry_helper.hpp>
2222
#include <behavior_velocity_planner_common/utilization/state_machine.hpp>
23-
#include <grid_map_core/grid_map_core.hpp>
2423
#include <motion_utils/motion_utils.hpp>
2524
#include <rclcpp/rclcpp.hpp>
2625
#include <tier4_autoware_utils/tier4_autoware_utils.hpp>
2726

2827
#include <autoware_auto_planning_msgs/msg/path_with_lane_id.hpp>
29-
#include <grid_map_msgs/msg/grid_map.hpp>
3028

3129
#include <lanelet2_core/LaneletMap.h>
3230
#include <lanelet2_routing/RoutingGraph.h>
@@ -108,7 +106,7 @@ class IntersectionModule : public SceneModuleInterface
108106
double min_vehicle_brake_for_rss;
109107
double max_vehicle_velocity_for_rss;
110108
double denoise_kernel;
111-
bool pub_debug_grid;
109+
std::vector<double> possible_object_bbox;
112110
} occlusion;
113111
};
114112

@@ -274,7 +272,6 @@ class IntersectionModule : public SceneModuleInterface
274272
*/
275273

276274
util::DebugData debug_data_;
277-
rclcpp::Publisher<grid_map_msgs::msg::GridMap>::SharedPtr occlusion_grid_pub_;
278275
};
279276

280277
} // namespace behavior_velocity_planner

planning/behavior_velocity_intersection_module/src/util_type.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct DebugData
4949
autoware_auto_perception_msgs::msg::PredictedObjects stuck_targets;
5050
std::optional<geometry_msgs::msg::Point> nearest_occlusion_point = std::nullopt;
5151
std::optional<geometry_msgs::msg::Point> nearest_occlusion_projection_point = std::nullopt;
52+
std::vector<geometry_msgs::msg::Polygon> occlusion_polygons;
5253
};
5354

5455
struct InterpolatedPathInfo

0 commit comments

Comments
 (0)