35 const std::shared_ptr<DependencyInjector> &injector,
36 const std::string &config_dir,
38 CHECK_NOTNULL(context);
39 bool ret =
Stage::Init(config, injector, config_dir, context);
44 precise_parking_context_ = GetContextAs<PreciseParkingContext>();
51 GetOpenspaceRoi(frame);
55 AERROR <<
"StagePreceseParking planning error";
60 AINFO <<
"StagePreceseParking destination reached";
61 return FinishStage(frame);
77bool StagePreciseParking::GetOpenspaceRoi(
Frame *frame) {
83 std::vector<hdmap::AreaInfoConstPtr> areas;
87 AERROR <<
"can not find any junction near parking spot";
90 const auto &area_polygon = areas.front()->polygon();
92 double ego_x =
injector_->ego_info()->vehicle_state().
x();
93 double ego_y =
injector_->ego_info()->vehicle_state().y();
94 Vec2d ego_pos(ego_x, ego_y);
96 auto points = area_polygon.points();
98 std::reverse(points.begin(), points.end());
99 AINFO <<
"Junction polygon is anticlockwise";
101 SetOrigin(points, ego_pos, frame);
107 std::vector<std::vector<common::math::Vec2d>> roi_parking_boundary;
108 std::vector<common::math::Vec2d> parking_point;
109 for (
const auto point : points) {
110 parking_point.emplace_back(point.
x(), point.
y());
111 parking_point.back() -= frame->open_space_info().origin_point();
112 parking_point.back().SelfRotate(-frame->open_space_info().origin_heading());
114 parking_point.push_back(parking_point.front());
116 for (
int i = 0; i < parking_point.size() - 1; ++i) {
117 roi_parking_boundary.emplace_back(std::vector<Vec2d>{parking_point.at(i), parking_point.at(i + 1)});
121 if (!FuseLineSegments(roi_parking_boundary)) {
122 AERROR <<
"FuseLineSegments failed in parking ROI";
127 auto xminmax = std::minmax_element(
128 parking_point.begin(), parking_point.end(), [](
const Vec2d &a,
const Vec2d &b) { return a.x() < b.x(); });
129 auto yminmax = std::minmax_element(
130 parking_point.begin(), parking_point.end(), [](
const Vec2d &a,
const Vec2d &b) { return a.y() < b.y(); });
131 std::vector<double> ROI_xy_boundary{
132 xminmax.first->x(), xminmax.second->x(), yminmax.first->y(), yminmax.second->y()};
133 auto *xy_boundary = frame->mutable_open_space_info()->mutable_ROI_xy_boundary();
134 xy_boundary->assign(ROI_xy_boundary.begin(), ROI_xy_boundary.end());
136 ego_pos -= frame->open_space_info().origin_point();
137 ego_pos.SelfRotate(-frame->open_space_info().origin_heading());
138 if (ego_pos.x() < ROI_xy_boundary[0] || ego_pos.x() > ROI_xy_boundary[1] || ego_pos.y() < ROI_xy_boundary[2]
139 || ego_pos.y() > ROI_xy_boundary[3]) {
140 AERROR <<
"vehicle outside of xy boundary of parking ROI";
143 if (!FormulateBoundaryConstraints(roi_parking_boundary, frame)) {
144 const std::string msg =
"Fail to formulate boundary constraints";
151void StagePreciseParking::SetOrigin(
const std::vector<Vec2d> &points,
const Vec2d &ego_pos,
Frame *frame) {
152 auto *previous_frame =
injector_->frame_history()->Latest();
153 if (previous_frame->open_space_info().origin_point().x() != 0
154 && previous_frame->open_space_info().origin_point().y() != 0
155 && previous_frame->open_space_info().origin_heading() != 0) {
156 frame->mutable_open_space_info()->set_origin_heading(previous_frame->open_space_info().origin_heading());
157 frame->mutable_open_space_info()->mutable_origin_point()->set_x(
158 previous_frame->open_space_info().origin_point().x());
159 frame->mutable_open_space_info()->mutable_origin_point()->set_y(
160 previous_frame->open_space_info().origin_point().y());
162 double distance = std::numeric_limits<double>::max();
164 for (
int index = 0; index < points.size(); index++) {
165 const auto &point = points[index];
166 if ((point - ego_pos).Length() < distance) {
167 distance = (point - ego_pos).Length();
172 if (min_index == points.size() - 1) {
173 angle = (points[0] - points[min_index]).Angle();
175 angle = (points[min_index + 1] - points[min_index]).Angle();
177 frame->mutable_open_space_info()->set_origin_heading(angle);
178 frame->mutable_open_space_info()->mutable_origin_point()->set_x(points[min_index].x());
179 frame->mutable_open_space_info()->mutable_origin_point()->set_y(points[min_index].y());
183void StagePreciseParking::GetEndPose(
Frame *frame) {
185 Vec2d end_pt = Vec2d(parking_spot_pose.x(), parking_spot_pose.y());
188 * Vec2d(std::cos(parking_spot_pose.heading()), std::sin(parking_spot_pose.heading())) * -1.0
190 * Vec2d(std::cos(parking_spot_pose.heading()), std::sin(parking_spot_pose.heading()));
192 const auto &origin_point = frame->open_space_info().origin_point();
193 const auto &origin_heading = frame->open_space_info().origin_heading();
194 end_pt -= origin_point;
195 end_pt.SelfRotate(-origin_heading);
197 auto *end_pose = frame->mutable_open_space_info()->mutable_open_space_end_pose();
198 end_pose->push_back(end_pt.x());
199 end_pose->push_back(end_pt.y());
200 end_pose->push_back(parking_spot_pose.heading() - origin_heading);
201 end_pose->push_back(0.0);
204bool StagePreciseParking::FuseLineSegments(std::vector<std::vector<common::math::Vec2d>> &line_segments_vec) {
205 static constexpr double kEpsilon = 1.0e-8;
206 auto cur_segment = line_segments_vec.begin();
207 while (cur_segment != line_segments_vec.end() - 1) {
208 auto next_segment = cur_segment + 1;
209 auto cur_last_point = cur_segment->back();
210 auto next_first_point = next_segment->front();
212 if (cur_last_point.DistanceTo(next_first_point) > kEpsilon) {
216 if (cur_segment->size() < 2 || next_segment->size() < 2) {
217 AERROR <<
"Single point line_segments vec not expected";
220 size_t cur_segments_size = cur_segment->size();
221 auto cur_second_to_last_point = cur_segment->at(cur_segments_size - 2);
222 auto next_second_point = next_segment->at(1);
224 cur_segment->push_back(next_second_point);
225 next_segment->erase(next_segment->begin(), next_segment->begin() + 2);
226 if (next_segment->empty()) {
227 line_segments_vec.erase(next_segment);
236bool StagePreciseParking::FormulateBoundaryConstraints(
237 const std::vector<std::vector<common::math::Vec2d>> &roi_parking_boundary,
238 Frame *
const frame) {
240 if (!LoadObstacleInVertices(roi_parking_boundary, frame)) {
241 AERROR <<
"fail at LoadObstacleInVertices()";
246 AERROR <<
"fail at LoadObstacleInHyperPlanes()";
252bool StagePreciseParking::LoadObstacleInVertices(
253 const std::vector<std::vector<common::math::Vec2d>> &roi_parking_boundary,
254 Frame *
const frame) {
255 auto *mutable_open_space_info = frame->mutable_open_space_info();
256 const auto &open_space_info = frame->open_space_info();
257 auto *obstacles_vertices_vec = mutable_open_space_info->mutable_obstacles_vertices_vec();
258 auto *obstacles_edges_num_vec = mutable_open_space_info->mutable_obstacles_edges_num();
262 size_t parking_boundaries_num = roi_parking_boundary.size();
263 size_t perception_obstacles_num = 0;
265 for (
size_t i = 0; i < parking_boundaries_num; ++i) {
266 obstacles_vertices_vec->push_back(roi_parking_boundary[i]);
269 Eigen::MatrixXi parking_boundaries_obstacles_edges_num(parking_boundaries_num, 1);
270 for (
size_t i = 0; i < parking_boundaries_num; i++) {
271 if (roi_parking_boundary[i].size() <= 1U) {
272 AERROR <<
"Roi parking boundary is invalid: " << roi_parking_boundary[i].size();
275 parking_boundaries_obstacles_edges_num(i, 0) =
static_cast<int>(roi_parking_boundary[i].size()) - 1;
280 if (perception_obstacles_num == 0) {
281 ADEBUG <<
"no obstacle given by perception";
285 const auto &origin_point = open_space_info.origin_point();
286 const auto &origin_heading = open_space_info.origin_heading();
288 AINFO << obstacles_by_frame->Items().size();
289 for (
const auto &obstacle : obstacles_by_frame->Items()) {
291 AINFO <<
"obstacle is filtered out";
294 ++perception_obstacles_num;
296 std::vector<Vec2d> vertices_ccw;
298 common::math::Polygon2d original_polygon = obstacle->PerceptionPolygon();
299 original_polygon.ExpandByDistance(
301 original_polygon.CalculateVertices(-1.0 * origin_point);
302 vertices_ccw = original_polygon.GetAllVertices();
304 Box2d original_box = obstacle->PerceptionBoundingBox();
305 original_box.Shift(-1.0 * origin_point);
308 vertices_ccw = original_box.GetAllCorners();
318 std::vector<Vec2d> vertices_cw;
319 while (!vertices_ccw.empty()) {
320 auto current_corner_pt = vertices_ccw.back();
321 current_corner_pt.SelfRotate(-1.0 * origin_heading);
322 vertices_cw.push_back(current_corner_pt);
323 vertices_ccw.pop_back();
328 vertices_cw.push_back(vertices_cw.front());
329 AINFO <<
"obstacle vertices: " << vertices_cw.size();
330 obstacles_vertices_vec->push_back(vertices_cw);
334 Eigen::MatrixXi perception_obstacles_edges_num = 4 * Eigen::MatrixXi::Ones(perception_obstacles_num, 1);
336 obstacles_edges_num_vec->resize(
337 parking_boundaries_obstacles_edges_num.rows() + perception_obstacles_edges_num.rows(), 1);
338 *(obstacles_edges_num_vec) << parking_boundaries_obstacles_edges_num, perception_obstacles_edges_num;
341 obstacles_edges_num_vec->resize(parking_boundaries_obstacles_edges_num.rows(), 1);
342 *(obstacles_edges_num_vec) << parking_boundaries_obstacles_edges_num;
345 mutable_open_space_info->set_obstacles_num(parking_boundaries_num + perception_obstacles_num);
Implements a class of 2-dimensional vectors.
static const HDMap * BaseMapPtr()
Frame holds all data for one planning cycle.
const OpenSpaceInfo & open_space_info() const
OpenSpaceInfo * mutable_open_space_info()
bool destination_reached() const
void set_is_on_open_space_trajectory(const bool flag)
DiscretizedTrajectory * mutable_path_planning_trajectory_result()
DiscretizedTrajectory * mutable_interpolated_trajectory_result()
DiscretizedTrajectory * mutable_optimizer_trajectory_data()
TrajGearPair * mutable_chosen_partitioned_trajectory()
std::vector< TrajGearPair > * mutable_partitioned_trajectories()
static bool AdjustPointsOrderToClockwise(std::vector< Vec2d > *polygon)
static bool LoadObstacleInHyperPlanes(OpenSpaceInfo *const open_space_info)
brief Transform the vertice presentation of the obstacles into linear inequality as Ax>b
static bool FilterOutObstacle(const double filtering_distance, const Frame &frame, const std::vector< double > &xy_boundary, const Obstacle &obstacle)
is obstacle can be filterd out, filtered by distance and roi XY bound
StageResult Process(const common::TrajectoryPoint &planning_init_point, Frame *frame) override
Each stage does its business logic inside Process function.
bool Init(const StagePipeline &config, const std::shared_ptr< DependencyInjector > &injector, const std::string &config_dir, void *context)
const StageResult & SetStageStatus(const StageStatusType &stage_status)
Set the stage status.
bool HasError() const
Check if StageResult contains error.
StageResult ExecuteTaskOnOpenSpace(Frame *frame)
virtual bool Init(const StagePipeline &config, const std::shared_ptr< DependencyInjector > &injector, const std::string &config_dir, void *context)
std::shared_ptr< DependencyInjector > injector_
const std::string & Name() const
Planning module main class.
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.
ThreadSafeIndexedList< std::string, Obstacle > ThreadSafeIndexedObstacles
required Pose parking_spot_pose
required bool parking_inwards
apollo::external_command::PreciseParkingCommand precise_parking_command
ScenarioPreciseParkingConfig scenario_config
optional double perception_obstacle_buffer
optional bool enable_perception_obstacles
optional double precise_trajectory_length
optional bool expand_polygon_of_obstacle_by_distance