Apollo 10.0
自动驾驶开放平台
st_boundary.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 "cyber/common/log.h"
27
28namespace apollo {
29namespace planning {
30
33
35 const std::vector<std::pair<STPoint, STPoint>>& point_pairs,
36 bool is_accurate_boundary) {
37 ACHECK(IsValid(point_pairs)) << "The input point_pairs are NOT valid";
38
39 std::vector<std::pair<STPoint, STPoint>> reduced_pairs(point_pairs);
40 if (!is_accurate_boundary) {
41 RemoveRedundantPoints(&reduced_pairs);
42 }
43
44 for (const auto& item : reduced_pairs) {
45 // use same t for both points
46 const double t = item.first.t();
47 lower_points_.emplace_back(item.first.s(), t);
48 upper_points_.emplace_back(item.second.s(), t);
49 }
50
51 for (const auto& point : lower_points_) {
52 points_.emplace_back(point.t(), point.s());
53 }
54 for (auto rit = upper_points_.rbegin(); rit != upper_points_.rend(); ++rit) {
55 points_.emplace_back(rit->t(), rit->s());
56 }
57
59
60 for (const auto& point : lower_points_) {
61 min_s_ = std::fmin(min_s_, point.s());
62 }
63 for (const auto& point : upper_points_) {
64 max_s_ = std::fmax(max_s_, point.s());
65 }
66 min_t_ = lower_points_.front().t();
67 max_t_ = lower_points_.back().t();
68
69 obstacle_road_right_ending_t_ = std::numeric_limits<double>::lowest();
70}
71
73 const std::vector<STPoint>& lower_points,
74 const std::vector<STPoint>& upper_points) {
75 if (lower_points.size() != upper_points.size() || lower_points.size() < 2) {
76 return STBoundary();
77 }
78
79 std::vector<std::pair<STPoint, STPoint>> point_pairs;
80 for (size_t i = 0; i < lower_points.size(); ++i) {
81 point_pairs.emplace_back(
82 STPoint(lower_points.at(i).s(), lower_points.at(i).t()),
83 STPoint(upper_points.at(i).s(), upper_points.at(i).t()));
84 }
85 return STBoundary(point_pairs);
86}
87
89 const std::vector<STPoint>& lower_points,
90 const std::vector<STPoint>& upper_points) {
91 if (lower_points.size() != upper_points.size() || lower_points.size() < 2) {
92 return STBoundary();
93 }
94
95 std::vector<std::pair<STPoint, STPoint>> point_pairs;
96 for (size_t i = 0; i < lower_points.size(); ++i) {
97 point_pairs.emplace_back(
98 STPoint(lower_points.at(i).s(), lower_points.at(i).t()),
99 STPoint(upper_points.at(i).s(), upper_points.at(i).t()));
100 }
101 return STBoundary(point_pairs, true);
102}
103
105 if (type == BoundaryType::FOLLOW) {
106 return "FOLLOW";
107 } else if (type == BoundaryType::KEEP_CLEAR) {
108 return "KEEP_CLEAR";
109 } else if (type == BoundaryType::OVERTAKE) {
110 return "OVERTAKE";
111 } else if (type == BoundaryType::STOP) {
112 return "STOP";
113 } else if (type == BoundaryType::YIELD) {
114 return "YIELD";
115 } else if (type == BoundaryType::UNKNOWN) {
116 return "UNKNOWN";
117 }
118 AWARN << "Unknown boundary type " << static_cast<int>(type)
119 << ", treated as UNKNOWN";
120 return "UNKNOWN";
121}
122
123bool STBoundary::GetUnblockSRange(const double curr_time, double* s_upper,
124 double* s_lower) const {
125 CHECK_NOTNULL(s_upper);
126 CHECK_NOTNULL(s_lower);
127
128 *s_upper = FLAGS_speed_lon_decision_horizon;
129 *s_lower = 0.0;
130 if (curr_time < min_t_ || curr_time > max_t_) {
131 return true;
132 }
133
134 size_t left = 0;
135 size_t right = 0;
136 if (!GetIndexRange(lower_points_, curr_time, &left, &right)) {
137 AERROR << "Fail to get index range.";
138 return false;
139 }
140
141 if (curr_time > upper_points_[right].t()) {
142 return true;
143 }
144
145 const double r =
146 (left == right
147 ? 0.0
148 : (curr_time - upper_points_[left].t()) /
149 (upper_points_[right].t() - upper_points_[left].t()));
150
151 double upper_cross_s =
152 upper_points_[left].s() +
153 r * (upper_points_[right].s() - upper_points_[left].s());
154 double lower_cross_s =
155 lower_points_[left].s() +
156 r * (lower_points_[right].s() - lower_points_[left].s());
157
158 if (boundary_type_ == BoundaryType::STOP ||
159 boundary_type_ == BoundaryType::YIELD ||
160 boundary_type_ == BoundaryType::FOLLOW) {
161 *s_upper = lower_cross_s;
162 } else if (boundary_type_ == BoundaryType::OVERTAKE) {
163 *s_lower = std::fmax(*s_lower, upper_cross_s);
164 } else {
165 ADEBUG << "boundary_type is not supported. boundary_type: "
166 << static_cast<int>(boundary_type_);
167 return false;
168 }
169 return true;
170}
171
172bool STBoundary::GetBoundarySRange(const double curr_time, double* s_upper,
173 double* s_lower) const {
174 CHECK_NOTNULL(s_upper);
175 CHECK_NOTNULL(s_lower);
176 if (curr_time < min_t_ || curr_time > max_t_) {
177 return false;
178 }
179
180 size_t left = 0;
181 size_t right = 0;
182 if (!GetIndexRange(lower_points_, curr_time, &left, &right)) {
183 AERROR << "Fail to get index range.";
184 return false;
185 }
186 const double r =
187 (left == right
188 ? 0.0
189 : (curr_time - upper_points_[left].t()) /
190 (upper_points_[right].t() - upper_points_[left].t()));
191
192 *s_upper = upper_points_[left].s() +
193 r * (upper_points_[right].s() - upper_points_[left].s());
194 *s_lower = lower_points_[left].s() +
195 r * (lower_points_[right].s() - lower_points_[left].s());
196
197 *s_upper = std::fmin(*s_upper, FLAGS_speed_lon_decision_horizon);
198 *s_lower = std::fmax(*s_lower, 0.0);
199 return true;
200}
201
202bool STBoundary::GetBoundarySlopes(const double curr_time, double* ds_upper,
203 double* ds_lower) const {
204 if (ds_upper == nullptr || ds_lower == nullptr) {
205 return false;
206 }
207 if (curr_time < min_t_ || curr_time > max_t_) {
208 return false;
209 }
210
211 static constexpr double kTimeIncrement = 0.05;
212 double t_prev = curr_time - kTimeIncrement;
213 double prev_s_upper = 0.0;
214 double prev_s_lower = 0.0;
215 bool has_prev = GetBoundarySRange(t_prev, &prev_s_upper, &prev_s_lower);
216 double t_next = curr_time + kTimeIncrement;
217 double next_s_upper = 0.0;
218 double next_s_lower = 0.0;
219 bool has_next = GetBoundarySRange(t_next, &next_s_upper, &next_s_lower);
220 double curr_s_upper = 0.0;
221 double curr_s_lower = 0.0;
222 GetBoundarySRange(curr_time, &curr_s_upper, &curr_s_lower);
223 if (!has_prev && !has_next) {
224 return false;
225 }
226 if (has_prev && has_next) {
227 *ds_upper = ((next_s_upper - curr_s_upper) / kTimeIncrement +
228 (curr_s_upper - prev_s_upper) / kTimeIncrement) *
229 0.5;
230 *ds_lower = ((next_s_lower - curr_s_lower) / kTimeIncrement +
231 (curr_s_lower - prev_s_lower) / kTimeIncrement) *
232 0.5;
233 return true;
234 }
235 if (has_prev) {
236 *ds_upper = (curr_s_upper - prev_s_upper) / kTimeIncrement;
237 *ds_lower = (curr_s_lower - prev_s_lower) / kTimeIncrement;
238 } else {
239 *ds_upper = (next_s_upper - curr_s_upper) / kTimeIncrement;
240 *ds_lower = (next_s_lower - curr_s_lower) / kTimeIncrement;
241 }
242 return true;
243}
244
245bool STBoundary::IsPointInBoundary(const STPoint& st_point) const {
246 if (st_point.t() <= min_t_ || st_point.t() >= max_t_) {
247 return false;
248 }
249 size_t left = 0;
250 size_t right = 0;
251 if (!GetIndexRange(lower_points_, st_point.t(), &left, &right)) {
252 AERROR << "failed to get index range.";
253 return false;
254 }
255 const double check_upper = common::math::CrossProd(
256 st_point, upper_points_[left], upper_points_[right]);
257 const double check_lower = common::math::CrossProd(
258 st_point, lower_points_[left], lower_points_[right]);
259
260 return (check_upper * check_lower < 0);
261}
262
263STBoundary STBoundary::ExpandByS(const double s) const {
264 if (lower_points_.empty()) {
265 return STBoundary();
266 }
267 std::vector<std::pair<STPoint, STPoint>> point_pairs;
268 for (size_t i = 0; i < lower_points_.size(); ++i) {
269 point_pairs.emplace_back(
270 STPoint(lower_points_[i].s() - s, lower_points_[i].t()),
271 STPoint(upper_points_[i].s() + s, upper_points_[i].t()));
272 }
273 return STBoundary(std::move(point_pairs));
274}
275
276STBoundary STBoundary::ExpandByT(const double t) const {
277 if (lower_points_.empty()) {
278 AERROR << "The current st_boundary has NO points.";
279 return STBoundary();
280 }
281
282 std::vector<std::pair<STPoint, STPoint>> point_pairs;
283
284 const double left_delta_t = lower_points_[1].t() - lower_points_[0].t();
285 const double lower_left_delta_s = lower_points_[1].s() - lower_points_[0].s();
286 const double upper_left_delta_s = upper_points_[1].s() - upper_points_[0].s();
287
288 point_pairs.emplace_back(
289 STPoint(lower_points_[0].s() - t * lower_left_delta_s / left_delta_t,
290 lower_points_[0].t() - t),
291 STPoint(upper_points_[0].s() - t * upper_left_delta_s / left_delta_t,
292 upper_points_.front().t() - t));
293
294 const double kMinSEpsilon = 1e-3;
295 point_pairs.front().first.set_s(
296 std::fmin(point_pairs.front().second.s() - kMinSEpsilon,
297 point_pairs.front().first.s()));
298
299 for (size_t i = 0; i < lower_points_.size(); ++i) {
300 point_pairs.emplace_back(lower_points_[i], upper_points_[i]);
301 }
302
303 size_t length = lower_points_.size();
304 DCHECK_GE(length, 2U);
305
306 const double right_delta_t =
307 lower_points_[length - 1].t() - lower_points_[length - 2].t();
308 const double lower_right_delta_s =
309 lower_points_[length - 1].s() - lower_points_[length - 2].s();
310 const double upper_right_delta_s =
311 upper_points_[length - 1].s() - upper_points_[length - 2].s();
312
313 point_pairs.emplace_back(STPoint(lower_points_.back().s() +
314 t * lower_right_delta_s / right_delta_t,
315 lower_points_.back().t() + t),
316 STPoint(upper_points_.back().s() +
317 t * upper_right_delta_s / right_delta_t,
318 upper_points_.back().t() + t));
319 point_pairs.back().second.set_s(
320 std::fmax(point_pairs.back().second.s(),
321 point_pairs.back().first.s() + kMinSEpsilon));
322
323 return STBoundary(std::move(point_pairs));
324}
325
327 return boundary_type_;
328}
329void STBoundary::SetBoundaryType(const BoundaryType& boundary_type) {
330 boundary_type_ = boundary_type;
331}
332
333const std::string& STBoundary::id() const { return id_; }
334
335void STBoundary::set_id(const std::string& id) { id_ = id; }
336
338 return characteristic_length_;
339}
340
341void STBoundary::SetCharacteristicLength(const double characteristic_length) {
342 characteristic_length_ = characteristic_length;
343}
344
345double STBoundary::min_s() const { return min_s_; }
346double STBoundary::min_t() const { return min_t_; }
347double STBoundary::max_s() const { return max_s_; }
348double STBoundary::max_t() const { return max_t_; }
349
350STBoundary STBoundary::CutOffByT(const double t) const {
351 std::vector<STPoint> lower_points;
352 std::vector<STPoint> upper_points;
353 for (size_t i = 0; i < lower_points_.size() && i < upper_points_.size();
354 ++i) {
355 if (lower_points_[i].t() < t) {
356 continue;
357 }
358 lower_points.push_back(lower_points_[i]);
359 upper_points.push_back(upper_points_[i]);
360 }
362}
363
365 DCHECK(!upper_points_.empty()) << "StBoundary has zero points.";
366 return upper_points_.front();
367}
368
370 DCHECK(!upper_points_.empty()) << "StBoundary has zero points.";
371 return upper_points_.back();
372}
373
375 DCHECK(!lower_points_.empty()) << "StBoundary has zero points.";
376 return lower_points_.front();
377}
378
380 DCHECK(!lower_points_.empty()) << "StBoundary has zero points.";
381 return lower_points_.back();
382}
383
385 upper_left_point_ = std::move(st_point);
386}
387
389 upper_right_point_ = std::move(st_point);
390}
391
393 bottom_left_point_ = std::move(st_point);
394}
395
397 bottom_right_point_ = std::move(st_point);
398}
399
401// Private functions for internal usage.
402
403bool STBoundary::IsValid(
404 const std::vector<std::pair<STPoint, STPoint>>& point_pairs) const {
405 if (point_pairs.size() < 2) {
406 AERROR << "point_pairs.size() must >= 2, but current point_pairs.size() = "
407 << point_pairs.size();
408 return false;
409 }
410
411 static constexpr double kStBoundaryEpsilon = 1e-9;
412 static constexpr double kMinDeltaT = 1e-6;
413 for (size_t i = 0; i < point_pairs.size(); ++i) {
414 const auto& curr_lower = point_pairs[i].first;
415 const auto& curr_upper = point_pairs[i].second;
416 if (curr_upper.s() < curr_lower.s()) {
417 AERROR << "ST-boundary's upper-s must >= lower-s";
418 return false;
419 }
420 if (std::fabs(curr_lower.t() - curr_upper.t()) > kStBoundaryEpsilon) {
421 AERROR << "Points in every ST-point pair should be at the same time.";
422 return false;
423 }
424 if (i + 1 != point_pairs.size()) {
425 const auto& next_lower = point_pairs[i + 1].first;
426 const auto& next_upper = point_pairs[i + 1].second;
427 if (std::fmax(curr_lower.t(), curr_upper.t()) + kMinDeltaT >=
428 std::fmin(next_lower.t(), next_upper.t())) {
429 AERROR << "Latter points should have larger t: "
430 << "curr_lower[" << curr_lower.DebugString() << "] curr_upper["
431 << curr_upper.DebugString() << "] next_lower["
432 << next_lower.DebugString() << "] next_upper["
433 << next_upper.DebugString() << "]";
434 return false;
435 }
436 }
437 }
438 return true;
439}
440
441bool STBoundary::IsPointNear(const common::math::LineSegment2d& seg,
442 const Vec2d& point, const double max_dist) {
443 return seg.DistanceSquareTo(point) < max_dist * max_dist;
444}
445
446void STBoundary::RemoveRedundantPoints(
447 std::vector<std::pair<STPoint, STPoint>>* point_pairs) {
448 if (!point_pairs || point_pairs->size() <= 2) {
449 return;
450 }
451
452 const double kMaxDist = 0.1;
453 size_t i = 0;
454 size_t j = 1;
455
456 while (i < point_pairs->size() && j + 1 < point_pairs->size()) {
457 LineSegment2d lower_seg(point_pairs->at(i).first,
458 point_pairs->at(j + 1).first);
459 LineSegment2d upper_seg(point_pairs->at(i).second,
460 point_pairs->at(j + 1).second);
461 if (!IsPointNear(lower_seg, point_pairs->at(j).first, kMaxDist) ||
462 !IsPointNear(upper_seg, point_pairs->at(j).second, kMaxDist)) {
463 ++i;
464 if (i != j) {
465 point_pairs->at(i) = point_pairs->at(j);
466 }
467 }
468 ++j;
469 }
470 point_pairs->at(++i) = point_pairs->back();
471 point_pairs->resize(i + 1);
472}
473
474bool STBoundary::GetIndexRange(const std::vector<STPoint>& points,
475 const double t, size_t* left,
476 size_t* right) const {
477 CHECK_NOTNULL(left);
478 CHECK_NOTNULL(right);
479 if (t < points.front().t() || t > points.back().t()) {
480 AERROR << "t is out of range. t = " << t;
481 return false;
482 }
483 auto comp = [](const STPoint& p, const double t) { return p.t() < t; };
484 auto first_ge = std::lower_bound(points.begin(), points.end(), t, comp);
485 size_t index = std::distance(points.begin(), first_ge);
486 if (index == 0) {
487 *left = *right = 0;
488 } else if (first_ge == points.end()) {
489 *left = *right = points.size() - 1;
490 } else {
491 *left = index - 1;
492 *right = index;
493 }
494 return true;
495}
496
497void STBoundary::PrintDebug(std::string suffix) const {
498 std::string type_name = TypeName(boundary_type_);
499 std::string key_name = type_name + id_ + suffix;
500 PrintPoints debug(key_name);
501 if (lower_points_.empty() || upper_points_.empty()) {
502 return;
503 }
504 for (auto pt : lower_points_) {
505 debug.AddPoint(pt.t(), pt.s());
506 }
507 for (auto iter = upper_points_.rbegin(); iter != upper_points_.rend();
508 iter++) {
509 debug.AddPoint(iter->t(), iter->s());
510 }
511 debug.AddPoint(lower_points_.front().t(), lower_points_.front().s());
512 debug.PrintToLog();
513}
514} // namespace planning
515} // namespace apollo
std::vector< Vec2d > points_
Definition polygon2d.h:379
const std::vector< Vec2d > & points() const
Get the vertices of the polygon.
Definition polygon2d.h:65
void BuildFromPoints(bool check_area=true)
Definition polygon2d.cc:293
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
void PrintToLog()
print curve to log
void AddPoint(double x, double y)
add points to curve
void set_bottom_right_point(STPoint st_point)
bool GetUnblockSRange(const double curr_time, double *s_upper, double *s_lower) const
const std::string & id() const
static std::string TypeName(BoundaryType type)
bool GetBoundarySlopes(const double curr_time, double *ds_upper, double *ds_lower) const
void set_id(const std::string &id)
STBoundary()=default
Constructors: STBoundary must be initialized with a vector of ST-point pairs.
static STBoundary CreateInstance(const std::vector< STPoint > &lower_points, const std::vector< STPoint > &upper_points)
Wrapper of the constructor (old).
void set_bottom_left_point(STPoint st_point)
void SetCharacteristicLength(const double characteristic_length)
std::vector< STPoint > lower_points() const
std::vector< STPoint > upper_points() const
BoundaryType boundary_type() const
STBoundary ExpandByT(const double t) const
void PrintDebug(std::string suffix="") const
static STBoundary CreateInstanceAccurate(const std::vector< STPoint > &lower_points, const std::vector< STPoint > &upper_points)
Wrapper of the constructor.
STBoundary ExpandByS(const double s) const
void set_upper_right_point(STPoint st_point)
STPoint bottom_right_point() const
bool IsPointInBoundary(const STPoint &st_point) const
bool GetBoundarySRange(const double curr_time, double *s_upper, double *s_lower) const
STPoint bottom_left_point() const
STBoundary CutOffByT(const double t) const
STPoint upper_right_point() const
void SetBoundaryType(const BoundaryType &boundary_type)
void set_upper_left_point(STPoint st_point)
STPoint upper_left_point() const
double characteristic_length() const
Planning module main class.
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AWARN
Definition log.h:43
Math-related util functions.
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
class register implement
Definition arena_queue.h:37