Apollo 11.0
自动驾驶开放平台
open_space_roi_decider.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2019 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 <utility>
26
33namespace apollo {
34namespace planning {
35
45
47 const std::string &config_dir, const std::string &name,
48 const std::shared_ptr<DependencyInjector> &injector) {
49 if (!Decider::Init(config_dir, name, injector)) {
50 return false;
51 }
53 CHECK_NOTNULL(hdmap_);
54 vehicle_params_ =
56 // Load the config this task.
57 bool res = Decider::LoadConfig<OpenSpaceRoiDeciderConfig>(&config_);
58 AINFO << config_.DebugString();
59 return res;
60}
61
62Status OpenSpaceRoiDecider::Process(Frame *frame) {
63 if (frame == nullptr) {
64 const std::string msg =
65 "Invalid frame, fail to process the OpenSpaceRoiDecider.";
66 AERROR << msg;
67 return Status(ErrorCode::PLANNING_ERROR, msg);
68 }
69
70 vehicle_state_ = frame->vehicle_state();
71 obstacles_by_frame_ = frame->GetObstacleList();
72
73 std::array<Vec2d, 4> spot_vertices;
74 Path nearby_path;
75 // @brief vector of different obstacle consisting of vertice points.The
76 // obstacle and the vertices order are in counter-clockwise order
77 std::vector<std::vector<common::math::Vec2d>> roi_boundary;
78
79 const auto &roi_type = config_.roi_type();
80 if (roi_type == OpenSpaceRoiDeciderConfig::PARKING) {
81 target_parking_spot_id_ = frame->open_space_info().target_parking_spot_id();
82 ParkingInfo parking_info;
83 if (!GetParkingSpot(frame, &parking_info)) {
84 const std::string msg = "Fail to get parking boundary from map";
85 AERROR << msg;
86 return Status(ErrorCode::PLANNING_ERROR, msg);
87 }
88
90 parking_info.parking_type);
91
92 SetOrigin(parking_info, frame);
93
94 SetParkingSpotEndPose(parking_info, frame);
95
96 if (!GetParkingBoundary(parking_info, *nearby_path_, frame,
97 &roi_boundary)) {
98 const std::string msg = "Fail to get parking boundary from map";
99 AERROR << msg;
100 return Status(ErrorCode::PLANNING_ERROR, msg);
101 }
102 } else if (roi_type == OpenSpaceRoiDeciderConfig::PULL_OVER) {
103 if (!GetPullOverSpot(frame, &spot_vertices, &nearby_path)) {
104 const std::string msg = "Fail to get parking boundary from map";
105 AERROR << msg;
106 return Status(ErrorCode::PLANNING_ERROR, msg);
107 }
108
109 SetOrigin(frame, spot_vertices);
110
111 SetPullOverSpotEndPose(frame);
112
113 if (!GetPullOverBoundary(frame, spot_vertices, nearby_path,
114 &roi_boundary)) {
115 const std::string msg = "Fail to get parking boundary from map";
116 AERROR << msg;
117 return Status(ErrorCode::PLANNING_ERROR, msg);
118 }
119 } else if (roi_type == OpenSpaceRoiDeciderConfig::PARK_AND_GO) {
120 ADEBUG << "in Park_and_Go";
121 nearby_path =
122 frame->reference_line_info().front().reference_line().GetMapPath();
123
124 ADEBUG << "nearby_path: " << nearby_path.DebugString();
125 ADEBUG << "found nearby_path";
126 if (!injector_->planning_context()
127 ->planning_status()
128 .park_and_go()
129 .has_adc_init_position()) {
130 const std::string msg = "ADC initial position is unavailable";
131 AERROR << msg;
132 return Status(ErrorCode::PLANNING_ERROR, msg);
133 }
134 SetOriginFromADC(frame, nearby_path);
135 ADEBUG << "SetOrigin";
136 auto adc_point = common::util::PointFactory::ToPointENU(vehicle_state_);
138 double s = 0.0;
139 double l = 0.0;
140 if (!is_parking_out) {
142 adc_point, 2.0, vehicle_state_.heading(), M_PI / 3.0,
143 &lane, &s, &l) == -1;
144 }
145 if (is_parking_out) {
146 AINFO << "GetParkingOutBoundary!!";
147 if (!GetParkingOutBoundary(nearby_path, frame, &roi_boundary)) {
148 const std::string msg = "Fail to get park and go boundary from map";
149 AERROR << msg;
150 return Status(ErrorCode::PLANNING_ERROR, msg);
151 }
152 } else {
153 AINFO << "GetParkAndGoBoundary!!!";
154 if (!GetParkAndGoBoundary(frame, nearby_path, &roi_boundary)) {
155 const std::string msg = "Fail to get park and go boundary from map";
156 AERROR << msg;
157 return Status(ErrorCode::PLANNING_ERROR, msg);
158 }
159 }
160
161 SetParkAndGoEndPose(frame);
162 ADEBUG << "SetEndPose";
163 } else {
164 const std::string msg =
165 "chosen open space roi secenario type not implemented";
166 AERROR << msg;
167 return Status(ErrorCode::PLANNING_ERROR, msg);
168 }
169 if (!FormulateBoundaryConstraints(roi_boundary, frame)) {
170 const std::string msg = "Fail to formulate boundary constraints";
171 AERROR << msg;
172 return Status(ErrorCode::PLANNING_ERROR, msg);
173 }
174
175 return Status::OK();
176}
177
178// get origin from ADC
179void OpenSpaceRoiDecider::SetOriginFromADC(Frame *const frame,
180 const hdmap::Path &nearby_path) {
181 // get ADC box
182 const auto &park_and_go_status =
183 injector_->planning_context()->planning_status().park_and_go();
184
185 const double adc_init_x = park_and_go_status.adc_init_position().x();
186 const double adc_init_y = park_and_go_status.adc_init_position().y();
187 const double adc_init_heading = park_and_go_status.adc_init_heading();
188 common::math::Vec2d adc_init_position = {adc_init_x, adc_init_y};
189 const double adc_length = vehicle_params_.length();
190 const double adc_width = vehicle_params_.width();
191 // ADC box
192 Box2d adc_box(adc_init_position, adc_init_heading, adc_length + 2.0,
193 adc_width + 2.0);
194 // get vertices from ADC box
195 std::vector<common::math::Vec2d> adc_corners;
196 adc_box.GetAllCorners(&adc_corners);
197 for (size_t i = 0; i < adc_corners.size(); ++i) {
198 AINFO << "ADC [" << i << "]x: " << std::setprecision(9)
199 << adc_corners[i].x();
200 AINFO << "ADC [" << i << "]y: " << std::setprecision(9)
201 << adc_corners[i].y();
202 }
203 auto left_top = adc_corners[1];
204
205 ADEBUG << "left_top x: " << std::setprecision(9) << left_top.x();
206 ADEBUG << "left_top y: " << std::setprecision(9) << left_top.y();
207
208 // rotate the points to have the lane to be horizontal to x axis positive
209 // direction and scale them base on the origin point
210 // heading angle
211 double heading;
212 if (!nearby_path.GetHeadingAlongPath(left_top, &heading)) {
213 AERROR << "fail to get heading on reference line";
214 return;
215 }
216
217 frame->mutable_open_space_info()->set_origin_heading(
219 ADEBUG << "heading: " << heading;
220 frame->mutable_open_space_info()->mutable_origin_point()->set_x(left_top.x());
221 frame->mutable_open_space_info()->mutable_origin_point()->set_y(left_top.y());
222}
223
224void OpenSpaceRoiDecider::SetOrigin(
225 Frame *const frame, const std::array<common::math::Vec2d, 4> &vertices) {
226 auto left_top = vertices[0];
227 auto right_top = vertices[3];
228 // rotate the points to have the lane to be horizontal to x axis positive
229 // direction and scale them base on the origin point
230 Vec2d heading_vec = right_top - left_top;
231 frame->mutable_open_space_info()->set_origin_heading(heading_vec.Angle());
232 frame->mutable_open_space_info()->mutable_origin_point()->set_x(left_top.x());
233 frame->mutable_open_space_info()->mutable_origin_point()->set_y(left_top.y());
234}
235
236void OpenSpaceRoiDecider::SetOrigin(const ParkingInfo &parking_info,
237 Frame *const frame) {
238 auto left_top = parking_info.corner_points[0];
239 auto right_top = parking_info.corner_points[1];
240 // rotate the points to have the lane to be horizontal to x axis positive
241 // direction and scale them base on the origin point
242 Vec2d heading_vec = right_top - left_top;
243 frame->mutable_open_space_info()->set_origin_heading(heading_vec.Angle());
244 frame->mutable_open_space_info()->mutable_origin_point()->set_x(left_top.x());
245 frame->mutable_open_space_info()->mutable_origin_point()->set_y(left_top.y());
246}
247
248void OpenSpaceRoiDecider::SetParkingSpotEndPose(const ParkingInfo &parking_info,
249 Frame *const frame) {
250 auto left_top = parking_info.corner_points[0];
251 auto left_down = parking_info.corner_points[3];
252 auto right_down = parking_info.corner_points[2];
253 auto right_top = parking_info.corner_points[1];
254
255 const auto &origin_point = frame->open_space_info().origin_point();
256 const auto &origin_heading = frame->open_space_info().origin_heading();
257
258 // End pose is set in normalized boundary
259 left_top -= origin_point;
260 left_top.SelfRotate(-origin_heading);
261 left_down -= origin_point;
262 left_down.SelfRotate(-origin_heading);
263 right_top -= origin_point;
264 right_top.SelfRotate(-origin_heading);
265 right_down -= origin_point;
266 right_down.SelfRotate(-origin_heading);
267 Vec2d end_pt;
268 double parking_heading = 0;
269 // now only support parking space at right road side
270 const double parking_depth_buffer = config_.parking_depth_buffer();
271 if (parking_info.parking_type == ParkingType::VERTICAL_PARKING) {
272 const bool parking_inwards = config_.parking_inwards();
273 if (parking_inwards) {
274 parking_heading = (left_down - left_top).Angle();
275 Vec2d middle_top = (left_top + right_top) / 2.0;
276 end_pt = middle_top + Vec2d::CreateUnitVec2d(parking_heading) *
277 (vehicle_params_.front_edge_to_center() +
278 parking_depth_buffer);
279 } else {
280 parking_heading = (left_top - left_down).Angle();
281 Vec2d middle_down = (left_down + right_down) / 2.0;
282 end_pt = middle_down + Vec2d::CreateUnitVec2d(parking_heading) *
283 (vehicle_params_.back_edge_to_center() +
284 parking_depth_buffer);
285 }
286 } else {
287 parking_heading = (right_top - left_top).Angle();
288 Vec2d middle_left = (left_top + left_down) / 2.0;
289 end_pt = middle_left +
290 Vec2d::CreateUnitVec2d(parking_heading) *
291 (vehicle_params_.back_edge_to_center() + parking_depth_buffer);
292 }
293 auto *end_pose =
294 frame->mutable_open_space_info()->mutable_open_space_end_pose();
295 end_pose->push_back(end_pt.x());
296 end_pose->push_back(end_pt.y());
297 end_pose->push_back(parking_heading);
298 end_pose->push_back(0.0);
299}
300
301void OpenSpaceRoiDecider::SetPullOverSpotEndPose(Frame *const frame) {
302 const auto &pull_over_status =
303 injector_->planning_context()->planning_status().pull_over();
304 const double pull_over_x = pull_over_status.position().x();
305 const double pull_over_y = pull_over_status.position().y();
306 double pull_over_theta = pull_over_status.theta();
307
308 // Normalize according to origin_point and origin_heading
309 const auto &origin_point = frame->open_space_info().origin_point();
310 const auto &origin_heading = frame->open_space_info().origin_heading();
311 Vec2d center(pull_over_x, pull_over_y);
312 center -= origin_point;
313 center.SelfRotate(-origin_heading);
314 pull_over_theta =
315 common::math::NormalizeAngle(pull_over_theta - origin_heading);
316
317 auto *end_pose =
318 frame->mutable_open_space_info()->mutable_open_space_end_pose();
319 end_pose->push_back(center.x());
320 end_pose->push_back(center.y());
321 end_pose->push_back(pull_over_theta);
322 // end pose velocity set to be zero
323 end_pose->push_back(0.0);
324}
325
326void OpenSpaceRoiDecider::SetParkAndGoEndPose(Frame *const frame) {
327 const double kSTargetBuffer = config_.end_pose_s_distance();
328 const double kSpeedRatio = 0.1; // after adjust speed is 10% of speed limit
329 // get vehicle current location
330 // get vehicle s,l info
331 auto park_and_go_status = injector_->planning_context()
332 ->mutable_planning_status()
333 ->mutable_park_and_go();
334
335 const double adc_init_x = park_and_go_status->adc_init_position().x();
336 const double adc_init_y = park_and_go_status->adc_init_position().y();
337
338 ADEBUG << "ADC position (x): " << std::setprecision(9) << adc_init_x;
339 ADEBUG << "ADC position (y): " << std::setprecision(9) << adc_init_y;
340
341 const common::math::Vec2d adc_position = {adc_init_x, adc_init_y};
342 common::SLPoint adc_position_sl;
343
344 // get nearest reference line
345 const auto &reference_line_list = frame->reference_line_info();
346 ADEBUG << reference_line_list.size();
347 const auto reference_line_info = std::min_element(
348 reference_line_list.begin(), reference_line_list.end(),
349 [&](const ReferenceLineInfo &ref_a, const ReferenceLineInfo &ref_b) {
350 common::SLPoint adc_position_sl_a;
351 common::SLPoint adc_position_sl_b;
352 ref_a.reference_line().XYToSL(adc_position, &adc_position_sl_a);
353 ref_b.reference_line().XYToSL(adc_position, &adc_position_sl_b);
354 return std::fabs(adc_position_sl_a.l()) <
355 std::fabs(adc_position_sl_b.l());
356 });
357
358 const auto &reference_line = reference_line_info->reference_line();
359 reference_line.XYToSL(adc_position, &adc_position_sl);
360
361 // target is at reference line
362 const double target_s = adc_position_sl.s() + kSTargetBuffer;
363 const auto reference_point = reference_line.GetReferencePoint(target_s);
364 const double target_x = reference_point.x();
365 const double target_y = reference_point.y();
366 double target_theta = reference_point.heading();
367
368 park_and_go_status->mutable_adc_adjust_end_pose()->set_x(target_x);
369 park_and_go_status->mutable_adc_adjust_end_pose()->set_y(target_y);
370
371 ADEBUG << "center.x(): " << std::setprecision(9) << target_x;
372 ADEBUG << "center.y(): " << std::setprecision(9) << target_y;
373 ADEBUG << "target_theta: " << std::setprecision(9) << target_theta;
374
375 // Normalize according to origin_point and origin_heading
376 const auto &origin_point = frame->open_space_info().origin_point();
377 const auto &origin_heading = frame->open_space_info().origin_heading();
378 Vec2d center(target_x, target_y);
379 center -= origin_point;
380 center.SelfRotate(-origin_heading);
381 target_theta = common::math::NormalizeAngle(target_theta - origin_heading);
382
383 auto *end_pose =
384 frame->mutable_open_space_info()->mutable_open_space_end_pose();
385
386 end_pose->push_back(center.x());
387 end_pose->push_back(center.y());
388 end_pose->push_back(target_theta);
389
390 ADEBUG << "ADC position (x): " << std::setprecision(9) << (*end_pose)[0];
391 ADEBUG << "ADC position (y): " << std::setprecision(9) << (*end_pose)[1];
392 ADEBUG << "reference_line ID: " << reference_line_info->Lanes().Id();
393
394 // end pose velocity set to be speed limit
395 double target_speed = reference_line.GetSpeedLimitFromS(target_s);
396 end_pose->push_back(kSpeedRatio * target_speed);
397}
398
399void OpenSpaceRoiDecider::GetRoadBoundary(
400 const hdmap::Path &nearby_path, const double center_line_s,
401 const common::math::Vec2d &origin_point, const double origin_heading,
402 std::vector<Vec2d> *left_lane_boundary,
403 std::vector<Vec2d> *right_lane_boundary,
404 std::vector<Vec2d> *center_lane_boundary_left,
405 std::vector<Vec2d> *center_lane_boundary_right,
406 std::vector<double> *center_lane_s_left,
407 std::vector<double> *center_lane_s_right,
408 std::vector<double> *left_lane_road_width,
409 std::vector<double> *right_lane_road_width) {
410 double start_s = center_line_s - config_.roi_longitudinal_range_start();
411 double end_s = center_line_s + config_.roi_longitudinal_range_end();
412
413 hdmap::MapPathPoint start_point = nearby_path.GetSmoothPoint(start_s);
414 double last_check_point_heading = start_point.heading();
415 double index = 0.0;
416 double check_point_s = start_s;
417
418 // For the road boundary, add key points to left/right side boundary
419 // separately. Iterate s_value to check key points at a step of
420 // roi_line_segment_length. Key points include: start_point, end_point, points
421 // where path curvature is large, points near left/right road-curb corners
422 while (check_point_s <= end_s) {
423 hdmap::MapPathPoint check_point = nearby_path.GetSmoothPoint(check_point_s);
424 double check_point_heading = check_point.heading();
425 bool is_center_lane_heading_change =
426 std::abs(common::math::NormalizeAngle(check_point_heading -
427 last_check_point_heading)) >
429 last_check_point_heading = check_point_heading;
430
431 ADEBUG << "is is_center_lane_heading_change: "
432 << is_center_lane_heading_change;
433 // Check if the current center-lane checking-point is start point || end
434 // point || or point with larger curvature. If yes, mark it as an anchor
435 // point.
436 bool is_anchor_point = check_point_s == start_s || check_point_s == end_s ||
437 is_center_lane_heading_change;
438 // Add key points to the left-half boundary
439 AddBoundaryKeyPoint(nearby_path, check_point_s, start_s, end_s,
440 is_anchor_point, true, center_lane_boundary_left,
441 left_lane_boundary, center_lane_s_left,
442 left_lane_road_width);
443 // Add key points to the right-half boundary
444 AddBoundaryKeyPoint(nearby_path, check_point_s, start_s, end_s,
445 is_anchor_point, false, center_lane_boundary_right,
446 right_lane_boundary, center_lane_s_right,
447 right_lane_road_width);
448 if (check_point_s == end_s) {
449 break;
450 }
451 index += 1.0;
452 check_point_s = start_s + index * config_.roi_line_segment_length();
453 check_point_s = check_point_s >= end_s ? end_s : check_point_s;
454 }
455
456 size_t left_point_size = left_lane_boundary->size();
457 size_t right_point_size = right_lane_boundary->size();
458 for (size_t i = 0; i < left_point_size; i++) {
459 left_lane_boundary->at(i) -= origin_point;
460 left_lane_boundary->at(i).SelfRotate(-origin_heading);
461 }
462 for (size_t i = 0; i < right_point_size; i++) {
463 right_lane_boundary->at(i) -= origin_point;
464 right_lane_boundary->at(i).SelfRotate(-origin_heading);
465 }
466}
467
468void OpenSpaceRoiDecider::GetRoadBoundaryFromMap(
469 const hdmap::Path &nearby_path, const double center_line_s,
470 const Vec2d &origin_point, const double origin_heading,
471 std::vector<Vec2d> *left_lane_boundary,
472 std::vector<Vec2d> *right_lane_boundary,
473 std::vector<Vec2d> *center_lane_boundary_left,
474 std::vector<Vec2d> *center_lane_boundary_right,
475 std::vector<double> *center_lane_s_left,
476 std::vector<double> *center_lane_s_right,
477 std::vector<double> *left_lane_road_width,
478 std::vector<double> *right_lane_road_width) {
479 // Longitudinal range can be asymmetric.
480 double start_s = center_line_s - config_.roi_longitudinal_range_start();
481 double end_s = center_line_s + config_.roi_longitudinal_range_end();
482 hdmap::MapPathPoint start_point = nearby_path.GetSmoothPoint(start_s);
483
484 double check_point_s = start_s;
485
486 while (check_point_s <= end_s) {
487 hdmap::MapPathPoint check_point = nearby_path.GetSmoothPoint(check_point_s);
488
489 // get road boundaries
490 double left_road_width = nearby_path.GetRoadLeftWidth(check_point_s);
491 double right_road_width = nearby_path.GetRoadRightWidth(check_point_s);
492
493 double current_road_width = std::max(left_road_width, right_road_width);
494
495 // get road boundaries at current location
496 common::PointENU check_point_xy;
497 std::vector<hdmap::RoadRoiPtr> road_boundaries;
498 std::vector<hdmap::JunctionInfoConstPtr> junctions;
499 check_point_xy.set_x(check_point.x());
500 check_point_xy.set_y(check_point.y());
501 hdmap_->GetRoadBoundaries(check_point_xy, current_road_width,
502 &road_boundaries, &junctions);
503
504 if (check_point_s < center_line_s) {
505 for (size_t i = 0;
506 i < (*road_boundaries.at(0)).left_boundary.line_points.size(); i++) {
507 right_lane_boundary->emplace_back(
508 Vec2d((*road_boundaries.at(0)).left_boundary.line_points[i].x(),
509 (*road_boundaries.at(0)).left_boundary.line_points[i].y()));
510 }
511 for (size_t i = 0;
512 i < (*road_boundaries.at(0)).right_boundary.line_points.size();
513 i++) {
514 left_lane_boundary->emplace_back(
515 Vec2d((*road_boundaries.at(0)).right_boundary.line_points[i].x(),
516 (*road_boundaries.at(0)).right_boundary.line_points[i].y()));
517 }
518 } else {
519 for (size_t i = 0;
520 i < (*road_boundaries.at(0)).left_boundary.line_points.size(); i++) {
521 left_lane_boundary->emplace_back(
522 Vec2d((*road_boundaries.at(0)).left_boundary.line_points[i].x(),
523 (*road_boundaries.at(0)).left_boundary.line_points[i].y()));
524 }
525 for (size_t i = 0;
526 i < (*road_boundaries.at(0)).right_boundary.line_points.size();
527 i++) {
528 right_lane_boundary->emplace_back(
529 Vec2d((*road_boundaries.at(0)).right_boundary.line_points[i].x(),
530 (*road_boundaries.at(0)).right_boundary.line_points[i].y()));
531 }
532 }
533
534 center_lane_boundary_right->emplace_back(check_point);
535 center_lane_boundary_left->emplace_back(check_point);
536 center_lane_s_left->emplace_back(check_point_s);
537 center_lane_s_right->emplace_back(check_point_s);
538 left_lane_road_width->emplace_back(left_road_width);
539 right_lane_road_width->emplace_back(right_road_width);
540
541 check_point_s = check_point_s + config_.roi_line_segment_length_from_map();
542 }
543
544 size_t left_point_size = left_lane_boundary->size();
545 size_t right_point_size = right_lane_boundary->size();
546 ADEBUG << "right_road_boundary size: " << right_lane_boundary->size();
547 ADEBUG << "left_road_boundary size: " << left_lane_boundary->size();
548 for (size_t i = 0; i < left_point_size; i++) {
549 left_lane_boundary->at(i) -= origin_point;
550 left_lane_boundary->at(i).SelfRotate(-origin_heading);
551 ADEBUG << "left_road_boundary: [" << std::setprecision(9)
552 << left_lane_boundary->at(i).x() << ", "
553 << left_lane_boundary->at(i).y() << "]";
554 }
555 for (size_t i = 0; i < right_point_size; i++) {
556 right_lane_boundary->at(i) -= origin_point;
557 right_lane_boundary->at(i).SelfRotate(-origin_heading);
558 ADEBUG << "right_road_boundary: [" << std::setprecision(9)
559 << right_lane_boundary->at(i).x() << ", "
560 << right_lane_boundary->at(i).y() << "]";
561 }
562 if (!left_lane_boundary->empty()) {
563 sort(left_lane_boundary->begin(), left_lane_boundary->end(),
564 [](const Vec2d &first_pt, const Vec2d &second_pt) {
565 return first_pt.x() < second_pt.x() ||
566 (first_pt.x() == second_pt.x() &&
567 first_pt.y() < second_pt.y());
568 });
569 auto unique_end =
570 std::unique(left_lane_boundary->begin(), left_lane_boundary->end());
571 left_lane_boundary->erase(unique_end, left_lane_boundary->end());
572 }
573 if (!right_lane_boundary->empty()) {
574 sort(right_lane_boundary->begin(), right_lane_boundary->end(),
575 [](const Vec2d &first_pt, const Vec2d &second_pt) {
576 return first_pt.x() < second_pt.x() ||
577 (first_pt.x() == second_pt.x() &&
578 first_pt.y() < second_pt.y());
579 });
580 auto unique_end =
581 std::unique(right_lane_boundary->begin(), right_lane_boundary->end());
582 right_lane_boundary->erase(unique_end, right_lane_boundary->end());
583 }
584}
585
586void OpenSpaceRoiDecider::AddBoundaryKeyPoint(
587 const hdmap::Path &nearby_path, const double check_point_s,
588 const double start_s, const double end_s, const bool is_anchor_point,
589 const bool is_left_curb, std::vector<Vec2d> *center_lane_boundary,
590 std::vector<Vec2d> *curb_lane_boundary, std::vector<double> *center_lane_s,
591 std::vector<double> *road_width) {
592 // Check if current central-lane checking point's mapping on the left/right
593 // road boundary is a key point. The road boundary point is a key point if
594 // one of the following two confitions is satisfied:
595 // 1. the current central-lane point is an anchor point: (a start/end point
596 // or the point on path with large curvatures)
597 // 2. the point on the left/right lane boundary is close to a curb corner
598 // As indicated below:
599 // (#) Key Point Type 1: Lane anchor points
600 // (*) Key Point Type 2: Curb-corner points
601 // #
602 // Path Direction --> / / #
603 // Left Lane Boundary #--------------------------------# / /
604 // / /
605 // Center Lane - - - - - - - - - - - - - - - - - - / /
606 // /
607 // Right Lane Boundary #--------* *----------#
608 // \ /
609 // *-------------*
610
611 // road width changes slightly at the turning point of a path
612 // TODO(SHU): 1. consider distortion introduced by curvy road; 2. use both
613 // round boundaries for single-track road; 3. longitudinal range may not be
614 // symmetric
615 const double previous_distance_s =
616 std::min(config_.roi_line_segment_length(), check_point_s - start_s);
617 const double next_distance_s =
618 std::min(config_.roi_line_segment_length(), end_s - check_point_s);
619
620 hdmap::MapPathPoint current_check_point =
621 nearby_path.GetSmoothPoint(check_point_s);
622
623 double current_check_point_heading = current_check_point.heading();
624 double current_road_width =
625 is_left_curb ? nearby_path.GetRoadLeftWidth(check_point_s)
626 : nearby_path.GetRoadRightWidth(check_point_s);
627 // If the current center-lane checking point is an anchor point, then add
628 // current left/right curb boundary point as a key point
629 if (is_anchor_point) {
630 double point_vec_cos =
631 is_left_curb ? std::cos(current_check_point_heading + M_PI / 2.0)
632 : std::cos(current_check_point_heading - M_PI / 2.0);
633 double point_vec_sin =
634 is_left_curb ? std::sin(current_check_point_heading + M_PI / 2.0)
635 : std::sin(current_check_point_heading - M_PI / 2.0);
636 Vec2d curb_lane_point = Vec2d(current_road_width * point_vec_cos,
637 current_road_width * point_vec_sin);
638 curb_lane_point = curb_lane_point + current_check_point;
639 center_lane_boundary->push_back(current_check_point);
640 curb_lane_boundary->push_back(curb_lane_point);
641 center_lane_s->push_back(check_point_s);
642 road_width->push_back(current_road_width);
643 return;
644 }
645 double previous_road_width =
646 is_left_curb
647 ? nearby_path.GetRoadLeftWidth(check_point_s - previous_distance_s)
648 : nearby_path.GetRoadRightWidth(check_point_s - previous_distance_s);
649 double next_road_width =
650 is_left_curb
651 ? nearby_path.GetRoadLeftWidth(check_point_s + next_distance_s)
652 : nearby_path.GetRoadRightWidth(check_point_s + next_distance_s);
653 double previous_curb_segment_angle =
654 (current_road_width - previous_road_width) / previous_distance_s;
655 double next_segment_angle =
656 (next_road_width - current_road_width) / next_distance_s;
657 double current_curb_point_delta_theta =
658 next_segment_angle - previous_curb_segment_angle;
659 // If the delta angle between the previous curb segment and the next curb
660 // segment is large (near a curb corner), then add current curb_lane_point
661 // as a key point.
662 if (std::abs(current_curb_point_delta_theta) >
664 double point_vec_cos =
665 is_left_curb ? std::cos(current_check_point_heading + M_PI / 2.0)
666 : std::cos(current_check_point_heading - M_PI / 2.0);
667 double point_vec_sin =
668 is_left_curb ? std::sin(current_check_point_heading + M_PI / 2.0)
669 : std::sin(current_check_point_heading - M_PI / 2.0);
670 Vec2d curb_lane_point = Vec2d(current_road_width * point_vec_cos,
671 current_road_width * point_vec_sin);
672 curb_lane_point = curb_lane_point + current_check_point;
673 center_lane_boundary->push_back(current_check_point);
674 curb_lane_boundary->push_back(curb_lane_point);
675 center_lane_s->push_back(check_point_s);
676 road_width->push_back(current_road_width);
677 }
678}
679
680bool OpenSpaceRoiDecider::GetParkingBoundary(
681 const ParkingInfo &parking_info, const hdmap::Path &nearby_path,
682 Frame *const frame,
683 std::vector<std::vector<common::math::Vec2d>> *const roi_parking_boundary) {
684 auto left_top = parking_info.corner_points[0];
685 ADEBUG << std::fixed << "left_top: " << left_top.x() << ", " << left_top.y();
686 auto left_down = parking_info.corner_points[3];
687 ADEBUG << std::fixed << "left_down: " << left_down.x() << ", "
688 << left_down.y();
689 auto right_down = parking_info.corner_points[2];
690 ADEBUG << std::fixed << "right_down: " << right_down.x() << ", "
691 << right_down.y();
692 auto right_top = parking_info.corner_points[1];
693 ADEBUG << std::fixed << "right_top: " << right_top.x() << ", "
694 << right_top.y();
695
696 const auto &origin_point = frame->open_space_info().origin_point();
697 ADEBUG << std::fixed << "origin_point: " << origin_point.x() << ", "
698 << origin_point.y();
699 const auto &origin_heading = frame->open_space_info().origin_heading();
700
701 double left_top_s = 0.0;
702 double left_top_l = 0.0;
703 double right_top_s = 0.0;
704 double right_top_l = 0.0;
705 if (!(nearby_path.GetProjection(left_top, &left_top_s, &left_top_l) &&
706 nearby_path.GetProjection(right_top, &right_top_s, &right_top_l))) {
707 AERROR << "fail to get parking spot points' projections on reference line";
708 return false;
709 }
710
711 left_top -= origin_point;
712 left_top.SelfRotate(-origin_heading);
713 left_down -= origin_point;
714 left_down.SelfRotate(-origin_heading);
715 right_top -= origin_point;
716 right_top.SelfRotate(-origin_heading);
717 right_down -= origin_point;
718 right_down.SelfRotate(-origin_heading);
719
720 const double center_line_s = (left_top_s + right_top_s) / 2.0;
721 std::vector<Vec2d> left_lane_boundary;
722 std::vector<Vec2d> right_lane_boundary;
723 // The pivot points on the central lane, mapping with the key points on
724 // the left lane boundary.
725 std::vector<Vec2d> center_lane_boundary_left;
726 // The pivot points on the central lane, mapping with the key points on
727 // the right lane boundary.
728 std::vector<Vec2d> center_lane_boundary_right;
729 // The s-value for the anchor points on the center_lane_boundary_left.
730 std::vector<double> center_lane_s_left;
731 // The s-value for the anchor points on the center_lane_boundary_right.
732 std::vector<double> center_lane_s_right;
733 // The left-half road width between the pivot points on the
734 // center_lane_boundary_left and key points on the
735 // left_lane_boundary.
736 std::vector<double> left_lane_road_width;
737 // The right-half road width between the pivot points on the
738 // center_lane_boundary_right and key points on the
739 // right_lane_boundary.
740 std::vector<double> right_lane_road_width;
741
742 GetRoadBoundary(nearby_path, center_line_s, origin_point, origin_heading,
743 &left_lane_boundary, &right_lane_boundary,
744 &center_lane_boundary_left, &center_lane_boundary_right,
745 &center_lane_s_left, &center_lane_s_right,
746 &left_lane_road_width, &right_lane_road_width);
747
748 // If smaller than zero, the parking spot is on the right of the lane
749 // Left, right, down or opposite of the boundary is decided when viewing the
750 // parking spot upward
751 const double average_l = (left_top_l + right_top_l) / 2.0;
752 std::vector<Vec2d> boundary_points;
753
754 // TODO(jiaxuan): Write a half-boundary formation function and call it twice
755 // to avoid duplicated manipulations on the left and right sides
756 if (average_l < 0) {
757 // if average_l is lower than zero, the parking spot is on the right
758 // lane boundary and assume that the lane half width is average_l
759 ADEBUG << "average_l is less than 0 in OpenSpaceROI";
760 size_t point_size = right_lane_boundary.size();
761 for (size_t i = 0; i < point_size; i++) {
762 right_lane_boundary[i].SelfRotate(origin_heading);
763 right_lane_boundary[i] += origin_point;
764 right_lane_boundary[i] -= center_lane_boundary_right[i];
765 right_lane_boundary[i] /= right_lane_road_width[i];
766 right_lane_boundary[i] *= (-average_l);
767 right_lane_boundary[i] += center_lane_boundary_right[i];
768 right_lane_boundary[i] -= origin_point;
769 right_lane_boundary[i].SelfRotate(-origin_heading);
770 }
771
772 auto point_left_to_left_top_connor_s = std::lower_bound(
773 center_lane_s_right.begin(), center_lane_s_right.end(), left_top_s);
774 size_t point_left_to_left_top_connor_index = std::distance(
775 center_lane_s_right.begin(), point_left_to_left_top_connor_s);
776 point_left_to_left_top_connor_index =
777 point_left_to_left_top_connor_index == 0
778 ? point_left_to_left_top_connor_index
779 : point_left_to_left_top_connor_index - 1;
780 auto point_left_to_left_top_connor_itr =
781 right_lane_boundary.begin() + point_left_to_left_top_connor_index;
782 auto point_right_to_right_top_connor_s = std::upper_bound(
783 center_lane_s_right.begin(), center_lane_s_right.end(), right_top_s);
784 size_t point_right_to_right_top_connor_index = std::distance(
785 center_lane_s_right.begin(), point_right_to_right_top_connor_s);
786 auto point_right_to_right_top_connor_itr =
787 right_lane_boundary.begin() + point_right_to_right_top_connor_index;
788
789 std::copy(right_lane_boundary.begin(), point_left_to_left_top_connor_itr,
790 std::back_inserter(boundary_points));
791
792 std::vector<Vec2d> parking_spot_boundary{left_top, left_down, right_down,
793 right_top};
794
795 std::copy(parking_spot_boundary.begin(), parking_spot_boundary.end(),
796 std::back_inserter(boundary_points));
797
798 std::copy(point_right_to_right_top_connor_itr, right_lane_boundary.end(),
799 std::back_inserter(boundary_points));
800
801 std::reverse_copy(left_lane_boundary.begin(), left_lane_boundary.end(),
802 std::back_inserter(boundary_points));
803
804 // reinsert the initial point to the back to from closed loop
805 boundary_points.push_back(right_lane_boundary.front());
806
807 // disassemble line into line2d segments
808 for (size_t i = 0; i < point_left_to_left_top_connor_index; i++) {
809 std::vector<Vec2d> segment{right_lane_boundary[i],
810 right_lane_boundary[i + 1]};
811 roi_parking_boundary->push_back(segment);
812 }
813
814 std::vector<Vec2d> left_stitching_segment{
815 right_lane_boundary[point_left_to_left_top_connor_index], left_top};
816 roi_parking_boundary->push_back(left_stitching_segment);
817
818 std::vector<Vec2d> left_parking_spot_segment{left_top, left_down};
819 std::vector<Vec2d> down_parking_spot_segment{left_down, right_down};
820 std::vector<Vec2d> right_parking_spot_segment{right_down, right_top};
821 roi_parking_boundary->push_back(left_parking_spot_segment);
822 roi_parking_boundary->push_back(down_parking_spot_segment);
823 roi_parking_boundary->push_back(right_parking_spot_segment);
824
825 std::vector<Vec2d> right_stitching_segment{
826 right_top, right_lane_boundary[point_right_to_right_top_connor_index]};
827 roi_parking_boundary->push_back(right_stitching_segment);
828
829 size_t right_lane_boundary_last_index = right_lane_boundary.size() - 1;
830 for (size_t i = point_right_to_right_top_connor_index;
831 i < right_lane_boundary_last_index; i++) {
832 std::vector<Vec2d> segment{right_lane_boundary[i],
833 right_lane_boundary[i + 1]};
834 roi_parking_boundary->push_back(segment);
835 }
836
837 size_t left_lane_boundary_last_index = left_lane_boundary.size() - 1;
838 for (size_t i = left_lane_boundary_last_index; i > 0; i--) {
839 std::vector<Vec2d> segment{left_lane_boundary[i],
840 left_lane_boundary[i - 1]};
841 roi_parking_boundary->push_back(segment);
842 }
843
844 } else {
845 // if average_l is higher than zero, the parking spot is on the left
846 // lane boundary and assume that the lane half width is average_l
847 ADEBUG << "average_l is greater than 0 in OpenSpaceROI";
848 size_t point_size = left_lane_boundary.size();
849 for (size_t i = 0; i < point_size; i++) {
850 left_lane_boundary[i].SelfRotate(origin_heading);
851 left_lane_boundary[i] += origin_point;
852 left_lane_boundary[i] -= center_lane_boundary_left[i];
853 left_lane_boundary[i] /= left_lane_road_width[i];
854 left_lane_boundary[i] *= average_l;
855 left_lane_boundary[i] += center_lane_boundary_left[i];
856 left_lane_boundary[i] -= origin_point;
857 left_lane_boundary[i].SelfRotate(-origin_heading);
858 ADEBUG << "left_lane_boundary[" << i << "]: " << left_lane_boundary[i].x()
859 << ", " << left_lane_boundary[i].y();
860 }
861
862 auto point_right_to_right_top_connor_s = std::lower_bound(
863 center_lane_s_left.begin(), center_lane_s_left.end(), right_top_s);
864 size_t point_right_to_right_top_connor_index = std::distance(
865 center_lane_s_left.begin(), point_right_to_right_top_connor_s);
866
867 auto point_right_to_right_top_connor_itr =
868 left_lane_boundary.begin() + point_right_to_right_top_connor_index;
869
870 auto point_left_to_left_top_connor_s = std::upper_bound(
871 center_lane_s_left.begin(), center_lane_s_left.end(), left_top_s);
872 size_t point_left_to_left_top_connor_index = std::distance(
873 center_lane_s_left.begin(), point_left_to_left_top_connor_s);
874 point_left_to_left_top_connor_index =
875 point_left_to_left_top_connor_index == 0
876 ? point_left_to_left_top_connor_index
877 : point_left_to_left_top_connor_index - 1;
878 auto point_left_to_left_top_connor_itr =
879 left_lane_boundary.begin() + point_left_to_left_top_connor_index;
880
881 std::copy(right_lane_boundary.begin(), right_lane_boundary.end(),
882 std::back_inserter(boundary_points));
883
884 std::reverse_copy(point_left_to_left_top_connor_itr,
885 left_lane_boundary.end(),
886 std::back_inserter(boundary_points));
887
888 std::vector<Vec2d> parking_spot_boundary{left_top, left_down, right_down,
889 right_top};
890 std::copy(parking_spot_boundary.begin(), parking_spot_boundary.end(),
891 std::back_inserter(boundary_points));
892
893 std::reverse_copy(left_lane_boundary.begin(),
894 point_right_to_right_top_connor_itr,
895 std::back_inserter(boundary_points));
896
897 // reinsert the initial point to the back to from closed loop
898 boundary_points.push_back(right_lane_boundary.front());
899
900 // disassemble line into line2d segments
901 size_t right_lane_boundary_last_index = right_lane_boundary.size() - 1;
902 for (size_t i = 0; i < right_lane_boundary_last_index; i++) {
903 std::vector<Vec2d> segment{right_lane_boundary[i],
904 right_lane_boundary[i + 1]};
905 roi_parking_boundary->push_back(segment);
906 }
907
908 size_t left_lane_boundary_last_index = left_lane_boundary.size() - 1;
909 for (size_t i = left_lane_boundary_last_index;
910 i > point_right_to_right_top_connor_index; i--) {
911 std::vector<Vec2d> segment{left_lane_boundary[i],
912 left_lane_boundary[i - 1]};
913 roi_parking_boundary->push_back(segment);
914 }
915
916 std::vector<Vec2d> left_stitching_segment{
917 left_lane_boundary[point_right_to_right_top_connor_index], right_top};
918 roi_parking_boundary->push_back(left_stitching_segment);
919
920 std::vector<Vec2d> right_parking_spot_segment{right_top, right_down};
921 std::vector<Vec2d> down_parking_spot_segment{right_down, left_down};
922 std::vector<Vec2d> left_parking_spot_segment{left_down, left_top};
923 roi_parking_boundary->push_back(right_parking_spot_segment);
924 roi_parking_boundary->push_back(down_parking_spot_segment);
925 roi_parking_boundary->push_back(left_parking_spot_segment);
926
927 std::vector<Vec2d> right_stitching_segment{
928 left_top, left_lane_boundary[point_left_to_left_top_connor_index]};
929 roi_parking_boundary->push_back(right_stitching_segment);
930
931 for (size_t i = point_left_to_left_top_connor_index; i > 0; --i) {
932 std::vector<Vec2d> segment{left_lane_boundary[i],
933 left_lane_boundary[i - 1]};
934 roi_parking_boundary->push_back(segment);
935 }
936 }
937
938 // Fuse line segments into convex contraints
939 if (!FuseLineSegments(roi_parking_boundary)) {
940 AERROR << "FuseLineSegments failed in parking ROI";
941 return false;
942 }
943 // Get xy boundary
944 auto xminmax = std::minmax_element(
945 boundary_points.begin(), boundary_points.end(),
946 [](const Vec2d &a, const Vec2d &b) { return a.x() < b.x(); });
947 auto yminmax = std::minmax_element(
948 boundary_points.begin(), boundary_points.end(),
949 [](const Vec2d &a, const Vec2d &b) { return a.y() < b.y(); });
950 std::vector<double> ROI_xy_boundary{xminmax.first->x(), xminmax.second->x(),
951 yminmax.first->y(), yminmax.second->y()};
952 auto *xy_boundary =
953 frame->mutable_open_space_info()->mutable_ROI_xy_boundary();
954 xy_boundary->assign(ROI_xy_boundary.begin(), ROI_xy_boundary.end());
955
956 Vec2d vehicle_xy = Vec2d(vehicle_state_.x(), vehicle_state_.y());
957 vehicle_xy -= origin_point;
958 vehicle_xy.SelfRotate(-origin_heading);
959 if (vehicle_xy.x() < ROI_xy_boundary[0] ||
960 vehicle_xy.x() > ROI_xy_boundary[1] ||
961 vehicle_xy.y() < ROI_xy_boundary[2] ||
962 vehicle_xy.y() > ROI_xy_boundary[3]) {
963 AERROR << "vehicle outside of xy boundary of parking ROI";
964 return false;
965 }
966 return true;
967}
968
969bool OpenSpaceRoiDecider::GetPullOverBoundary(
970 Frame *const frame, const std::array<common::math::Vec2d, 4> &vertices,
971 const hdmap::Path &nearby_path,
972 std::vector<std::vector<common::math::Vec2d>> *const roi_parking_boundary) {
973 auto left_top = vertices[0];
974 auto left_down = vertices[1];
975 auto right_down = vertices[2];
976 auto right_top = vertices[3];
977
978 const auto &origin_point = frame->open_space_info().origin_point();
979 const auto &origin_heading = frame->open_space_info().origin_heading();
980
981 double left_top_s = 0.0;
982 double left_top_l = 0.0;
983 double right_top_s = 0.0;
984 double right_top_l = 0.0;
985 if (!(nearby_path.GetProjection(left_top, &left_top_s, &left_top_l) &&
986 nearby_path.GetProjection(right_top, &right_top_s, &right_top_l))) {
987 AERROR << "fail to get parking spot points' projections on reference line";
988 return false;
989 }
990
991 left_top -= origin_point;
992 left_top.SelfRotate(-origin_heading);
993 left_down -= origin_point;
994 left_down.SelfRotate(-origin_heading);
995 right_top -= origin_point;
996 right_top.SelfRotate(-origin_heading);
997 right_down -= origin_point;
998 right_down.SelfRotate(-origin_heading);
999
1000 const double center_line_s = (left_top_s + right_top_s) / 2.0;
1001 std::vector<Vec2d> left_lane_boundary;
1002 std::vector<Vec2d> right_lane_boundary;
1003 std::vector<Vec2d> center_lane_boundary_left;
1004 std::vector<Vec2d> center_lane_boundary_right;
1005 std::vector<double> center_lane_s_left;
1006 std::vector<double> center_lane_s_right;
1007 std::vector<double> left_lane_road_width;
1008 std::vector<double> right_lane_road_width;
1009
1010 GetRoadBoundary(nearby_path, center_line_s, origin_point, origin_heading,
1011 &left_lane_boundary, &right_lane_boundary,
1012 &center_lane_boundary_left, &center_lane_boundary_right,
1013 &center_lane_s_left, &center_lane_s_right,
1014 &left_lane_road_width, &right_lane_road_width);
1015
1016 // Load boundary as line segments in counter-clockwise order
1017 std::reverse(left_lane_boundary.begin(), left_lane_boundary.end());
1018
1019 std::vector<Vec2d> boundary_points;
1020 std::copy(right_lane_boundary.begin(), right_lane_boundary.end(),
1021 std::back_inserter(boundary_points));
1022 std::copy(left_lane_boundary.begin(), left_lane_boundary.end(),
1023 std::back_inserter(boundary_points));
1024
1025 size_t right_lane_boundary_last_index = right_lane_boundary.size() - 1;
1026 for (size_t i = 0; i < right_lane_boundary_last_index; i++) {
1027 std::vector<Vec2d> segment{right_lane_boundary[i],
1028 right_lane_boundary[i + 1]};
1029 roi_parking_boundary->push_back(segment);
1030 }
1031
1032 size_t left_lane_boundary_last_index = left_lane_boundary.size() - 1;
1033 for (size_t i = left_lane_boundary_last_index; i > 0; i--) {
1034 std::vector<Vec2d> segment{left_lane_boundary[i],
1035 left_lane_boundary[i - 1]};
1036 roi_parking_boundary->push_back(segment);
1037 }
1038
1039 // Fuse line segments into convex contraints
1040 if (!FuseLineSegments(roi_parking_boundary)) {
1041 return false;
1042 }
1043 // Get xy boundary
1044 auto xminmax = std::minmax_element(
1045 boundary_points.begin(), boundary_points.end(),
1046 [](const Vec2d &a, const Vec2d &b) { return a.x() < b.x(); });
1047 auto yminmax = std::minmax_element(
1048 boundary_points.begin(), boundary_points.end(),
1049 [](const Vec2d &a, const Vec2d &b) { return a.y() < b.y(); });
1050 std::vector<double> ROI_xy_boundary{xminmax.first->x(), xminmax.second->x(),
1051 yminmax.first->y(), yminmax.second->y()};
1052 auto *xy_boundary =
1053 frame->mutable_open_space_info()->mutable_ROI_xy_boundary();
1054 xy_boundary->assign(ROI_xy_boundary.begin(), ROI_xy_boundary.end());
1055
1056 Vec2d vehicle_xy = Vec2d(vehicle_state_.x(), vehicle_state_.y());
1057 vehicle_xy -= origin_point;
1058 vehicle_xy.SelfRotate(-origin_heading);
1059 if (vehicle_xy.x() < ROI_xy_boundary[0] ||
1060 vehicle_xy.x() > ROI_xy_boundary[1] ||
1061 vehicle_xy.y() < ROI_xy_boundary[2] ||
1062 vehicle_xy.y() > ROI_xy_boundary[3]) {
1063 AERROR << "vehicle outside of xy boundary of parking ROI";
1064 return false;
1065 }
1066 return true;
1067}
1068
1069bool OpenSpaceRoiDecider::GetParkAndGoBoundary(
1070 Frame *const frame, const hdmap::Path &nearby_path,
1071 std::vector<std::vector<common::math::Vec2d>> *const roi_parking_boundary) {
1072 const auto &park_and_go_status =
1073 injector_->planning_context()->planning_status().park_and_go();
1074 const double adc_init_x = park_and_go_status.adc_init_position().x();
1075 const double adc_init_y = park_and_go_status.adc_init_position().y();
1076 const double adc_init_heading = park_and_go_status.adc_init_heading();
1077 common::math::Vec2d adc_init_position = {adc_init_x, adc_init_y};
1078 const double adc_length = vehicle_params_.length();
1079 const double adc_width = vehicle_params_.width();
1080 // ADC box
1081 Box2d adc_box(adc_init_position, adc_init_heading, adc_length, adc_width);
1082 // get vertices from ADC box
1083 std::vector<common::math::Vec2d> adc_corners;
1084 adc_box.GetAllCorners(&adc_corners);
1085 auto left_top = adc_corners[1];
1086 auto right_top = adc_corners[0];
1087
1088 const auto &origin_point = frame->open_space_info().origin_point();
1089 const auto &origin_heading = frame->open_space_info().origin_heading();
1090
1091 double left_top_s = 0.0;
1092 double left_top_l = 0.0;
1093 double right_top_s = 0.0;
1094 double right_top_l = 0.0;
1095 if (!(nearby_path.GetProjection(left_top, &left_top_s, &left_top_l) &&
1096 nearby_path.GetProjection(right_top, &right_top_s, &right_top_l))) {
1097 AERROR << "fail to get parking spot points' projections on reference line";
1098 return false;
1099 }
1100 left_top -= origin_point;
1101 left_top.SelfRotate(-origin_heading);
1102 right_top -= origin_point;
1103 right_top.SelfRotate(-origin_heading);
1104
1105 const double center_line_s = (left_top_s + right_top_s) / 2.0;
1106 std::vector<Vec2d> left_lane_boundary;
1107 std::vector<Vec2d> right_lane_boundary;
1108 std::vector<Vec2d> center_lane_boundary_left;
1109 std::vector<Vec2d> center_lane_boundary_right;
1110 std::vector<double> center_lane_s_left;
1111 std::vector<double> center_lane_s_right;
1112 std::vector<double> left_lane_road_width;
1113 std::vector<double> right_lane_road_width;
1114
1115 if (config_.use_road_boundary_from_map()) {
1116 GetRoadBoundaryFromMap(
1117 nearby_path, center_line_s, origin_point, origin_heading,
1118 &left_lane_boundary, &right_lane_boundary, &center_lane_boundary_left,
1119 &center_lane_boundary_right, &center_lane_s_left, &center_lane_s_right,
1120 &left_lane_road_width, &right_lane_road_width);
1121 } else {
1122 GetRoadBoundary(nearby_path, center_line_s, origin_point, origin_heading,
1123 &left_lane_boundary, &right_lane_boundary,
1124 &center_lane_boundary_left, &center_lane_boundary_right,
1125 &center_lane_s_left, &center_lane_s_right,
1126 &left_lane_road_width, &right_lane_road_width);
1127 }
1128
1129 // Load boundary as line segments in counter-clockwise order
1130 std::reverse(left_lane_boundary.begin(), left_lane_boundary.end());
1131
1132 std::vector<Vec2d> boundary_points;
1133 std::copy(right_lane_boundary.begin(), right_lane_boundary.end(),
1134 std::back_inserter(boundary_points));
1135 std::copy(left_lane_boundary.begin(), left_lane_boundary.end(),
1136 std::back_inserter(boundary_points));
1137
1138 size_t right_lane_boundary_last_index = right_lane_boundary.size() - 1;
1139 for (size_t i = 0; i < right_lane_boundary_last_index; i++) {
1140 std::vector<Vec2d> segment{right_lane_boundary[i],
1141 right_lane_boundary[i + 1]};
1142 ADEBUG << "right segment";
1143 ADEBUG << "right_road_boundary: [" << std::setprecision(9)
1144 << right_lane_boundary[i].x() << ", " << right_lane_boundary[i].y()
1145 << "]";
1146 ADEBUG << "right_road_boundary: [" << std::setprecision(9)
1147 << right_lane_boundary[i + 1].x() << ", "
1148 << right_lane_boundary[i + 1].y() << "]";
1149 roi_parking_boundary->push_back(segment);
1150 }
1151
1152 size_t left_lane_boundary_last_index = left_lane_boundary.size() - 1;
1153 for (size_t i = left_lane_boundary_last_index; i > 0; i--) {
1154 std::vector<Vec2d> segment{left_lane_boundary[i],
1155 left_lane_boundary[i - 1]};
1156 roi_parking_boundary->push_back(segment);
1157 }
1158
1159 PrintCurves print_curves;
1160 for (auto it : *roi_parking_boundary) {
1161 for (auto pt : it) {
1162 pt.SelfRotate(origin_heading);
1163 pt += origin_point;
1164 print_curves.AddPoint("roi_parking_boundary", pt);
1165 }
1166 }
1167 print_curves.PrintToLog();
1168
1169 ADEBUG << "roi_parking_boundary size: [" << roi_parking_boundary->size()
1170 << "]";
1171
1172 // Fuse line segments into convex contraints
1173 if (!FuseLineSegments(roi_parking_boundary)) {
1174 return false;
1175 }
1176
1177 ADEBUG << "roi_parking_boundary size: [" << roi_parking_boundary->size()
1178 << "]";
1179 // Get xy boundary
1180 auto xminmax = std::minmax_element(
1181 boundary_points.begin(), boundary_points.end(),
1182 [](const Vec2d &a, const Vec2d &b) { return a.x() < b.x(); });
1183 auto yminmax = std::minmax_element(
1184 boundary_points.begin(), boundary_points.end(),
1185 [](const Vec2d &a, const Vec2d &b) { return a.y() < b.y(); });
1186 std::vector<double> ROI_xy_boundary{xminmax.first->x(), xminmax.second->x(),
1187 yminmax.first->y(), yminmax.second->y()};
1188 auto *xy_boundary =
1189 frame->mutable_open_space_info()->mutable_ROI_xy_boundary();
1190 xy_boundary->assign(ROI_xy_boundary.begin(), ROI_xy_boundary.end());
1191
1192 Vec2d vehicle_xy = Vec2d(vehicle_state_.x(), vehicle_state_.y());
1193 vehicle_xy -= origin_point;
1194 vehicle_xy.SelfRotate(-origin_heading);
1195 if (vehicle_xy.x() < ROI_xy_boundary[0] ||
1196 vehicle_xy.x() > ROI_xy_boundary[1] ||
1197 vehicle_xy.y() < ROI_xy_boundary[2] ||
1198 vehicle_xy.y() > ROI_xy_boundary[3]) {
1199 AERROR << "vehicle outside of xy boundary of parking ROI";
1200 return false;
1201 }
1202 return true;
1203}
1204
1205bool OpenSpaceRoiDecider::GetParkingSpot(Frame *const frame,
1206 ParkingInfo *parking_info) {
1207 if (frame == nullptr) {
1208 AERROR << "Invalid frame, fail to GetParkingSpotFromMap from frame. ";
1209 return false;
1210 }
1211 const auto &parking_spot_id_string =
1212 frame->open_space_info().target_parking_spot_id();
1213 hdmap::Id parking_spot_id = hdmap::MakeMapId(parking_spot_id_string);
1214 auto parking_spot = hdmap_->GetParkingSpaceById(parking_spot_id);
1215 if (!nearby_path_) {
1216 GetNearbyPath(frame->local_view().planning_command->lane_follow_command(),
1217 parking_spot, &nearby_path_);
1218 }
1219 // points in polygon is always clockwise
1220 auto points = parking_spot->polygon().points();
1221 OpenSpaceRoiUtil::UpdateParkingPointsOrder(*nearby_path_, &points);
1222 Vec2d center_point(0, 0);
1223 for (size_t i = 0; i < points.size(); i++) {
1224 center_point += points[i];
1225 }
1226 center_point /= 4.0;
1227 double lane_heading = 0;
1228 parking_info->center_point = center_point;
1229 nearby_path_->GetHeadingAlongPath(center_point, &lane_heading);
1230 double s, l;
1231 nearby_path_->GetProjection(center_point, &s, &l);
1232 if (l > 0) {
1233 parking_info->is_on_left = true;
1234 std::swap(points[1], points[3]);
1235 } else {
1236 parking_info->is_on_left = false;
1237 }
1238 double diff_angle = common::math::AngleDiff(
1239 lane_heading, parking_spot->parking_space().heading());
1240 if (std::fabs(diff_angle) < M_PI / 3.0) {
1241 parking_info->parking_type = ParkingType::PARALLEL_PARKING;
1242 } else {
1243 parking_info->parking_type = ParkingType::VERTICAL_PARKING;
1244 }
1245 parking_info->corner_points = points;
1246 double parallel_dist =
1247 parking_info->corner_points[0].DistanceTo(parking_info->corner_points[1]);
1248 double verticle_dist =
1249 parking_info->corner_points[0].DistanceTo(parking_info->corner_points[3]);
1250 if (parallel_dist > verticle_dist) {
1251 parking_info->parking_type = ParkingType::PARALLEL_PARKING;
1252 } else {
1253 parking_info->parking_type = ParkingType::VERTICAL_PARKING;
1254 }
1255 return true;
1256}
1257
1258bool OpenSpaceRoiDecider::GetPullOverSpot(
1259 Frame *const frame, std::array<common::math::Vec2d, 4> *vertices,
1260 hdmap::Path *nearby_path) {
1261 const auto &pull_over_status =
1262 injector_->planning_context()->planning_status().pull_over();
1263 if (!pull_over_status.has_position() ||
1264 !pull_over_status.position().has_x() ||
1265 !pull_over_status.position().has_y() || !pull_over_status.has_theta()) {
1266 AERROR << "Pull over position not set in planning context";
1267 return false;
1268 }
1269
1270 if (frame->reference_line_info().size() > 1) {
1271 AERROR << "Should not be in pull over when changing lane in open space "
1272 "planning";
1273 return false;
1274 }
1275
1276 *nearby_path =
1277 frame->reference_line_info().front().reference_line().GetMapPath();
1278
1279 // Construct left_top, left_down, right_down, right_top points
1280 double pull_over_x = pull_over_status.position().x();
1281 double pull_over_y = pull_over_status.position().y();
1282 const double pull_over_theta = pull_over_status.theta();
1283 const double pull_over_length_front = pull_over_status.length_front();
1284 const double pull_over_length_back = pull_over_status.length_back();
1285 const double pull_over_width_left = pull_over_status.width_left();
1286 const double pull_over_width_right = pull_over_status.width_right();
1287
1288 Vec2d center_shift_vec((pull_over_length_front - pull_over_length_back) * 0.5,
1289 (pull_over_width_left - pull_over_width_right) * 0.5);
1290 center_shift_vec.SelfRotate(pull_over_theta);
1291 pull_over_x += center_shift_vec.x();
1292 pull_over_y += center_shift_vec.y();
1293
1294 const double half_length =
1295 (pull_over_length_front + pull_over_length_back) / 2.0;
1296 const double half_width =
1297 (pull_over_width_left + pull_over_width_right) / 2.0;
1298
1299 const double cos_heading = std::cos(pull_over_theta);
1300 const double sin_heading = std::sin(pull_over_theta);
1301
1302 const double dx1 = cos_heading * half_length;
1303 const double dy1 = sin_heading * half_length;
1304 const double dx2 = sin_heading * half_width;
1305 const double dy2 = -cos_heading * half_width;
1306
1307 Vec2d left_top(pull_over_x - dx1 + dx2, pull_over_y - dy1 + dy2);
1308 Vec2d left_down(pull_over_x - dx1 - dx2, pull_over_y - dy1 - dy2);
1309 Vec2d right_down(pull_over_x + dx1 - dx2, pull_over_y + dy1 - dy2);
1310 Vec2d right_top(pull_over_x + dx1 + dx2, pull_over_y + dy1 + dy2);
1311
1312 std::array<Vec2d, 4> pull_over_vertices{left_top, left_down, right_down,
1313 right_top};
1314 *vertices = std::move(pull_over_vertices);
1315
1316 return true;
1317}
1318
1319void OpenSpaceRoiDecider::SearchTargetParkingSpotOnPath(
1320 const hdmap::Path &nearby_path,
1321 ParkingSpaceInfoConstPtr *target_parking_spot) {
1322 const auto &parking_space_overlaps = nearby_path.parking_space_overlaps();
1323 for (const auto &parking_overlap : parking_space_overlaps) {
1324 if (parking_overlap.object_id == target_parking_spot_id_) {
1325 hdmap::Id id;
1326 id.set_id(parking_overlap.object_id);
1327 *target_parking_spot = hdmap_->GetParkingSpaceById(id);
1328 }
1329 }
1330}
1331
1332bool OpenSpaceRoiDecider::FuseLineSegments(
1333 std::vector<std::vector<common::math::Vec2d>> *line_segments_vec) {
1334 static constexpr double kEpsilon = 1.0e-8;
1335 auto cur_segment = line_segments_vec->begin();
1336 while (cur_segment != line_segments_vec->end() - 1) {
1337 auto next_segment = cur_segment + 1;
1338 auto cur_last_point = cur_segment->back();
1339 auto next_first_point = next_segment->front();
1340 // Check if they are the same points
1341 if (cur_last_point.DistanceTo(next_first_point) > kEpsilon) {
1342 ++cur_segment;
1343 continue;
1344 }
1345 if (cur_segment->size() < 2 || next_segment->size() < 2) {
1346 AERROR << "Single point line_segments vec not expected";
1347 return false;
1348 }
1349 size_t cur_segments_size = cur_segment->size();
1350 auto cur_second_to_last_point = cur_segment->at(cur_segments_size - 2);
1351 auto next_second_point = next_segment->at(1);
1352 if (CrossProd(cur_second_to_last_point, cur_last_point, next_second_point) <
1353 0.0) {
1354 cur_segment->push_back(next_second_point);
1355 next_segment->erase(next_segment->begin(), next_segment->begin() + 2);
1356 if (next_segment->empty()) {
1357 line_segments_vec->erase(next_segment);
1358 }
1359 } else {
1360 ++cur_segment;
1361 }
1362 }
1363 return true;
1364}
1365
1366bool OpenSpaceRoiDecider::FormulateBoundaryConstraints(
1367 const std::vector<std::vector<common::math::Vec2d>> &roi_parking_boundary,
1368 Frame *const frame) {
1369 // Gather vertice needed by warm start and distance approach
1370 if (!LoadObstacleInVertices(roi_parking_boundary, frame)) {
1371 AERROR << "fail at LoadObstacleInVertices()";
1372 return false;
1373 }
1374 // Transform vertices into the form of Ax>b
1375 if (!LoadObstacleInHyperPlanes(frame)) {
1376 AERROR << "fail at LoadObstacleInHyperPlanes()";
1377 return false;
1378 }
1379 return true;
1380}
1381
1382bool OpenSpaceRoiDecider::LoadObstacleInVertices(
1383 const std::vector<std::vector<common::math::Vec2d>> &roi_parking_boundary,
1384 Frame *const frame) {
1385 auto *mutable_open_space_info = frame->mutable_open_space_info();
1386 const auto &open_space_info = frame->open_space_info();
1387 auto *obstacles_vertices_vec =
1388 mutable_open_space_info->mutable_obstacles_vertices_vec();
1389 auto *obstacles_edges_num_vec =
1390 mutable_open_space_info->mutable_obstacles_edges_num();
1391
1392 // load vertices for parking boundary (not need to repeat the first
1393 // vertice to get close hull)
1394 size_t parking_boundaries_num = roi_parking_boundary.size();
1395 size_t perception_obstacles_num = 0;
1396
1397 for (size_t i = 0; i < parking_boundaries_num; ++i) {
1398 obstacles_vertices_vec->push_back(roi_parking_boundary[i]);
1399 }
1400
1401 Eigen::MatrixXi parking_boundaries_obstacles_edges_num(parking_boundaries_num,
1402 1);
1403 for (size_t i = 0; i < parking_boundaries_num; i++) {
1404 if (roi_parking_boundary[i].size() <= 1U) {
1405 AERROR << "Roi parking boundary is invalid: "
1406 << roi_parking_boundary[i].size();
1407 return false;
1408 }
1409 parking_boundaries_obstacles_edges_num(i, 0) =
1410 static_cast<int>(roi_parking_boundary[i].size()) - 1;
1411 }
1412
1413 if (config_.enable_perception_obstacles()) {
1414 if (perception_obstacles_num == 0) {
1415 ADEBUG << "no obstacle given by perception";
1416 }
1417
1418 // load vertices for perception obstacles(repeat the first vertice at the
1419 // last to form closed convex hull)
1420 const auto &origin_point = open_space_info.origin_point();
1421 const auto &origin_heading = open_space_info.origin_heading();
1422 for (const auto &obstacle : obstacles_by_frame_->Items()) {
1423 if (FilterOutObstacle(*frame, *obstacle)) {
1424 continue;
1425 }
1426 ++perception_obstacles_num;
1427
1428 std::vector<Vec2d> vertices_ccw;
1430 common::math::Polygon2d original_polygon =
1431 obstacle->PerceptionPolygon();
1432 original_polygon.ExpandByDistance(config_.perception_obstacle_buffer());
1433 original_polygon.CalculateVertices(-1.0 * origin_point);
1434 vertices_ccw = original_polygon.GetAllVertices();
1435 } else {
1436 Box2d original_box = obstacle->PerceptionBoundingBox();
1437 original_box.Shift(-1.0 * origin_point);
1438 original_box.LongitudinalExtend(config_.perception_obstacle_buffer());
1439 original_box.LateralExtend(config_.perception_obstacle_buffer());
1440 vertices_ccw = original_box.GetAllCorners();
1441 }
1442
1443 // TODO(Jinyun): Check correctness of ExpandByDistance() in polygon
1444 // Polygon2d buffered_box(original_box);
1445 // buffered_box = buffered_box.ExpandByDistance(
1446 // config_.perception_obstacle_buffer());
1447 // TODO(Runxin): Rotate from origin instead
1448 // original_box.RotateFromCenter(-1.0 * origin_heading);
1449
1450 std::vector<Vec2d> vertices_cw;
1451 while (!vertices_ccw.empty()) {
1452 auto current_corner_pt = vertices_ccw.back();
1453 current_corner_pt.SelfRotate(-1.0 * origin_heading);
1454 vertices_cw.push_back(current_corner_pt);
1455 vertices_ccw.pop_back();
1456 }
1457 // As the perception obstacle is a closed convex set, the first vertice
1458 // is repeated at the end of the vector to help transform all four edges
1459 // to inequality constraint
1460 vertices_cw.push_back(vertices_cw.front());
1461 obstacles_vertices_vec->push_back(vertices_cw);
1462 }
1463
1464 // obstacle boundary box is used, thus the edges are set to be 4
1465 Eigen::MatrixXi perception_obstacles_edges_num =
1466 4 * Eigen::MatrixXi::Ones(perception_obstacles_num, 1);
1467
1468 obstacles_edges_num_vec->resize(
1469 parking_boundaries_obstacles_edges_num.rows() +
1470 perception_obstacles_edges_num.rows(),
1471 1);
1472 *(obstacles_edges_num_vec) << parking_boundaries_obstacles_edges_num,
1473 perception_obstacles_edges_num;
1474
1475 } else {
1476 obstacles_edges_num_vec->resize(
1477 parking_boundaries_obstacles_edges_num.rows(), 1);
1478 *(obstacles_edges_num_vec) << parking_boundaries_obstacles_edges_num;
1479 }
1480
1481 mutable_open_space_info->set_obstacles_num(parking_boundaries_num +
1482 perception_obstacles_num);
1483 return true;
1484}
1485
1486bool OpenSpaceRoiDecider::FilterOutObstacle(const Frame &frame,
1487 const Obstacle &obstacle) {
1488 if (obstacle.IsVirtual() || !obstacle.IsStatic()) {
1489 return true;
1490 }
1491
1492 const auto &open_space_info = frame.open_space_info();
1493 const auto &origin_point = open_space_info.origin_point();
1494 const auto &origin_heading = open_space_info.origin_heading();
1495 const auto &obstacle_box = obstacle.PerceptionBoundingBox();
1496 auto obstacle_center_xy = obstacle_box.center();
1497
1498 // xy_boundary in xmin, xmax, ymin, ymax.
1499 const auto &roi_xy_boundary = open_space_info.ROI_xy_boundary();
1500 obstacle_center_xy -= origin_point;
1501 obstacle_center_xy.SelfRotate(-origin_heading);
1502 if (obstacle_center_xy.x() < roi_xy_boundary[0] ||
1503 obstacle_center_xy.x() > roi_xy_boundary[1] ||
1504 obstacle_center_xy.y() < roi_xy_boundary[2] ||
1505 obstacle_center_xy.y() > roi_xy_boundary[3]) {
1506 return true;
1507 }
1508
1509 // Translate the end pose back to world frame with endpose in x, y, phi, v
1510 const auto &end_pose = open_space_info.open_space_end_pose();
1511 Vec2d end_pose_x_y(end_pose[0], end_pose[1]);
1512 end_pose_x_y.SelfRotate(origin_heading);
1513 end_pose_x_y += origin_point;
1514
1515 // Get vehicle state
1516 Vec2d vehicle_x_y(vehicle_state_.x(), vehicle_state_.y());
1517
1518 // Use vehicle position and end position to filter out obstacle
1519 const double vehicle_center_to_obstacle =
1520 obstacle_box.DistanceTo(vehicle_x_y);
1521 const double end_pose_center_to_obstacle =
1522 obstacle_box.DistanceTo(end_pose_x_y);
1523 const double filtering_distance =
1525 if (vehicle_center_to_obstacle > filtering_distance &&
1526 end_pose_center_to_obstacle > filtering_distance) {
1527 return true;
1528 }
1529 return false;
1530}
1531
1532bool OpenSpaceRoiDecider::LoadObstacleInHyperPlanes(Frame *const frame) {
1533 *(frame->mutable_open_space_info()->mutable_obstacles_A()) =
1534 Eigen::MatrixXd::Zero(
1535 frame->open_space_info().obstacles_edges_num().sum(), 2);
1536 *(frame->mutable_open_space_info()->mutable_obstacles_b()) =
1537 Eigen::MatrixXd::Zero(
1538 frame->open_space_info().obstacles_edges_num().sum(), 1);
1539 // vertices using H-representation
1540 if (!GetHyperPlanes(
1541 frame->open_space_info().obstacles_num(),
1542 frame->open_space_info().obstacles_edges_num(),
1543 frame->open_space_info().obstacles_vertices_vec(),
1544 frame->mutable_open_space_info()->mutable_obstacles_A(),
1545 frame->mutable_open_space_info()->mutable_obstacles_b())) {
1546 AERROR << "Fail to present obstacle in hyperplane";
1547 return false;
1548 }
1549 return true;
1550}
1551
1552bool OpenSpaceRoiDecider::GetHyperPlanes(
1553 const size_t &obstacles_num, const Eigen::MatrixXi &obstacles_edges_num,
1554 const std::vector<std::vector<Vec2d>> &obstacles_vertices_vec,
1555 Eigen::MatrixXd *A_all, Eigen::MatrixXd *b_all) {
1556 if (obstacles_num != obstacles_vertices_vec.size()) {
1557 AERROR << "obstacles_num != obstacles_vertices_vec.size()";
1558 return false;
1559 }
1560
1561 A_all->resize(obstacles_edges_num.sum(), 2);
1562 b_all->resize(obstacles_edges_num.sum(), 1);
1563
1564 int counter = 0;
1565 double kEpsilon = 1.0e-5;
1566 // start building H representation
1567 for (size_t i = 0; i < obstacles_num; ++i) {
1568 size_t current_vertice_num = obstacles_edges_num(i, 0);
1569 Eigen::MatrixXd A_i(current_vertice_num, 2);
1570 Eigen::MatrixXd b_i(current_vertice_num, 1);
1571
1572 // take two subsequent vertices, and computer hyperplane
1573 for (size_t j = 0; j < current_vertice_num; ++j) {
1574 Vec2d v1 = obstacles_vertices_vec[i][j];
1575 Vec2d v2 = obstacles_vertices_vec[i][j + 1];
1576
1577 Eigen::MatrixXd A_tmp(2, 1), b_tmp(1, 1), ab(2, 1);
1578 // find hyperplane passing through v1 and v2
1579 if (std::abs(v1.x() - v2.x()) < kEpsilon) {
1580 if (v2.y() < v1.y()) {
1581 A_tmp << 1, 0;
1582 b_tmp << v1.x();
1583 } else {
1584 A_tmp << -1, 0;
1585 b_tmp << -v1.x();
1586 }
1587 } else if (std::abs(v1.y() - v2.y()) < kEpsilon) {
1588 if (v1.x() < v2.x()) {
1589 A_tmp << 0, 1;
1590 b_tmp << v1.y();
1591 } else {
1592 A_tmp << 0, -1;
1593 b_tmp << -v1.y();
1594 }
1595 } else {
1596 Eigen::MatrixXd tmp1(2, 2);
1597 tmp1 << v1.x(), 1, v2.x(), 1;
1598 Eigen::MatrixXd tmp2(2, 1);
1599 tmp2 << v1.y(), v2.y();
1600 ab = tmp1.inverse() * tmp2;
1601 double a = ab(0, 0);
1602 double b = ab(1, 0);
1603
1604 if (v1.x() < v2.x()) {
1605 A_tmp << -a, 1;
1606 b_tmp << b;
1607 } else {
1608 A_tmp << a, -1;
1609 b_tmp << -b;
1610 }
1611 }
1612
1613 // store vertices
1614 A_i.block(j, 0, 1, 2) = A_tmp.transpose();
1615 b_i.block(j, 0, 1, 1) = b_tmp;
1616 }
1617
1618 A_all->block(counter, 0, A_i.rows(), 2) = A_i;
1619 b_all->block(counter, 0, b_i.rows(), 1) = b_i;
1620 counter += static_cast<int>(current_vertice_num);
1621 }
1622 return true;
1623}
1624
1625bool OpenSpaceRoiDecider::IsInParkingLot(
1626 const double adc_init_x, const double adc_init_y,
1627 const double adc_init_heading, std::array<Vec2d, 4> *parking_lot_vertices) {
1628 std::vector<ParkingSpaceInfoConstPtr> parking_lots;
1629 // make sure there is only one parking lot in search range
1630 const double kDistance = 1.0;
1631 auto adc_parking_spot =
1632 common::util::PointFactory::ToPointENU(adc_init_x, adc_init_y, 0);
1633 ADEBUG << "IsInParkingLot";
1634 ADEBUG << hdmap_;
1635 ADEBUG << hdmap_->GetParkingSpaces(adc_parking_spot, kDistance,
1636 &parking_lots);
1637 if (hdmap_->GetParkingSpaces(adc_parking_spot, kDistance, &parking_lots) ==
1638 0) {
1639 GetParkSpotFromMap(parking_lots.front(), parking_lot_vertices);
1640 AINFO << "Get park lot from map!!";
1641 return true;
1642 }
1643 return false;
1644}
1645
1646void OpenSpaceRoiDecider::GetParkSpotFromMap(
1647 ParkingSpaceInfoConstPtr parking_lot, std::array<Vec2d, 4> *vertices) {
1648 // left or right of the parking lot is decided when viewing the parking spot
1649 // open upward
1650 Vec2d left_top = parking_lot->polygon().points().at(3);
1651 Vec2d left_down = parking_lot->polygon().points().at(0);
1652 Vec2d right_down = parking_lot->polygon().points().at(1);
1653 Vec2d right_top = parking_lot->polygon().points().at(2);
1654
1655 std::array<Vec2d, 4> parking_vertices{left_top, left_down, right_down,
1656 right_top};
1657
1658 *vertices = std::move(parking_vertices);
1659 Vec2d tmp = (*vertices)[0];
1660 ADEBUG << "Parking Lot";
1661 ADEBUG << "parking_lot_vertices: (" << tmp.x() << ", " << tmp.y() << ")";
1662}
1663
1664void OpenSpaceRoiDecider::GetAllLaneSegments(
1665 const routing::RoutingResponse &routing_response,
1666 std::vector<routing::LaneSegment> *routing_segments) {
1667 routing_segments->clear();
1668 for (const auto &road : routing_response.road()) {
1669 for (const auto &passage : road.passage()) {
1670 for (const auto &segment : passage.segment()) {
1671 routing_segments->emplace_back(segment);
1672 }
1673 }
1674 }
1675}
1676
1677bool OpenSpaceRoiDecider::GetNearbyPath(
1678 const apollo::routing::RoutingResponse &routing_response,
1679 const ParkingSpaceInfoConstPtr &parking_spot,
1680 std::shared_ptr<hdmap::Path> *nearby_path) {
1681 LaneInfoConstPtr nearest_lane;
1682 if (nullptr == parking_spot) {
1683 AERROR << "The parking spot id is invalid!" << parking_spot->id().id();
1684 return false;
1685 }
1686 auto parking_space = parking_spot->parking_space();
1687 auto overlap_ids = parking_space.overlap_id();
1688 if (overlap_ids.empty()) {
1689 AERROR << "There is no lane overlaps with the parking spot: "
1690 << parking_spot->id().id();
1691 return false;
1692 }
1693 std::vector<routing::LaneSegment> lane_segments;
1694 GetAllLaneSegments(routing_response, &lane_segments);
1695 bool has_found_nearest_lane = false;
1696 size_t nearest_lane_index = 0;
1697 for (auto id : overlap_ids) {
1698 auto overlaps = hdmap_->GetOverlapById(id)->overlap();
1699 for (auto object : overlaps.object()) {
1700 if (!object.has_lane_overlap_info()) {
1701 continue;
1702 }
1703 nearest_lane = hdmap_->GetLaneById(object.id());
1704 if (nearest_lane == nullptr) {
1705 continue;
1706 }
1707 // Check if the lane is contained in the routing response.
1708 for (auto &segment : lane_segments) {
1709 if (segment.id() == nearest_lane->id().id()) {
1710 has_found_nearest_lane = true;
1711 break;
1712 }
1713 ++nearest_lane_index;
1714 }
1715 if (has_found_nearest_lane) {
1716 break;
1717 }
1718 }
1719 }
1720 if (!has_found_nearest_lane) {
1721 AERROR << "Cannot find the lane nearest to the parking spot when "
1722 "GetParkingSpot!";
1723 }
1724
1725 // Get the lane nearest to the current position of the vehicle. If the
1726 // vehicle has not reached the nearest lane to the parking spot, set the
1727 // lane nearest to the vehicle as "nearest_lane".
1728 LaneInfoConstPtr nearest_lane_to_vehicle;
1729 auto point = common::util::PointFactory::ToPointENU(vehicle_state_);
1730 double vehicle_lane_s = 0.0;
1731 double vehicle_lane_l = 0.0;
1732 int status = hdmap_->GetNearestLaneWithHeading(
1733 point, 10.0, vehicle_state_.heading(), M_PI / 2.0,
1734 &nearest_lane_to_vehicle, &vehicle_lane_s, &vehicle_lane_l);
1735 if (status == 0) {
1736 size_t nearest_lane_to_vehicle_index = 0;
1737 bool has_found_nearest_lane_to_vehicle = false;
1738 for (auto &segment : lane_segments) {
1739 if (segment.id() == nearest_lane_to_vehicle->id().id()) {
1740 has_found_nearest_lane_to_vehicle = true;
1741 break;
1742 }
1743 ++nearest_lane_to_vehicle_index;
1744 }
1745 // The vehicle has not reached the nearest lane to the parking spot。
1746 if (has_found_nearest_lane_to_vehicle &&
1747 nearest_lane_to_vehicle_index < nearest_lane_index) {
1748 nearest_lane = nearest_lane_to_vehicle;
1749 }
1750 }
1751
1752 // Find parking spot by getting nearestlane
1753 ParkingSpaceInfoConstPtr target_parking_spot = nullptr;
1754 LaneSegment nearest_lanesegment =
1755 LaneSegment(nearest_lane, nearest_lane->accumulate_s().front(),
1756 nearest_lane->accumulate_s().back());
1757 std::vector<LaneSegment> segments_vector;
1758 int next_lanes_num = nearest_lane->lane().successor_id_size();
1759 if (next_lanes_num != 0) {
1760 auto next_lane_id = nearest_lane->lane().successor_id(0);
1761 segments_vector.push_back(nearest_lanesegment);
1762 auto next_lane = hdmap_->GetLaneById(next_lane_id);
1763 LaneSegment next_lanesegment =
1764 LaneSegment(next_lane, next_lane->accumulate_s().front(),
1765 next_lane->accumulate_s().back());
1766 segments_vector.push_back(next_lanesegment);
1767 size_t succeed_lanes_num = next_lane->lane().successor_id_size();
1768 if (succeed_lanes_num != 0) {
1769 auto succeed_lane_id = next_lane->lane().successor_id(0);
1770 auto succeed_lane = hdmap_->GetLaneById(succeed_lane_id);
1771 LaneSegment succeed_lanesegment =
1772 LaneSegment(succeed_lane, succeed_lane->accumulate_s().front(),
1773 succeed_lane->accumulate_s().back());
1774 segments_vector.push_back(succeed_lanesegment);
1775 }
1776 *nearby_path = std::make_shared<Path>(segments_vector);
1777 } else {
1778 segments_vector.push_back(nearest_lanesegment);
1779 *nearby_path = std::make_shared<Path>(segments_vector);
1780 }
1781 return true;
1782}
1783bool OpenSpaceRoiDecider::AdjustPointsOrderToClockwise(
1784 std::vector<Vec2d> *polygon) {
1785 if (!OpenSpaceRoiUtil::IsPolygonClockwise(*polygon)) {
1786 // counter clockwise reverse it
1787 ADEBUG << "point is anticlockwise,reverse";
1788 std::reverse(polygon->begin(), polygon->end());
1789 return true;
1790 } else {
1791 return false;
1792 }
1793}
1794
1795bool OpenSpaceRoiDecider::GetParkingOutBoundary(
1796 const hdmap::Path &nearby_path, Frame *const frame,
1797 std::vector<std::vector<common::math::Vec2d>> *const roi_parking_boundary) {
1798 const auto &park_and_go_status =
1799 injector_->planning_context()->planning_status().park_and_go();
1800 const double adc_init_x = park_and_go_status.adc_init_position().x();
1801 const double adc_init_y = park_and_go_status.adc_init_position().y();
1802 const double adc_init_heading = park_and_go_status.adc_init_heading();
1803 common::math::Vec2d adc_init_position = {adc_init_x, adc_init_y};
1804 const double adc_length = vehicle_params_.length();
1805 const double adc_width = vehicle_params_.width();
1806 AINFO << std::fixed << "adc_init_x is " << adc_init_x << "adc_init_y is "
1807 << adc_init_y << "adc_init_heading is " << adc_init_heading;
1808 // Current localization position is not in the center of vehicle
1809 double shift_distance =
1810 vehicle_params_.front_edge_to_center() - 0.5 * adc_length;
1811 adc_init_position = adc_init_position +
1812 Vec2d::CreateUnitVec2d(adc_init_heading) * shift_distance;
1813 // ADC box of Vehcile
1814 Box2d adc_box(adc_init_position, adc_init_heading, adc_length, adc_width);
1815 // get vertices from ADC box
1816 std::vector<common::math::Vec2d> adc_corners;
1817 adc_box.GetAllCorners(&adc_corners);
1818 // Get the parking spot points where the vehicle is currently located
1819 std::vector<ParkingSpaceInfoConstPtr> parking_lots;
1820 auto adc_parking_spot =
1821 common::util::PointFactory::ToPointENU(adc_init_x, adc_init_y, 0);
1822 const double kDistance = 1.0;
1823 if (hdmap_->GetParkingSpaces(adc_parking_spot, kDistance, &parking_lots) !=
1824 0) {
1825 AINFO << "Failed to get the parking spot!!!";
1826 return false;
1827 } else {
1828 AINFO << "Get " << parking_lots.size() << " parking spots";
1829 }
1830 std::vector<Vec2d> parking_boundary;
1831 for (const auto &parking_overlap : parking_lots) {
1832 const auto parking_polygon = parking_overlap->polygon();
1833 AINFO << "parking_polygon: " << parking_polygon.DebugString();
1834 bool is_in_parking_spot = true;
1835 for (const auto &corner : adc_corners) {
1836 if (!parking_polygon.IsPointIn(corner)) {
1837 is_in_parking_spot = false;
1838 AINFO << "Vehicle is out of parking spot!";
1839 break;
1840 }
1841 }
1842 if (is_in_parking_spot) {
1843 auto points = parking_polygon.points();
1844 OpenSpaceRoiUtil::UpdateParkingPointsOrder(nearby_path, &points);
1845 for (size_t i = 0; i < points.size(); i++) {
1846 int t = static_cast<int>(i + 1) % static_cast<int>(points.size());
1847 parking_boundary.emplace_back(points.at(t).x(), points.at(t).y());
1848 }
1849 }
1850 }
1851 if (parking_boundary.size() < 4) {
1852 AINFO << " Current parking spot is invalid!";
1853 return false;
1854 }
1855 auto left_top = parking_boundary[3];
1856 auto right_top = parking_boundary[0];
1857 auto right_down = parking_boundary[1];
1858 auto left_down = parking_boundary[2];
1859
1860 double left_top_s = 0.0;
1861 double left_top_l = 0.0;
1862 double right_top_s = 0.0;
1863 double right_top_l = 0.0;
1864 double left_down_s = 0.0;
1865 double left_down_l = 0.0;
1866 double right_down_s = 0.0;
1867 double right_down_l = 0.0;
1868 if (!(nearby_path.GetProjection(left_top, &left_top_s, &left_top_l) &&
1869 nearby_path.GetProjection(right_top, &right_top_s, &right_top_l))) {
1870 AERROR << "fail to get parking spot points' projections on reference line";
1871 return false;
1872 }
1873
1874 if (!(nearby_path.GetProjection(left_down, &left_down_s, &left_down_l) &&
1875 nearby_path.GetProjection(right_down, &right_down_s, &right_down_l))) {
1876 AERROR << "fail to get parking spot points' projections on reference line";
1877 return false;
1878 }
1879 if (fabs(left_top_l + right_top_l) > fabs(left_down_l + right_down_l)) {
1880 frame->mutable_open_space_info()->mutable_origin_point()->set_x(
1881 right_down.x());
1882 frame->mutable_open_space_info()->mutable_origin_point()->set_y(
1883 right_down.y());
1884 double heading;
1885 if (!nearby_path.GetHeadingAlongPath(right_down, &heading)) {
1886 AERROR << "fail to get heading on reference line";
1887 return false;
1888 }
1889 frame->mutable_open_space_info()->set_origin_heading(
1891 std::swap(right_down, left_top);
1892 std::swap(right_top, left_down);
1893 std::swap(right_down_s, left_top_s);
1894 std::swap(right_down_l, left_top_l);
1895 std::swap(right_top_s, left_down_s);
1896 std::swap(right_top_l, left_down_l);
1897 }
1898
1899 const double center_line_s = (left_top_s + right_top_s) / 2.0;
1900 std::vector<Vec2d> left_lane_boundary;
1901 std::vector<Vec2d> right_lane_boundary;
1902 // The pivot points on the central lane, mapping with the key points on
1903 // the left lane boundary.
1904 std::vector<Vec2d> center_lane_boundary_left;
1905 // The pivot points on the central lane, mapping with the key points on
1906 // the right lane boundary.
1907 std::vector<Vec2d> center_lane_boundary_right;
1908 // The s-value for the anchor points on the center_lane_boundary_left.
1909 std::vector<double> center_lane_s_left;
1910 // The s-value for the anchor points on the center_lane_boundary_right.
1911 std::vector<double> center_lane_s_right;
1912 // The left-half road width between the pivot points on the
1913 // center_lane_boundary_left and key points on the
1914 // left_lane_boundary.
1915 std::vector<double> left_lane_road_width;
1916 // The right-half road width between the pivot points on the
1917 // center_lane_boundary_right and key points on the
1918 // right_lane_boundary.
1919 std::vector<double> right_lane_road_width;
1920
1921 GetRoadBoundary(nearby_path, center_line_s, Vec2d(0.0, 0.0), 0.0,
1922 &left_lane_boundary, &right_lane_boundary,
1923 &center_lane_boundary_left, &center_lane_boundary_right,
1924 &center_lane_s_left, &center_lane_s_right,
1925 &left_lane_road_width, &right_lane_road_width);
1926
1927 // If smaller than zero, the parking spot is on the right of the lane
1928 // Left, right, down or opposite of the boundary is decided when viewing the
1929 // parking spot upward
1930 const double average_l = (left_top_l + right_top_l) / 2.0;
1931 const double average_s = (left_top_s + right_top_s) / 2.0;
1932
1933 std::vector<Vec2d> boundary_points;
1934
1935 // TODO(jiaxuan): Write a half-boundary formation function and call it twice
1936 // to avoid duplicated manipulations on the left and right sides
1937 if (average_l < 0) {
1938 // if average_l is lower than zero, the parking spot is on the right
1939 // lane boundary and assume that the lane half width is average_l
1940 ADEBUG << "average_l is less than 0 in OpenSpaceROI";
1941 size_t point_size = right_lane_boundary.size();
1942 for (size_t i = 0; i < point_size; i++) {
1943 right_lane_boundary[i] -= center_lane_boundary_right[i];
1944 right_lane_boundary[i] /= right_lane_road_width[i];
1945 if (center_lane_s_right[i] < (average_s)) {
1946 right_lane_boundary[i] *= (std::fabs(left_top_l));
1947 } else {
1948 right_lane_boundary[i] *= (std::fabs(right_top_l));
1949 }
1950 right_lane_boundary[i] += center_lane_boundary_right[i];
1951 }
1952
1953 auto point_left_to_left_top_connor_s = std::lower_bound(
1954 center_lane_s_right.begin(), center_lane_s_right.end(), left_top_s);
1955 size_t point_left_to_left_top_connor_index = std::distance(
1956 center_lane_s_right.begin(), point_left_to_left_top_connor_s);
1957 point_left_to_left_top_connor_index =
1958 point_left_to_left_top_connor_index == 0
1959 ? point_left_to_left_top_connor_index
1960 : point_left_to_left_top_connor_index - 1;
1961 auto point_left_to_left_top_connor_itr =
1962 right_lane_boundary.begin() + point_left_to_left_top_connor_index;
1963 auto point_right_to_right_top_connor_s = std::upper_bound(
1964 center_lane_s_right.begin(), center_lane_s_right.end(), right_top_s);
1965 size_t point_right_to_right_top_connor_index = std::distance(
1966 center_lane_s_right.begin(), point_right_to_right_top_connor_s);
1967 auto point_right_to_right_top_connor_itr =
1968 right_lane_boundary.begin() + point_right_to_right_top_connor_index;
1969
1970 std::copy(right_lane_boundary.begin(), point_left_to_left_top_connor_itr,
1971 std::back_inserter(boundary_points));
1972
1973 std::vector<Vec2d> parking_spot_boundary{left_top, left_down, right_down,
1974 right_top};
1975
1976 std::copy(parking_spot_boundary.begin(), parking_spot_boundary.end(),
1977 std::back_inserter(boundary_points));
1978
1979 std::copy(point_right_to_right_top_connor_itr, right_lane_boundary.end(),
1980 std::back_inserter(boundary_points));
1981
1982 std::reverse_copy(left_lane_boundary.begin(), left_lane_boundary.end(),
1983 std::back_inserter(boundary_points));
1984
1985 // reinsert the initial point to the back to from closed loop
1986 boundary_points.push_back(right_lane_boundary.front());
1987
1988 // disassemble line into line2d segments
1989 for (size_t i = 0; i < point_left_to_left_top_connor_index; i++) {
1990 std::vector<Vec2d> segment{right_lane_boundary[i],
1991 right_lane_boundary[i + 1]};
1992 roi_parking_boundary->push_back(segment);
1993 }
1994
1995 std::vector<Vec2d> left_stitching_segment{
1996 right_lane_boundary[point_left_to_left_top_connor_index], left_top};
1997 roi_parking_boundary->push_back(left_stitching_segment);
1998
1999 std::vector<Vec2d> left_parking_spot_segment{left_top, left_down};
2000 std::vector<Vec2d> down_parking_spot_segment{left_down, right_down};
2001 std::vector<Vec2d> right_parking_spot_segment{right_down, right_top};
2002 roi_parking_boundary->push_back(left_parking_spot_segment);
2003 roi_parking_boundary->push_back(down_parking_spot_segment);
2004 roi_parking_boundary->push_back(right_parking_spot_segment);
2005
2006 std::vector<Vec2d> right_stitching_segment{
2007 right_top, right_lane_boundary[point_right_to_right_top_connor_index]};
2008 roi_parking_boundary->push_back(right_stitching_segment);
2009
2010 size_t right_lane_boundary_last_index = right_lane_boundary.size() - 1;
2011 for (size_t i = point_right_to_right_top_connor_index;
2012 i < right_lane_boundary_last_index; i++) {
2013 std::vector<Vec2d> segment{right_lane_boundary[i],
2014 right_lane_boundary[i + 1]};
2015 roi_parking_boundary->push_back(segment);
2016 }
2017
2018 size_t left_lane_boundary_last_index = left_lane_boundary.size() - 1;
2019 for (size_t i = left_lane_boundary_last_index; i > 0; i--) {
2020 std::vector<Vec2d> segment{left_lane_boundary[i],
2021 left_lane_boundary[i - 1]};
2022 roi_parking_boundary->push_back(segment);
2023 }
2024
2025 } else {
2026 // if average_l is higher than zero, the parking spot is on the left
2027 // lane boundary and assume that the lane half width is average_l
2028 ADEBUG << "average_l is greater than 0 in OpenSpaceROI";
2029 size_t point_size = left_lane_boundary.size();
2030 for (size_t i = 0; i < point_size; i++) {
2031 left_lane_boundary[i] -= center_lane_boundary_left[i];
2032 left_lane_boundary[i] /= left_lane_road_width[i];
2033 if (center_lane_s_right[i] < (average_s)) {
2034 left_lane_boundary[i] *= (std::fabs(right_top_l));
2035 } else {
2036 left_lane_boundary[i] *= (std::fabs(left_top_l));
2037 }
2038 left_lane_boundary[i] += center_lane_boundary_left[i];
2039 ADEBUG << "left_lane_boundary[" << i << "]: " << left_lane_boundary[i].x()
2040 << ", " << left_lane_boundary[i].y();
2041 }
2042
2043 auto point_right_to_right_top_connor_s = std::lower_bound(
2044 center_lane_s_left.begin(), center_lane_s_left.end(), right_top_s);
2045 size_t point_right_to_right_top_connor_index = std::distance(
2046 center_lane_s_left.begin(), point_right_to_right_top_connor_s);
2047 if (point_right_to_right_top_connor_index > 0) {
2048 --point_right_to_right_top_connor_index;
2049 }
2050 auto point_right_to_right_top_connor_itr =
2051 left_lane_boundary.begin() + point_right_to_right_top_connor_index;
2052
2053 auto point_left_to_left_top_connor_s = std::upper_bound(
2054 center_lane_s_left.begin(), center_lane_s_left.end(), left_top_s);
2055 size_t point_left_to_left_top_connor_index = std::distance(
2056 center_lane_s_left.begin(), point_left_to_left_top_connor_s);
2057 auto point_left_to_left_top_connor_itr =
2058 left_lane_boundary.begin() + point_left_to_left_top_connor_index;
2059
2060 std::copy(right_lane_boundary.begin(), right_lane_boundary.end(),
2061 std::back_inserter(boundary_points));
2062
2063 std::reverse_copy(point_left_to_left_top_connor_itr,
2064 left_lane_boundary.end(),
2065 std::back_inserter(boundary_points));
2066
2067 std::vector<Vec2d> parking_spot_boundary{left_top, left_down, right_down,
2068 right_top};
2069 std::copy(parking_spot_boundary.begin(), parking_spot_boundary.end(),
2070 std::back_inserter(boundary_points));
2071
2072 std::reverse_copy(left_lane_boundary.begin(),
2073 point_right_to_right_top_connor_itr,
2074 std::back_inserter(boundary_points));
2075
2076 // reinsert the initial point to the back to from closed loop
2077 boundary_points.push_back(right_lane_boundary.front());
2078
2079 // disassemble line into line2d segments
2080 size_t right_lane_boundary_last_index = right_lane_boundary.size() - 1;
2081 for (size_t i = 0; i < right_lane_boundary_last_index; i++) {
2082 std::vector<Vec2d> segment{right_lane_boundary[i],
2083 right_lane_boundary[i + 1]};
2084 roi_parking_boundary->push_back(segment);
2085 }
2086
2087 size_t left_lane_boundary_last_index = left_lane_boundary.size() - 1;
2088 for (size_t i = left_lane_boundary_last_index;
2089 i > point_left_to_left_top_connor_index; i--) {
2090 std::vector<Vec2d> segment{left_lane_boundary[i],
2091 left_lane_boundary[i - 1]};
2092 roi_parking_boundary->push_back(segment);
2093 }
2094
2095 std::vector<Vec2d> left_stitching_segment{
2096 left_lane_boundary[point_left_to_left_top_connor_index], left_top};
2097 roi_parking_boundary->push_back(left_stitching_segment);
2098
2099 std::vector<Vec2d> left_parking_spot_segment{left_top, left_down};
2100 std::vector<Vec2d> down_parking_spot_segment{left_down, right_down};
2101 std::vector<Vec2d> right_parking_spot_segment{right_down, right_top};
2102 roi_parking_boundary->push_back(left_parking_spot_segment);
2103 roi_parking_boundary->push_back(down_parking_spot_segment);
2104 roi_parking_boundary->push_back(right_parking_spot_segment);
2105
2106 std::vector<Vec2d> right_stitching_segment{
2107 right_top, left_lane_boundary[point_right_to_right_top_connor_index]};
2108 roi_parking_boundary->push_back(right_stitching_segment);
2109
2110 for (size_t i = point_right_to_right_top_connor_index; i > 0; --i) {
2111 std::vector<Vec2d> segment{left_lane_boundary[i],
2112 left_lane_boundary[i - 1]};
2113 roi_parking_boundary->push_back(segment);
2114 }
2115 }
2116 PrintCurves print_curves;
2117 const auto &origin_point = frame->mutable_open_space_info()->origin_point();
2118 double origin_heading = frame->mutable_open_space_info()->origin_heading();
2119 // AddParkingSpaceBoundary(frame, nearby_path, roi_parking_boundary);
2120 for (auto it : *roi_parking_boundary) {
2121 for (auto pt : it) {
2122 print_curves.AddPoint("roi_parking_boundary", pt);
2123 }
2124 }
2125 OpenSpaceRoiUtil::TransformByOriginPoint(origin_point, origin_heading,
2126 roi_parking_boundary);
2127 for (auto it : *roi_parking_boundary) {
2128 for (auto pt : it) {
2129 print_curves.AddPoint("transformed_roi_parking_boundary", pt);
2130 }
2131 }
2132 // Fuse line segments into convex contraints
2133 if (!FuseLineSegments(roi_parking_boundary)) {
2134 AERROR << "FuseLineSegments failed in parking ROI";
2135 return false;
2136 }
2137 print_curves.PrintToLog();
2138 auto *xy_boundary =
2139 frame->mutable_open_space_info()->mutable_ROI_xy_boundary();
2140 OpenSpaceRoiUtil::GetRoiXYBoundary(*roi_parking_boundary, xy_boundary);
2141
2142 Vec2d vehicle_xy = Vec2d(vehicle_state_.x(), vehicle_state_.y());
2143 vehicle_xy -= origin_point;
2144 vehicle_xy.SelfRotate(-origin_heading);
2145 if (vehicle_xy.x() < xy_boundary->at(0) ||
2146 vehicle_xy.x() > xy_boundary->at(1) ||
2147 vehicle_xy.y() < xy_boundary->at(2) ||
2148 vehicle_xy.y() > xy_boundary->at(3)) {
2149 AERROR << "vehicle outside of xy boundary of parking ROI";
2150 return false;
2151 }
2152 AINFO << "success get ROI";
2153 return true;
2154}
2155
2156bool OpenSpaceRoiDecider::AddParkingSpaceBoundary(
2157 Frame *const frame, const hdmap::Path &nearby_path,
2158 std::vector<std::vector<common::math::Vec2d>> *const roi_parking_boundary) {
2159 const auto &park_and_go_status =
2160 injector_->planning_context()->planning_status().park_and_go();
2161 const double adc_init_x = park_and_go_status.adc_init_position().x();
2162 const double adc_init_y = park_and_go_status.adc_init_position().y();
2163 const double adc_init_heading = park_and_go_status.adc_init_heading();
2164 common::math::Vec2d adc_init_position = {adc_init_x, adc_init_y};
2165 const double adc_length = vehicle_params_.length();
2166 const double adc_width = vehicle_params_.width();
2167 // ADC box
2168 double shift_distance =
2169 vehicle_params_.front_edge_to_center() - 0.5 * adc_length;
2170 adc_init_position = adc_init_position +
2171 Vec2d::CreateUnitVec2d(adc_init_heading) * shift_distance;
2172 Box2d adc_box(adc_init_position, adc_init_heading, adc_length, adc_width);
2173 // get vertices from ADC box
2174 std::vector<common::math::Vec2d> adc_corners;
2175 adc_box.GetAllCorners(&adc_corners);
2176 PrintCurves print_curves;
2177 for (auto pt : adc_corners) {
2178 print_curves.AddPoint("adc_corners", pt);
2179 }
2180 for (const auto &parking_overlap : nearby_path.parking_space_overlaps()) {
2181 hdmap::Id id;
2182 id.set_id(parking_overlap.object_id);
2183 const auto target_parking_spot = hdmap_->GetParkingSpaceById(id);
2184 if (!target_parking_spot) {
2185 continue;
2186 }
2187 const auto parking_polygon = target_parking_spot->polygon();
2188 for (const auto &pt : parking_polygon.points()) {
2189 print_curves.AddPoint(id.id() + "parking_polygon", pt);
2190 }
2191 bool is_in_polygon = true;
2192 for (const auto &pt : adc_corners) {
2193 if (!parking_polygon.IsPointIn(pt)) {
2194 is_in_polygon = false;
2195 break;
2196 }
2197 }
2198 if (is_in_polygon) {
2199 auto points = parking_polygon.points();
2200 OpenSpaceRoiUtil::UpdateParkingPointsOrder(nearby_path, &points);
2201 std::vector<Vec2d> parking_boundary;
2202 for (size_t i = 0; i < points.size(); i++) {
2203 int t = static_cast<int>(i + 1) % static_cast<int>(points.size());
2204 parking_boundary.emplace_back(points.at(t).x(), points.at(t).y());
2205 }
2206 roi_parking_boundary->push_back(parking_boundary);
2207 }
2208 }
2209 print_curves.PrintToLog();
2210 return true;
2211}
2212
2213} // namespace planning
2214} // namespace apollo
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
static Vec2d CreateUnitVec2d(const double angle)
Creates a unit-vector with a given angle to the positive x semi-axis
Definition vec2d.cc:29
static PointENU ToPointENU(const double x, const double y, const double z=0)
static const HDMap * BaseMapPtr()
static const HDMap & BaseMap()
int GetNearestLaneWithHeading(const apollo::common::PointENU &point, const double distance, const double central_heading, const double max_heading_difference, LaneInfoConstPtr *nearest_lane, double *nearest_s, double *nearest_l) const
get the nearest lane within a certain range by pose
Definition hdmap.cc:176
int GetParkingSpaces(const apollo::common::PointENU &point, double distance, std::vector< ParkingSpaceInfoConstPtr > *parking_spaces) const
get all parking spaces in certain range
Definition hdmap.cc:149
ParkingSpaceInfoConstPtr GetParkingSpaceById(const Id &id) const
Definition hdmap.cc:82
int GetRoadBoundaries(const apollo::common::PointENU &point, double radius, std::vector< RoadROIBoundaryPtr > *road_boundaries, std::vector< JunctionBoundaryPtr > *junctions) const
get all road and junctions boundaries within certain range
Definition hdmap.cc:197
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
OpenSpaceInfo * mutable_open_space_info()
Definition frame.h:169
ThreadSafeIndexedObstacles * GetObstacleList()
Definition frame.h:165
const std::list< ReferenceLineInfo > & reference_line_info() const
Definition frame.cc:123
void set_parking_type(const ParkingType type)
const std::string target_parking_spot_id() const
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
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
std::shared_ptr< DependencyInjector > injector_
Definition task.h:59
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
Definition task.cc:40
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
float cos(Angle16 a)
Definition angle.cc:42
double CrossProd(const Vec2d &start_point, const Vec2d &end_point_1, const Vec2d &end_point_2)
Cross product between two 2-D vectors from the common start point, and end at two other points.
Definition math_utils.cc:28
float sin(Angle16 a)
Definition angle.cc:25
double AngleDiff(const double from, const double to)
Calculate the difference between angle from and to
Definition math_utils.cc:61
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
Definition math_utils.cc:53
apollo::hdmap::Id MakeMapId(const std::string &id)
create a Map ID given a string.
Definition hdmap_util.h:85
std::shared_ptr< const LaneInfo > LaneInfoConstPtr
std::shared_ptr< const ParkingSpaceInfo > ParkingSpaceInfoConstPtr
class register implement
Definition arena_queue.h:37
Definition future.h:29
Define the Polygon2d class.
optional VehicleParam vehicle_param
Defines the Vec2d class.