Apollo 11.0
自动驾驶开放平台
path_time_graph.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 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 <algorithm>
24#include <limits>
25
26#include "modules/common_msgs/planning_msgs/sl_boundary.pb.h"
27
32
33namespace apollo {
34namespace planning {
35
42
44 const std::vector<const Obstacle*>& obstacles,
45 const std::vector<PathPoint>& discretized_ref_points,
46 const ReferenceLineInfo* ptr_reference_line_info, const double s_start,
47 const double s_end, const double t_start, const double t_end,
48 const std::array<double, 3>& init_d) {
49 CHECK_LT(s_start, s_end);
50 CHECK_LT(t_start, t_end);
51 path_range_.first = s_start;
52 path_range_.second = s_end;
53 time_range_.first = t_start;
54 time_range_.second = t_end;
55 ptr_reference_line_info_ = ptr_reference_line_info;
56 init_d_ = init_d;
57
58 SetupObstacles(obstacles, discretized_ref_points);
59}
60
61SLBoundary PathTimeGraph::ComputeObstacleBoundary(
62 const std::vector<common::math::Vec2d>& vertices,
63 const std::vector<PathPoint>& discretized_ref_points) const {
64 double start_s(std::numeric_limits<double>::max());
65 double end_s(std::numeric_limits<double>::lowest());
66 double start_l(std::numeric_limits<double>::max());
67 double end_l(std::numeric_limits<double>::lowest());
68
69 for (const auto& point : vertices) {
70 auto sl_point = PathMatcher::GetPathFrenetCoordinate(discretized_ref_points,
71 point.x(), point.y());
72 start_s = std::fmin(start_s, sl_point.first);
73 end_s = std::fmax(end_s, sl_point.first);
74 start_l = std::fmin(start_l, sl_point.second);
75 end_l = std::fmax(end_l, sl_point.second);
76 }
77
78 SLBoundary sl_boundary;
79 sl_boundary.set_start_s(start_s);
80 sl_boundary.set_end_s(end_s);
81 sl_boundary.set_start_l(start_l);
82 sl_boundary.set_end_l(end_l);
83
84 return sl_boundary;
85}
86
87void PathTimeGraph::SetupObstacles(
88 const std::vector<const Obstacle*>& obstacles,
89 const std::vector<PathPoint>& discretized_ref_points) {
90 for (const Obstacle* obstacle : obstacles) {
91 if (obstacle->IsVirtual()) {
92 continue;
93 }
94 if (!obstacle->HasTrajectory()) {
95 SetStaticObstacle(obstacle, discretized_ref_points);
96 } else {
97 SetDynamicObstacle(obstacle, discretized_ref_points);
98 }
99 }
100
101 std::sort(static_obs_sl_boundaries_.begin(), static_obs_sl_boundaries_.end(),
102 [](const SLBoundary& sl0, const SLBoundary& sl1) {
103 return sl0.start_s() < sl1.start_s();
104 });
105
106 for (auto& path_time_obstacle : path_time_obstacle_map_) {
107 path_time_obstacles_.push_back(path_time_obstacle.second);
108 }
109}
110
111void PathTimeGraph::SetStaticObstacle(
112 const Obstacle* obstacle,
113 const std::vector<PathPoint>& discretized_ref_points) {
114 const Polygon2d& polygon = obstacle->PerceptionPolygon();
115
116 std::string obstacle_id = obstacle->Id();
117 SLBoundary sl_boundary =
118 ComputeObstacleBoundary(polygon.GetAllVertices(), discretized_ref_points);
119
120 double left_width = FLAGS_default_reference_line_width * 0.5;
121 double right_width = FLAGS_default_reference_line_width * 0.5;
122 ptr_reference_line_info_->reference_line().GetLaneWidth(
123 sl_boundary.start_s(), &left_width, &right_width);
124 if (sl_boundary.start_s() > path_range_.second ||
125 sl_boundary.end_s() < path_range_.first ||
126 sl_boundary.start_l() > left_width ||
127 sl_boundary.end_l() < -right_width) {
128 ADEBUG << "Obstacle [" << obstacle_id << "] is out of range.";
129 return;
130 }
131
132 path_time_obstacle_map_[obstacle_id].set_id(obstacle_id);
133 path_time_obstacle_map_[obstacle_id].set_bottom_left_point(
134 SetPathTimePoint(obstacle_id, sl_boundary.start_s(), 0.0));
135 path_time_obstacle_map_[obstacle_id].set_bottom_right_point(SetPathTimePoint(
136 obstacle_id, sl_boundary.start_s(), FLAGS_trajectory_time_length));
137 path_time_obstacle_map_[obstacle_id].set_upper_left_point(
138 SetPathTimePoint(obstacle_id, sl_boundary.end_s(), 0.0));
139 path_time_obstacle_map_[obstacle_id].set_upper_right_point(SetPathTimePoint(
140 obstacle_id, sl_boundary.end_s(), FLAGS_trajectory_time_length));
141 static_obs_sl_boundaries_.push_back(std::move(sl_boundary));
142 ADEBUG << "ST-Graph mapping static obstacle: " << obstacle_id
143 << ", start_s : " << sl_boundary.start_s()
144 << ", end_s : " << sl_boundary.end_s()
145 << ", start_l : " << sl_boundary.start_l()
146 << ", end_l : " << sl_boundary.end_l();
147}
148
149void PathTimeGraph::SetDynamicObstacle(
150 const Obstacle* obstacle,
151 const std::vector<PathPoint>& discretized_ref_points) {
152 double relative_time = time_range_.first;
153 while (relative_time < time_range_.second) {
154 TrajectoryPoint point = obstacle->GetPointAtTime(relative_time);
155 Box2d box = obstacle->GetBoundingBox(point);
156 SLBoundary sl_boundary =
157 ComputeObstacleBoundary(box.GetAllCorners(), discretized_ref_points);
158
159 double left_width = FLAGS_default_reference_line_width * 0.5;
160 double right_width = FLAGS_default_reference_line_width * 0.5;
161 ptr_reference_line_info_->reference_line().GetLaneWidth(
162 sl_boundary.start_s(), &left_width, &right_width);
163
164 // The obstacle is not shown on the region to be considered.
165 if (sl_boundary.start_s() > path_range_.second ||
166 sl_boundary.end_s() < path_range_.first ||
167 sl_boundary.start_l() > left_width ||
168 sl_boundary.end_l() < -right_width) {
169 if (path_time_obstacle_map_.find(obstacle->Id()) !=
170 path_time_obstacle_map_.end()) {
171 break;
172 }
173 relative_time += FLAGS_trajectory_time_resolution;
174 continue;
175 }
176
177 if (path_time_obstacle_map_.find(obstacle->Id()) ==
178 path_time_obstacle_map_.end()) {
179 path_time_obstacle_map_[obstacle->Id()].set_id(obstacle->Id());
180
181 path_time_obstacle_map_[obstacle->Id()].set_bottom_left_point(
182 SetPathTimePoint(obstacle->Id(), sl_boundary.start_s(),
183 relative_time));
184 path_time_obstacle_map_[obstacle->Id()].set_upper_left_point(
185 SetPathTimePoint(obstacle->Id(), sl_boundary.end_s(), relative_time));
186 }
187
188 path_time_obstacle_map_[obstacle->Id()].set_bottom_right_point(
189 SetPathTimePoint(obstacle->Id(), sl_boundary.start_s(), relative_time));
190 path_time_obstacle_map_[obstacle->Id()].set_upper_right_point(
191 SetPathTimePoint(obstacle->Id(), sl_boundary.end_s(), relative_time));
192 relative_time += FLAGS_trajectory_time_resolution;
193 }
194}
195
196STPoint PathTimeGraph::SetPathTimePoint(const std::string& obstacle_id,
197 const double s, const double t) const {
198 STPoint path_time_point(s, t);
199 return path_time_point;
200}
201
202const std::vector<STBoundary>& PathTimeGraph::GetPathTimeObstacles() const {
203 return path_time_obstacles_;
204}
205
206bool PathTimeGraph::GetPathTimeObstacle(const std::string& obstacle_id,
207 STBoundary* path_time_obstacle) {
208 if (path_time_obstacle_map_.find(obstacle_id) ==
209 path_time_obstacle_map_.end()) {
210 return false;
211 }
212 *path_time_obstacle = path_time_obstacle_map_[obstacle_id];
213 return true;
214}
215
216std::vector<std::pair<double, double>> PathTimeGraph::GetPathBlockingIntervals(
217 const double t) const {
218 ACHECK(time_range_.first <= t && t <= time_range_.second);
219 std::vector<std::pair<double, double>> intervals;
220 for (const auto& pt_obstacle : path_time_obstacles_) {
221 if (t > pt_obstacle.max_t() || t < pt_obstacle.min_t()) {
222 continue;
223 }
224 double s_upper = lerp(pt_obstacle.upper_left_point().s(),
225 pt_obstacle.upper_left_point().t(),
226 pt_obstacle.upper_right_point().s(),
227 pt_obstacle.upper_right_point().t(), t);
228
229 double s_lower = lerp(pt_obstacle.bottom_left_point().s(),
230 pt_obstacle.bottom_left_point().t(),
231 pt_obstacle.bottom_right_point().s(),
232 pt_obstacle.bottom_right_point().t(), t);
233
234 intervals.emplace_back(s_lower, s_upper);
235 }
236 return intervals;
237}
238
239std::vector<std::vector<std::pair<double, double>>>
241 const double t_end,
242 const double t_resolution) {
243 std::vector<std::vector<std::pair<double, double>>> intervals;
244 for (double t = t_start; t <= t_end; t += t_resolution) {
245 intervals.push_back(GetPathBlockingIntervals(t));
246 }
247 return intervals;
248}
249
250std::pair<double, double> PathTimeGraph::get_path_range() const {
251 return path_range_;
252}
253
254std::pair<double, double> PathTimeGraph::get_time_range() const {
255 return time_range_;
256}
257
259 const std::string& obstacle_id, const double s_dist,
260 const double t_min_density) const {
261 ACHECK(t_min_density > 0.0);
262 std::vector<STPoint> pt_pairs;
263 if (path_time_obstacle_map_.find(obstacle_id) ==
264 path_time_obstacle_map_.end()) {
265 return pt_pairs;
266 }
267
268 const auto& pt_obstacle = path_time_obstacle_map_.at(obstacle_id);
269
270 double s0 = 0.0;
271 double s1 = 0.0;
272
273 double t0 = 0.0;
274 double t1 = 0.0;
275 if (s_dist > 0.0) {
276 s0 = pt_obstacle.upper_left_point().s();
277 s1 = pt_obstacle.upper_right_point().s();
278
279 t0 = pt_obstacle.upper_left_point().t();
280 t1 = pt_obstacle.upper_right_point().t();
281 } else {
282 s0 = pt_obstacle.bottom_left_point().s();
283 s1 = pt_obstacle.bottom_right_point().s();
284
285 t0 = pt_obstacle.bottom_left_point().t();
286 t1 = pt_obstacle.bottom_right_point().t();
287 }
288
289 double time_gap = t1 - t0;
290 ACHECK(time_gap > -FLAGS_numerical_epsilon);
291 time_gap = std::fabs(time_gap);
292
293 size_t num_sections = static_cast<size_t>(time_gap / t_min_density + 1);
294 double t_interval = time_gap / static_cast<double>(num_sections);
295
296 for (size_t i = 0; i <= num_sections; ++i) {
297 double t = t_interval * static_cast<double>(i) + t0;
298 double s = lerp(s0, t0, s1, t1, t) + s_dist;
299
300 STPoint ptt;
301 ptt.set_t(t);
302 ptt.set_s(s);
303 pt_pairs.push_back(std::move(ptt));
304 }
305
306 return pt_pairs;
307}
308
309bool PathTimeGraph::IsObstacleInGraph(const std::string& obstacle_id) {
310 return path_time_obstacle_map_.find(obstacle_id) !=
311 path_time_obstacle_map_.end();
312}
313
314std::vector<std::pair<double, double>> PathTimeGraph::GetLateralBounds(
315 const double s_start, const double s_end, const double s_resolution) {
316 CHECK_LT(s_start, s_end);
317 CHECK_GT(s_resolution, FLAGS_numerical_epsilon);
318 std::vector<std::pair<double, double>> bounds;
319 std::vector<double> discretized_path;
320 double s_range = s_end - s_start;
321 double s_curr = s_start;
322 size_t num_bound = static_cast<size_t>(s_range / s_resolution);
323
324 const auto& vehicle_config =
325 common::VehicleConfigHelper::Instance()->GetConfig();
326 double ego_width = vehicle_config.vehicle_param().width();
327
328 // Initialize bounds by reference line width
329 for (size_t i = 0; i < num_bound; ++i) {
330 double left_width = FLAGS_default_reference_line_width / 2.0;
331 double right_width = FLAGS_default_reference_line_width / 2.0;
332 ptr_reference_line_info_->reference_line().GetLaneWidth(s_curr, &left_width,
333 &right_width);
334 double ego_d_lower = init_d_[0] - ego_width / 2.0;
335 double ego_d_upper = init_d_[0] + ego_width / 2.0;
336 bounds.emplace_back(
337 std::min(-right_width, ego_d_lower - FLAGS_bound_buffer),
338 std::max(left_width, ego_d_upper + FLAGS_bound_buffer));
339 discretized_path.push_back(s_curr);
340 s_curr += s_resolution;
341 }
342
343 for (const SLBoundary& static_sl_boundary : static_obs_sl_boundaries_) {
344 UpdateLateralBoundsByObstacle(static_sl_boundary, discretized_path, s_start,
345 s_end, &bounds);
346 }
347
348 for (size_t i = 0; i < bounds.size(); ++i) {
349 bounds[i].first += ego_width / 2.0;
350 bounds[i].second -= ego_width / 2.0;
351 if (bounds[i].first >= bounds[i].second) {
352 bounds[i].first = 0.0;
353 bounds[i].second = 0.0;
354 }
355 }
356 return bounds;
357}
358
359void PathTimeGraph::UpdateLateralBoundsByObstacle(
360 const SLBoundary& sl_boundary, const std::vector<double>& discretized_path,
361 const double s_start, const double s_end,
362 std::vector<std::pair<double, double>>* const bounds) {
363 if (sl_boundary.start_s() > s_end || sl_boundary.end_s() < s_start) {
364 return;
365 }
366 auto start_iter = std::lower_bound(
367 discretized_path.begin(), discretized_path.end(), sl_boundary.start_s());
368 auto end_iter = std::upper_bound(
369 discretized_path.begin(), discretized_path.end(), sl_boundary.start_s());
370 size_t start_index = start_iter - discretized_path.begin();
371 size_t end_index = end_iter - discretized_path.begin();
372 if (sl_boundary.end_l() > -FLAGS_numerical_epsilon &&
373 sl_boundary.start_l() < FLAGS_numerical_epsilon) {
374 for (size_t i = start_index; i < end_index; ++i) {
375 bounds->operator[](i).first = -FLAGS_numerical_epsilon;
376 bounds->operator[](i).second = FLAGS_numerical_epsilon;
377 }
378 return;
379 }
380 if (sl_boundary.end_l() < FLAGS_numerical_epsilon) {
381 for (size_t i = start_index; i < std::min(end_index + 1, bounds->size());
382 ++i) {
383 bounds->operator[](i).first =
384 std::max(bounds->operator[](i).first,
385 sl_boundary.end_l() + FLAGS_nudge_buffer);
386 }
387 return;
388 }
389 if (sl_boundary.start_l() > -FLAGS_numerical_epsilon) {
390 for (size_t i = start_index; i < std::min(end_index + 1, bounds->size());
391 ++i) {
392 bounds->operator[](i).second =
393 std::min(bounds->operator[](i).second,
394 sl_boundary.start_l() - FLAGS_nudge_buffer);
395 }
396 return;
397 }
398}
399
400} // namespace planning
401} // namespace apollo
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
static std::pair< double, double > GetPathFrenetCoordinate(const std::vector< PathPoint > &reference_line, const double x, const double y)
The class of polygon in 2-D.
Definition polygon2d.h:42
std::vector< STPoint > GetObstacleSurroundingPoints(const std::string &obstacle_id, const double s_dist, const double t_density) const
std::vector< std::pair< double, double > > GetPathBlockingIntervals(const double t) const
PathTimeGraph(const std::vector< const Obstacle * > &obstacles, const std::vector< common::PathPoint > &discretized_ref_points, const ReferenceLineInfo *ptr_reference_line_info, const double s_start, const double s_end, const double t_start, const double t_end, const std::array< double, 3 > &init_d)
std::pair< double, double > get_path_range() const
bool GetPathTimeObstacle(const std::string &obstacle_id, STBoundary *path_time_obstacle)
bool IsObstacleInGraph(const std::string &obstacle_id)
std::vector< std::pair< double, double > > GetLateralBounds(const double s_start, const double s_end, const double s_resolution)
std::pair< double, double > get_time_range() const
const std::vector< STBoundary > & GetPathTimeObstacles() const
ReferenceLineInfo holds all data for one reference line.
const ReferenceLine & reference_line() const
bool GetLaneWidth(const double s, double *const lane_left_width, double *const lane_right_width) const
void set_s(const double s)
Definition st_point.cc:38
void set_t(const double t)
Definition st_point.cc:40
Planning module main class.
Linear interpolation functions.
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
T lerp(const T &x0, const double t0, const T &x1, const double t1, const double t)
Linear interpolation between two points of type T.
class register implement
Definition arena_queue.h:37