Apollo 10.0
自动驾驶开放平台
open_space_roi_util.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2023 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
22
23#include <limits>
24#include <memory>
25#include <numeric>
26#include <utility>
27
29
30namespace apollo {
31namespace planning {
32
35
37 OpenSpaceInfo *const open_space_info) {
38 auto &obstacles_vertices_vec =
39 *open_space_info->mutable_obstacles_vertices_vec();
40 auto &obstacles_edges_num_vec =
41 *open_space_info->mutable_obstacles_edges_num();
42 size_t obstacles_vertices_vec_num = obstacles_vertices_vec.size();
43 obstacles_edges_num_vec.resize(obstacles_vertices_vec_num, 1);
44 for (size_t i = 0; i < obstacles_vertices_vec_num; i++) {
45 CHECK_GT(obstacles_vertices_vec[i].size(), 1U);
46 obstacles_edges_num_vec(i, 0) =
47 static_cast<int>(obstacles_vertices_vec[i].size()) - 1;
48 }
49 open_space_info->set_obstacles_num(obstacles_vertices_vec.size());
50 // Transform vertices into the form of Ax>b
51 if (!LoadObstacleInHyperPlanes(open_space_info)) {
52 AERROR << "fail at LoadObstacleInHyperPlanes()";
53 return false;
54 }
55 return true;
56}
57
59 const std::vector<std::vector<common::math::Vec2d>> &roi_parking_boundary,
60 std::vector<double> *const XYBoundary) {
61 XYBoundary->clear();
62 XYBoundary->resize(4); // x_min x_max y_min y_max
63 *XYBoundary = {std::numeric_limits<double>::max(),
64 std::numeric_limits<double>::lowest(),
65 std::numeric_limits<double>::max(),
66 std::numeric_limits<double>::lowest()};
67 for (auto &bound_vec : roi_parking_boundary) {
68 for (auto &pt : bound_vec) {
69 XYBoundary->at(0) = std::min<double>(XYBoundary->at(0), pt.x());
70 XYBoundary->at(1) = std::max<double>(XYBoundary->at(1), pt.x());
71 XYBoundary->at(2) = std::min<double>(XYBoundary->at(2), pt.y());
72 XYBoundary->at(3) = std::max<double>(XYBoundary->at(3), pt.y());
73 }
74 }
75}
76
78 const common::math::Vec2d &origin_point,
79 const double heading,
80 std::vector<std::vector<common::math::Vec2d>> *roi_parking_boundary) {
81 for (auto &bound_vec : *roi_parking_boundary) {
82 TransformByOriginPoint(origin_point, heading, &bound_vec);
83 }
84}
85
87 const common::math::Vec2d &origin_point,
88 const double heading,
89 std::vector<common::math::Vec2d> *roi_parking_boundary) {
90 for (auto &point : *roi_parking_boundary) {
91 TransformByOriginPoint(origin_point, heading, &point);
92 }
93}
94
96 const common::math::Vec2d &origin_point,
97 const double heading,
98 common::math::Vec2d *point) {
99 *point -= origin_point;
100 point->SelfRotate(-heading);
101}
102
104 const double filtering_distance,
105 const double perception_obstacle_buffer,
106 const std::vector<double> &xy_boundary,
107 Frame *const frame,
108 std::vector<std::vector<common::math::Vec2d>> *const
109 roi_parking_boundary) {
110 auto obstacles_by_frame = frame->GetObstacleList();
111 size_t perception_obstacles_num = 0;
112 // load vertices for perception obstacles(repeat the first vertice at the
113 // last to form closed convex hull)
114 for (const auto &obstacle : obstacles_by_frame->Items()) {
115 if (FilterOutObstacle(filtering_distance, *frame, xy_boundary, *obstacle)) {
116 continue;
117 }
118 ++perception_obstacles_num;
119
120 Box2d original_box = obstacle->PerceptionBoundingBox();
121 original_box.LongitudinalExtend(perception_obstacle_buffer);
122 original_box.LateralExtend(perception_obstacle_buffer);
123
124 // TODO(Jinyun): Check correctness of ExpandByDistance() in polygon
125 // Polygon2d buffered_box(original_box);
126 // buffered_box = buffered_box.ExpandByDistance(
127 // config_.perception_obstacle_buffer());
128 // TODO(Runxin): Rotate from origin instead
129 // original_box.RotateFromCenter(-1.0 * origin_heading);
130 std::vector<Vec2d> vertices_ccw = original_box.GetAllCorners();
131 std::vector<Vec2d> vertices_cw;
132 while (!vertices_ccw.empty()) {
133 auto current_corner_pt = vertices_ccw.back();
134 vertices_cw.push_back(current_corner_pt);
135 vertices_ccw.pop_back();
136 }
137 // As the perception obstacle is a closed convex set, the first vertice
138 // is repeated at the end of the vector to help transform all four edges
139 // to inequality constraint
140 vertices_cw.push_back(vertices_cw.front());
141 roi_parking_boundary->push_back(vertices_cw);
142 }
143
144 return true;
145}
146
148 const double filtering_distance,
149 const Frame &frame,
150 const std::vector<double> &xy_boundary,
151 const Obstacle &obstacle) {
152 if (obstacle.IsVirtual()) {
153 return true;
154 }
155
156 const auto &open_space_info = frame.open_space_info();
157 const auto &obstacle_box = obstacle.PerceptionBoundingBox();
158 auto obstacle_center_xy = obstacle_box.center();
159
160 // xy_boundary in xmin, xmax, ymin, ymax.
161 if (obstacle_center_xy.x() < xy_boundary[0] ||
162 obstacle_center_xy.x() > xy_boundary[1] ||
163 obstacle_center_xy.y() < xy_boundary[2] ||
164 obstacle_center_xy.y() > xy_boundary[3]) {
165 return true;
166 }
167
168 // Translate the end pose back to world frame with endpose in x, y, phi, v
169 const auto &end_pose = open_space_info.open_space_end_pose();
170 Vec2d end_pose_x_y(end_pose[0], end_pose[1]);
171 const auto &vehicle_state = frame.vehicle_state();
172 // Get vehicle state
173 Vec2d vehicle_x_y(vehicle_state.x(), vehicle_state.y());
174
175 // Use vehicle position and end position to filter out obstacle
176 const double vehicle_center_to_obstacle =
177 obstacle_box.DistanceTo(vehicle_x_y);
178 const double end_pose_center_to_obstacle =
179 obstacle_box.DistanceTo(end_pose_x_y);
180 if (vehicle_center_to_obstacle > filtering_distance &&
181 end_pose_center_to_obstacle > filtering_distance) {
182 return true;
183 }
184 return false;
185}
186
188 OpenSpaceInfo *const open_space_info) {
189 *(open_space_info->mutable_obstacles_A()) =
190 Eigen::MatrixXd::Zero(open_space_info->obstacles_edges_num().sum(), 2);
191 *(open_space_info->mutable_obstacles_b()) =
192 Eigen::MatrixXd::Zero(open_space_info->obstacles_edges_num().sum(), 1);
193 // vertices using H-representation
194 if (!GetHyperPlanes(open_space_info->obstacles_num(),
195 open_space_info->obstacles_edges_num(),
196 open_space_info->obstacles_vertices_vec(),
197 open_space_info->mutable_obstacles_A(),
198 open_space_info->mutable_obstacles_b())) {
199 AERROR << "Fail to present obstacle in hyperplane";
200 return false;
201 }
202 return true;
203}
204
206 const size_t &obstacles_num,
207 const Eigen::MatrixXi &obstacles_edges_num,
208 const std::vector<std::vector<Vec2d>> &obstacles_vertices_vec,
209 Eigen::MatrixXd *A_all,
210 Eigen::MatrixXd *b_all) {
211 if (obstacles_num != obstacles_vertices_vec.size()) {
212 AERROR << "obstacles_num != obstacles_vertices_vec.size()";
213 return false;
214 }
215
216 A_all->resize(obstacles_edges_num.sum(), 2);
217 b_all->resize(obstacles_edges_num.sum(), 1);
218
219 int counter = 0;
220 double kEpsilon = 1.0e-5;
221 // start building H representation
222 for (size_t i = 0; i < obstacles_num; ++i) {
223 size_t current_vertice_num = obstacles_edges_num(i, 0);
224 Eigen::MatrixXd A_i(current_vertice_num, 2);
225 Eigen::MatrixXd b_i(current_vertice_num, 1);
226
227 // take two subsequent vertices, and computer hyperplane
228 for (size_t j = 0; j < current_vertice_num; ++j) {
229 Vec2d v1 = obstacles_vertices_vec[i][j];
230 Vec2d v2 = obstacles_vertices_vec[i][j + 1];
231
232 Eigen::MatrixXd A_tmp(2, 1), b_tmp(1, 1), ab(2, 1);
233 // find hyperplane passing through v1 and v2
234 if (std::abs(v1.x() - v2.x()) < kEpsilon) {
235 if (v2.y() < v1.y()) {
236 A_tmp << 1, 0;
237 b_tmp << v1.x();
238 } else {
239 A_tmp << -1, 0;
240 b_tmp << -v1.x();
241 }
242 } else if (std::abs(v1.y() - v2.y()) < kEpsilon) {
243 if (v1.x() < v2.x()) {
244 A_tmp << 0, 1;
245 b_tmp << v1.y();
246 } else {
247 A_tmp << 0, -1;
248 b_tmp << -v1.y();
249 }
250 } else {
251 Eigen::MatrixXd tmp1(2, 2);
252 tmp1 << v1.x(), 1, v2.x(), 1;
253 Eigen::MatrixXd tmp2(2, 1);
254 tmp2 << v1.y(), v2.y();
255 ab = tmp1.inverse() * tmp2;
256 double a = ab(0, 0);
257 double b = ab(1, 0);
258
259 if (v1.x() < v2.x()) {
260 A_tmp << -a, 1;
261 b_tmp << b;
262 } else {
263 A_tmp << a, -1;
264 b_tmp << -b;
265 }
266 }
267
268 // store vertices
269 A_i.block(j, 0, 1, 2) = A_tmp.transpose();
270 b_i.block(j, 0, 1, 1) = b_tmp;
271 }
272
273 A_all->block(counter, 0, A_i.rows(), 2) = A_i;
274 b_all->block(counter, 0, b_i.rows(), 1) = b_i;
275 counter += static_cast<int>(current_vertice_num);
276 }
277 return true;
278}
279
281 const Vec2d &origin_point,
282 const double &origin_heading,
283 OpenSpaceInfo *open_space_info) {
284 open_space_info->set_origin_heading(origin_heading);
285 *open_space_info->mutable_origin_point() = origin_point;
286 auto obstacles_vertices_vec =
287 open_space_info->mutable_obstacles_vertices_vec();
288 TransformByOriginPoint(origin_point, origin_heading, obstacles_vertices_vec);
289 auto end_pose_vec = open_space_info->mutable_open_space_end_pose();
290 Vec2d end_pose(end_pose_vec->at(0), end_pose_vec->at(1));
291 TransformByOriginPoint(origin_point, origin_heading, &end_pose);
292 end_pose_vec->at(0) = end_pose.x();
293 end_pose_vec->at(1) = end_pose.y();
294 end_pose_vec->at(2) -= origin_heading;
295 auto xy_boundary = open_space_info->mutable_ROI_xy_boundary();
296 GetRoiXYBoundary(*obstacles_vertices_vec, xy_boundary);
297}
298bool OpenSpaceRoiUtil::IsPolygonClockwise(const std::vector<Vec2d> &polygon) {
299 double s = 0;
300 for (size_t i = 0; i < polygon.size(); i++) {
301 if (i + 1 < polygon.size()) {
302 s += polygon.at(i).x() * polygon.at(i + 1).y() -
303 polygon.at(i).y() * polygon.at(i + 1).x();
304 } else {
305 s += polygon.at(i).x() * polygon.at(0).y() -
306 polygon.at(i).y() * polygon.at(0).x();
307 }
308 }
309 if (s < 0) {
310 return true;
311 } else {
312 return false;
313 }
314}
315
317 std::vector<Vec2d> *polygon) {
318 if (!IsPolygonClockwise(*polygon)) {
319 // counter clockwise reverse it
320 ADEBUG << "point is anticlockwise,reverse";
321 std::reverse(polygon->begin(), polygon->end());
322 return true;
323 } else {
324 return false;
325 }
326}
327// make points order as left top ,right top, right bottom, left bottom
329 const apollo::hdmap::Path &nearby_path, std::vector<Vec2d> *points) {
331 double min_dist = std::numeric_limits<double>::max();
332 size_t min_index = 0;
333 for (size_t i = 0; i < points->size(); i++) {
334 double s = 0.0, l = 0.0;
335 nearby_path.GetProjection(points->at(i), &s, &l);
336 ADEBUG << std::fixed << points->at(i).x() << "," << points->at(i).y()
337 << "sl" << s << "," << l;
338 if (std::fabs(s) + 2.0 * std::fabs(l) < min_dist) {
339 min_dist = std::fabs(s) + 2.0 * std::fabs(l);
340 min_index = i;
341 }
342 }
343 std::vector<Vec2d> tmp_points(*points);
344 for (size_t i = 0; i < points->size(); i++) {
345 tmp_points[i] = points->at((i + min_index) % points->size());
346 }
347 for (size_t i = 0; i < points->size(); i++) {
348 points->at(i) = tmp_points[i];
349 }
350 return true;
351}
352
353} // namespace planning
354} // namespace apollo
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
void GetAllCorners(std::vector< Vec2d > *const corners) const
Getter of the corners of the box
Definition box2d.cc:140
void LateralExtend(const double extension_length)
Definition box2d.cc:412
const Vec2d & center() const
Getter of the center of the box
Definition box2d.h:106
void LongitudinalExtend(const double extension_length)
Extend the box longitudinally
Definition box2d.cc:406
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
void SelfRotate(const double angle)
rotate the vector itself by angle.
Definition vec2d.cc:70
double y() const
Getter for y component
Definition vec2d.h:57
double x() const
Getter for x component
Definition vec2d.h:54
bool GetProjection(const common::math::Vec2d &point, double *accumulate_s, double *lateral) const
Definition path.cc:739
Frame holds all data for one planning cycle.
Definition frame.h:62
const OpenSpaceInfo & open_space_info() const
Definition frame.h:167
const common::VehicleState & vehicle_state() const
Definition frame.cc:83
ThreadSafeIndexedObstacles * GetObstacleList()
Definition frame.h:165
This is the class that associates an Obstacle with its path properties.
Definition obstacle.h:62
const common::math::Box2d & PerceptionBoundingBox() const
Definition obstacle.h:90
std::vector< double > * mutable_ROI_xy_boundary()
Eigen::MatrixXd * mutable_obstacles_b()
Eigen::MatrixXd * mutable_obstacles_A()
std::vector< double > * mutable_open_space_end_pose()
const std::vector< std::vector< common::math::Vec2d > > & obstacles_vertices_vec() const
common::math::Vec2d * mutable_origin_point()
Eigen::MatrixXi * mutable_obstacles_edges_num()
std::vector< std::vector< common::math::Vec2d > > * mutable_obstacles_vertices_vec()
const Eigen::MatrixXi & obstacles_edges_num() const
void set_origin_heading(const double original_heading)
void set_obstacles_num(const size_t obstacles_num)
static bool AdjustPointsOrderToClockwise(std::vector< Vec2d > *polygon)
static bool LoadObstacleInHyperPlanes(OpenSpaceInfo *const open_space_info)
brief Transform the vertice presentation of the obstacles into linear inequality as Ax>b
static bool FormulateBoundaryConstraints(OpenSpaceInfo *const open_space_info)
main process to compute and load info needed by open space planner
static bool LoadObstacles(const double filtering_distance, const double perception_obstacle_buffer, const std::vector< double > &xy_boundary, Frame *const frame, std::vector< std::vector< common::math::Vec2d > > *const roi_parking_boundary)
Load obstacle polygon to roi_boundary in clock wise order
static bool UpdateParkingPointsOrder(const apollo::hdmap::Path &nearby_path, std::vector< Vec2d > *points)
static void TransformByOriginPoint(const common::math::Vec2d &origin_point, const double heading, std::vector< std::vector< common::math::Vec2d > > *roi_parking_boundary)
static bool IsPolygonClockwise(const std::vector< Vec2d > &polygon)
static void GetRoiXYBoundary(const std::vector< std::vector< common::math::Vec2d > > &roi_parking_boundary, std::vector< double > *const XYBoundary)
get XY boundary which is minmax x or y in roi boundary
static bool FilterOutObstacle(const double filtering_distance, const Frame &frame, const std::vector< double > &xy_boundary, const Obstacle &obstacle)
is obstacle can be filterd out, filtered by distance and roi XY bound
static bool GetHyperPlanes(const size_t &obstacles_num, const Eigen::MatrixXi &obstacles_edges_num, const std::vector< std::vector< Vec2d > > &obstacles_vertices_vec, Eigen::MatrixXd *A_all, Eigen::MatrixXd *b_all)
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
class register implement
Definition arena_queue.h:37