Apollo 11.0
自动驾驶开放平台
grid_search.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
17/*
18 * @file
19 */
20
22
23namespace apollo {
24namespace planning {
25
27
29 xy_grid_resolution_ = open_space_conf.warm_start_config().grid_a_star_xy_resolution();
30 node_radius_ = open_space_conf.warm_start_config().node_radius();
31}
32
33GridSearch::GridSearch(const WarmStartConfig& warm_start_conf) {
34 xy_grid_resolution_ = warm_start_conf.grid_a_star_xy_resolution();
35 node_radius_ = warm_start_conf.node_radius();
36 esdf_range_ = warm_start_conf.esdf_range();
37 use_esdf_ = warm_start_conf.use_esdf();
38}
39
40double GridSearch::EuclidDistance(const double x1, const double y1, const double x2, const double y2) {
41 return std::sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
42}
43
44bool GridSearch::CheckConstraints(std::shared_ptr<Node2d> node) {
45 const double node_grid_x = node->GetGridX();
46 const double node_grid_y = node->GetGridY();
47 if (node_grid_x > max_grid_x_ || node_grid_x < 0 || node_grid_y > max_grid_y_ || node_grid_y < 0) {
48 return false;
49 }
50 if (obstacles_linesegments_vec_.empty()) {
51 return true;
52 }
53 for (const auto& obstacle_linesegments : obstacles_linesegments_vec_) {
54 for (const common::math::LineSegment2d& linesegment : obstacle_linesegments) {
55 if (linesegment.DistanceTo({node->GetGridX(), node->GetGridY()}) < node_radius_) {
56 return false;
57 }
58 }
59 }
60 return true;
61}
62
63/* Currently it is only used to add cost at the boundaries of parking spaces,
64thus avoiding the generation of trajectories that press on the parking space lines.
65Since the parking space information is fixed, it is only called once.*/
66void GridSearch::AddSoftCost(const std::vector<std::vector<common::math::LineSegment2d>>& soft_boundary) {
67 for (const auto& soft_boundary_linesegments : soft_boundary) {
68 for (const common::math::LineSegment2d& linesegment : soft_boundary_linesegments) {
69 int max = linesegment.length() / xy_grid_resolution_;
70 Vec2d unit = linesegment.unit_direction();
71 Vec2d node = linesegment.start();
72 for (double i = 0; i < max; i++) {
73 std::unordered_set<std::string> close_set;
74 node += unit * xy_grid_resolution_;
75 int grid_x = static_cast<int>((node.x() - XYbounds_[0]) / xy_grid_resolution_);
76 int grid_y = static_cast<int>((node.y() - XYbounds_[2]) / xy_grid_resolution_);
77 Vec2d origin_index = {grid_x, grid_y};
78 ExtendNode(grid_x, grid_y, origin_index, close_set);
79 }
80 node = linesegment.end();
81 int grid_x = static_cast<int>((node.x() - XYbounds_[0]) / xy_grid_resolution_);
82 int grid_y = static_cast<int>((node.y() - XYbounds_[2]) / xy_grid_resolution_);
83 Vec2d origin_index = {grid_x, grid_y};
84 std::unordered_set<std::string> close_set;
85 ExtendNode(grid_x, grid_y, origin_index, close_set);
86 }
87 }
88}
89
90void GridSearch::ExtendNode(
91 const int& x,
92 const int& y,
93 Vec2d origin_index,
94 std::unordered_set<std::string>& close_set) {
95 Vec2d node = {x, y};
96 double min_dist = (node - origin_index).Length() * xy_grid_resolution_;
97 // AINFO << "x: " << x << " y: " << y << "origin x: "
98 // << origin_index.x() << " origin y: " << origin_index.y();
99 // AINFO << "min_dist: " << min_dist;
100 if (min_dist > esdf_range_ || x > max_grid_x_ || x < 0 || y > max_grid_y_ || y < 0) {
101 return;
102 }
103 // AINFO << "debug dist: " << min_dist;
104
105 std::string index = absl::StrCat(x, "_", y);
106 if (close_set.find(index) == close_set.end() && dp_map_.find(index) != dp_map_.end()
107 && dp_map_[index]->GetDistanceToObstacle() > min_dist) {
108 dp_map_[index]->SetDistanceToObstacle(min_dist);
109 close_set.insert(index);
110 for (int i = 0; i < 4; i++) {
111 int new_x = x + dx_[i];
112 int new_y = y + dy_[i];
113 ExtendNode(new_x, new_y, origin_index, close_set);
114 }
115 } else {
116 return;
117 }
118}
119
120std::vector<std::shared_ptr<Node2d>> GridSearch::GenerateNextNodes(std::shared_ptr<Node2d> current_node) {
121 double current_node_x = current_node->GetGridX();
122 double current_node_y = current_node->GetGridY();
123 double current_node_path_cost = current_node->GetPathCost();
124 double diagonal_distance = std::sqrt(2.0);
125 std::vector<std::shared_ptr<Node2d>> next_nodes;
126 std::shared_ptr<Node2d> up = std::make_shared<Node2d>(current_node_x, current_node_y + 1.0, XYbounds_);
127 up->SetPathCost(current_node_path_cost + 1.0);
128 std::shared_ptr<Node2d> up_right = std::make_shared<Node2d>(current_node_x + 1.0, current_node_y + 1.0, XYbounds_);
129 up_right->SetPathCost(current_node_path_cost + diagonal_distance);
130 std::shared_ptr<Node2d> right = std::make_shared<Node2d>(current_node_x + 1.0, current_node_y, XYbounds_);
131 right->SetPathCost(current_node_path_cost + 1.0);
132 std::shared_ptr<Node2d> down_right
133 = std::make_shared<Node2d>(current_node_x + 1.0, current_node_y - 1.0, XYbounds_);
134 down_right->SetPathCost(current_node_path_cost + diagonal_distance);
135 std::shared_ptr<Node2d> down = std::make_shared<Node2d>(current_node_x, current_node_y - 1.0, XYbounds_);
136 down->SetPathCost(current_node_path_cost + 1.0);
137 std::shared_ptr<Node2d> down_left = std::make_shared<Node2d>(current_node_x - 1.0, current_node_y - 1.0, XYbounds_);
138 down_left->SetPathCost(current_node_path_cost + diagonal_distance);
139 std::shared_ptr<Node2d> left = std::make_shared<Node2d>(current_node_x - 1.0, current_node_y, XYbounds_);
140 left->SetPathCost(current_node_path_cost + 1.0);
141 std::shared_ptr<Node2d> up_left = std::make_shared<Node2d>(current_node_x - 1.0, current_node_y + 1.0, XYbounds_);
142 up_left->SetPathCost(current_node_path_cost + diagonal_distance);
143
144 next_nodes.emplace_back(up);
145 next_nodes.emplace_back(up_right);
146 next_nodes.emplace_back(right);
147 next_nodes.emplace_back(down_right);
148 next_nodes.emplace_back(down);
149 next_nodes.emplace_back(down_left);
150 next_nodes.emplace_back(left);
151 next_nodes.emplace_back(up_left);
152 return next_nodes;
153}
154
156 const double sx,
157 const double sy,
158 const double ex,
159 const double ey,
160 const std::vector<double>& XYbounds,
161 const std::vector<std::vector<common::math::LineSegment2d>>& obstacles_linesegments_vec,
162 GridAStartResult* result) {
163 std::priority_queue<std::pair<std::string, double>, std::vector<std::pair<std::string, double>>, cmp> open_pq;
164 std::unordered_map<std::string, std::shared_ptr<Node2d>> open_set;
165 std::unordered_map<std::string, std::shared_ptr<Node2d>> close_set;
166 XYbounds_ = XYbounds;
167 std::shared_ptr<Node2d> start_node = std::make_shared<Node2d>(sx, sy, xy_grid_resolution_, XYbounds_);
168 std::shared_ptr<Node2d> end_node = std::make_shared<Node2d>(ex, ey, xy_grid_resolution_, XYbounds_);
169 std::shared_ptr<Node2d> final_node_ = nullptr;
170 obstacles_linesegments_vec_ = obstacles_linesegments_vec;
171 open_set.emplace(start_node->GetIndex(), start_node);
172 open_pq.emplace(start_node->GetIndex(), start_node->GetCost());
173
174 // Grid a star begins
175 size_t explored_node_num = 0;
176 while (!open_pq.empty()) {
177 std::string current_id = open_pq.top().first;
178 open_pq.pop();
179 std::shared_ptr<Node2d> current_node = open_set[current_id];
180 // Check destination
181 if (*(current_node) == *(end_node)) {
182 final_node_ = current_node;
183 break;
184 }
185 close_set.emplace(current_node->GetIndex(), current_node);
186 std::vector<std::shared_ptr<Node2d>> next_nodes = std::move(GenerateNextNodes(current_node));
187 for (auto& next_node : next_nodes) {
188 if (!CheckConstraints(next_node)) {
189 continue;
190 }
191 if (close_set.find(next_node->GetIndex()) != close_set.end()) {
192 continue;
193 }
194 if (open_set.find(next_node->GetIndex()) == open_set.end()) {
195 ++explored_node_num;
196 next_node->SetHeuristic(EuclidDistance(
197 next_node->GetGridX(), next_node->GetGridY(), end_node->GetGridX(), end_node->GetGridY()));
198 next_node->SetPreNode(current_node);
199 open_set.emplace(next_node->GetIndex(), next_node);
200 open_pq.emplace(next_node->GetIndex(), next_node->GetCost());
201 }
202 }
203 }
204
205 if (final_node_ == nullptr) {
206 AERROR << "Grid A searching return null ptr(open_set ran out)";
207 return false;
208 }
209 LoadGridAStarResult(result);
210 ADEBUG << "explored node num is " << explored_node_num;
211 return true;
212}
213
215 const double ex,
216 const double ey,
217 const std::vector<double>& XYbounds,
218 const std::vector<std::vector<common::math::LineSegment2d>>& obstacles_linesegments_vec,
219 const std::vector<std::vector<common::math::LineSegment2d>>& soft_boundary_linesegments_vec) {
220 std::priority_queue<std::pair<std::string, double>, std::vector<std::pair<std::string, double>>, cmp> open_pq;
221 std::unordered_map<std::string, std::shared_ptr<Node2d>> open_set;
222 dp_map_ = decltype(dp_map_)();
223 XYbounds_ = XYbounds;
224 // XYbounds with xmin, xmax, ymin, ymax
225 max_grid_y_ = std::round((XYbounds_[3] - XYbounds_[2]) / xy_grid_resolution_);
226 max_grid_x_ = std::round((XYbounds_[1] - XYbounds_[0]) / xy_grid_resolution_);
227 std::shared_ptr<Node2d> end_node = std::make_shared<Node2d>(ex, ey, xy_grid_resolution_, XYbounds_);
228 obstacles_linesegments_vec_ = obstacles_linesegments_vec;
229 open_set.emplace(end_node->GetIndex(), end_node);
230 open_pq.emplace(end_node->GetIndex(), end_node->GetCost());
231
232 // Grid a star begins
233 size_t explored_node_num = 0;
234 while (!open_pq.empty()) {
235 const std::string current_id = open_pq.top().first;
236 open_pq.pop();
237 std::shared_ptr<Node2d> current_node = open_set[current_id];
238 dp_map_.emplace(current_node->GetIndex(), current_node);
239 std::vector<std::shared_ptr<Node2d>> next_nodes = std::move(GenerateNextNodes(current_node));
240 for (auto& next_node : next_nodes) {
241 if (!CheckConstraints(next_node)) {
242 continue;
243 }
244 if (dp_map_.find(next_node->GetIndex()) != dp_map_.end()) {
245 continue;
246 }
247 if (open_set.find(next_node->GetIndex()) == open_set.end()) {
248 ++explored_node_num;
249 next_node->SetPreNode(current_node);
250 open_set.emplace(next_node->GetIndex(), next_node);
251 open_pq.emplace(next_node->GetIndex(), next_node->GetCost());
252 } else {
253 if (open_set[next_node->GetIndex()]->GetCost() > next_node->GetCost()) {
254 open_set[next_node->GetIndex()]->SetCost(next_node->GetCost());
255 open_set[next_node->GetIndex()]->SetPreNode(current_node);
256 }
257 }
258 }
259 }
260 if (use_esdf_) {
261 AddSoftCost(soft_boundary_linesegments_vec);
262 }
263 ADEBUG << "explored node num is " << explored_node_num;
264 return true;
265}
266
267double GridSearch::CheckDpMap(const double sx, const double sy) {
268 std::string index = Node2d::CalcIndex(sx, sy, xy_grid_resolution_, XYbounds_);
269 if (dp_map_.find(index) != dp_map_.end()) {
270 return dp_map_[index]->GetCost() * xy_grid_resolution_;
271 } else {
272 return std::numeric_limits<double>::infinity();
273 }
274}
275
276double GridSearch::GetObstacleDistance(const double x, const double y) {
277 std::string index = Node2d::CalcIndex(x, y, xy_grid_resolution_, XYbounds_);
278 if (dp_map_.find(index) != dp_map_.end()) {
279 return dp_map_[index]->GetDistanceToObstacle();
280 } else {
281 return 0.0;
282 }
283}
284
285void GridSearch::LoadGridAStarResult(GridAStartResult* result) {
286 (*result).path_cost = final_node_->GetPathCost() * xy_grid_resolution_;
287 std::shared_ptr<Node2d> current_node = final_node_;
288 std::vector<double> grid_a_x;
289 std::vector<double> grid_a_y;
290 while (current_node->GetPreNode() != nullptr) {
291 grid_a_x.push_back(current_node->GetGridX() * xy_grid_resolution_ + XYbounds_[0]);
292 grid_a_y.push_back(current_node->GetGridY() * xy_grid_resolution_ + XYbounds_[2]);
293 current_node = current_node->GetPreNode();
294 }
295 std::reverse(grid_a_x.begin(), grid_a_x.end());
296 std::reverse(grid_a_y.begin(), grid_a_y.end());
297 (*result).x = std::move(grid_a_x);
298 (*result).y = std::move(grid_a_y);
299}
300} // namespace planning
301} // namespace apollo
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
GridSearch(const PlannerOpenSpaceConfig &open_space_conf)
double CheckDpMap(const double sx, const double sy)
bool GenerateDpMap(const double ex, const double ey, const std::vector< double > &XYbounds, const std::vector< std::vector< common::math::LineSegment2d > > &obstacles_linesegments_vec, const std::vector< std::vector< common::math::LineSegment2d > > &soft_boundary_linesegments_vec={{}})
bool GenerateAStarPath(const double sx, const double sy, const double ex, const double ey, const std::vector< double > &XYbounds, const std::vector< std::vector< common::math::LineSegment2d > > &obstacles_linesegments_vec, GridAStartResult *result)
double GetObstacleDistance(const double x, const double y)
static std::string CalcIndex(const double x, const double y, const double xy_resolution, const std::vector< double > &XYbounds)
Definition grid_search.h:96
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
class register implement
Definition arena_queue.h:37