Apollo 11.0
自动驾驶开放平台
dp_st_cost.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
21
22#include <algorithm>
23#include <limits>
24
29
30namespace apollo {
31namespace planning {
32namespace {
33constexpr double kInf = std::numeric_limits<double>::infinity();
34}
35
36DpStCost::DpStCost(const DpStSpeedOptimizerConfig& config, const double total_t,
37 const double total_s,
38 const std::vector<const Obstacle*>& obstacles,
39 const STDrivableBoundary& st_drivable_boundary,
40 const common::TrajectoryPoint& init_point)
41 : config_(config),
42 obstacles_(obstacles),
43 st_drivable_boundary_(st_drivable_boundary),
44 init_point_(init_point),
45 unit_t_(config.unit_t()),
46 total_s_(total_s) {
47 int index = 0;
48 for (const auto& obstacle : obstacles) {
49 boundary_map_[obstacle->path_st_boundary().id()] = index++;
50 }
51
52 AddToKeepClearRange(obstacles);
53
54 const auto dimension_t =
55 static_cast<uint32_t>(std::ceil(total_t / static_cast<double>(unit_t_))) +
56 1;
57 boundary_cost_.resize(obstacles_.size());
58 for (auto& vec : boundary_cost_) {
59 vec.resize(dimension_t, std::make_pair(-1.0, -1.0));
60 }
61 accel_cost_.fill(-1.0);
62 jerk_cost_.fill(-1.0);
63}
64
65void DpStCost::AddToKeepClearRange(
66 const std::vector<const Obstacle*>& obstacles) {
67 for (const auto& obstacle : obstacles) {
68 if (obstacle->path_st_boundary().IsEmpty()) {
69 continue;
70 }
71 if (obstacle->path_st_boundary().boundary_type() !=
73 continue;
74 }
75
76 double start_s = obstacle->path_st_boundary().min_s();
77 double end_s = obstacle->path_st_boundary().max_s();
78 keep_clear_range_.emplace_back(start_s, end_s);
79 }
80 SortAndMergeRange(&keep_clear_range_);
81}
82
83void DpStCost::SortAndMergeRange(
84 std::vector<std::pair<double, double>>* keep_clear_range) {
85 if (!keep_clear_range || keep_clear_range->empty()) {
86 return;
87 }
88 std::sort(keep_clear_range->begin(), keep_clear_range->end());
89 size_t i = 0;
90 size_t j = i + 1;
91 while (j < keep_clear_range->size()) {
92 if (keep_clear_range->at(i).second < keep_clear_range->at(j).first) {
93 ++i;
94 ++j;
95 } else {
96 keep_clear_range->at(i).second = std::max(keep_clear_range->at(i).second,
97 keep_clear_range->at(j).second);
98 ++j;
99 }
100 }
101 keep_clear_range->resize(i + 1);
102}
103
104bool DpStCost::InKeepClearRange(double s) const {
105 for (const auto& p : keep_clear_range_) {
106 if (p.first <= s && p.second >= s) {
107 return true;
108 }
109 }
110 return false;
111}
112
113double DpStCost::GetObstacleCost(const StGraphPoint& st_graph_point) {
114 const double s = st_graph_point.point().s();
115 const double t = st_graph_point.point().t();
116
117 double cost = 0.0;
118
119 if (FLAGS_use_st_drivable_boundary) {
120 // TODO(Jiancheng): move to configs
121 static constexpr double boundary_resolution = 0.1;
122 int index = static_cast<int>(t / boundary_resolution);
123 const double lower_bound =
124 st_drivable_boundary_.st_boundary(index).s_lower();
125 const double upper_bound =
126 st_drivable_boundary_.st_boundary(index).s_upper();
127
128 if (s > upper_bound || s < lower_bound) {
129 return kInf;
130 }
131 }
132
133 for (const auto* obstacle : obstacles_) {
134 // Not applying obstacle approaching cost to virtual obstacle like created
135 // stop fences
136 if (obstacle->IsVirtual()) {
137 continue;
138 }
139
140 // Stop obstacles are assumed to have a safety margin when mapping them out,
141 // so repelling force in dp st is not needed as it is designed to have adc
142 // stop right at the stop distance we design in prior mapping process
143 if (obstacle->LongitudinalDecision().has_stop()) {
144 continue;
145 }
146
147 auto boundary = obstacle->path_st_boundary();
148
149 if (boundary.min_s() > FLAGS_speed_lon_decision_horizon) {
150 continue;
151 }
152 if (t < boundary.min_t() || t > boundary.max_t()) {
153 continue;
154 }
155 if (boundary.IsPointInBoundary(st_graph_point.point())) {
156 return kInf;
157 }
158 double s_upper = 0.0;
159 double s_lower = 0.0;
160
161 int boundary_index = boundary_map_[boundary.id()];
162 if (boundary_cost_[boundary_index][st_graph_point.index_t()].first < 0.0) {
163 boundary.GetBoundarySRange(t, &s_upper, &s_lower);
164 boundary_cost_[boundary_index][st_graph_point.index_t()] =
165 std::make_pair(s_upper, s_lower);
166 } else {
167 s_upper = boundary_cost_[boundary_index][st_graph_point.index_t()].first;
168 s_lower = boundary_cost_[boundary_index][st_graph_point.index_t()].second;
169 }
170 if (s < s_lower) {
171 const double follow_distance_s = config_.safe_distance();
172 if (s + follow_distance_s < s_lower) {
173 continue;
174 } else {
175 auto s_diff = follow_distance_s - s_lower + s;
176 cost += config_.obstacle_weight() * config_.default_obstacle_cost() *
177 s_diff * s_diff;
178 }
179 } else if (s > s_upper) {
180 const double overtake_distance_s =
182 if (s > s_upper + overtake_distance_s) { // or calculated from velocity
183 continue;
184 } else {
185 auto s_diff = overtake_distance_s + s_upper - s;
186 cost += config_.obstacle_weight() * config_.default_obstacle_cost() *
187 s_diff * s_diff;
188 }
189 }
190 }
191 return cost * unit_t_;
192}
193
195 return (total_s_ - point.point().s()) * config_.spatial_potential_penalty();
196}
197
199 const STPoint& reference_point) const {
200 return config_.reference_weight() * (point.s() - reference_point.s()) *
201 (point.s() - reference_point.s()) * unit_t_;
202}
203
204double DpStCost::GetSpeedCost(const STPoint& first, const STPoint& second,
205 const double speed_limit,
206 const double cruise_speed) const {
207 double cost = 0.0;
208 const double speed = (second.s() - first.s()) / unit_t_;
209 if (speed < 0) {
210 return kInf;
211 }
212
213 const double max_adc_stop_speed = common::VehicleConfigHelper::Instance()
214 ->GetConfig()
215 .vehicle_param()
216 .max_abs_speed_when_stopped();
217 if (speed < max_adc_stop_speed && InKeepClearRange(second.s())) {
218 // first.s in range
219 cost += config_.keep_clear_low_speed_penalty() * unit_t_ *
220 config_.default_speed_cost();
221 }
222
223 double det_speed = (speed - speed_limit) / speed_limit;
224 if (det_speed > 0) {
225 cost += config_.exceed_speed_penalty() * config_.default_speed_cost() *
226 (det_speed * det_speed) * unit_t_;
227 } else if (det_speed < 0) {
228 cost += config_.low_speed_penalty() * config_.default_speed_cost() *
229 -det_speed * unit_t_;
230 }
231
232 if (config_.enable_dp_reference_speed()) {
233 double diff_speed = speed - cruise_speed;
234 cost += config_.reference_speed_penalty() * config_.default_speed_cost() *
235 fabs(diff_speed) * unit_t_;
236 }
237
238 return cost;
239}
240
241double DpStCost::GetAccelCost(const double accel) {
242 double cost = 0.0;
243 static constexpr double kEpsilon = 0.1;
244 static constexpr size_t kShift = 100;
245 const size_t accel_key = static_cast<size_t>(accel / kEpsilon + 0.5 + kShift);
246 DCHECK_LT(accel_key, accel_cost_.size());
247 if (accel_key >= accel_cost_.size()) {
248 return kInf;
249 }
250
251 if (accel_cost_.at(accel_key) < 0.0) {
252 const double accel_sq = accel * accel;
253 double max_acc = config_.max_acceleration();
254 double max_dec = config_.max_deceleration();
255 double accel_penalty = config_.accel_penalty();
256 double decel_penalty = config_.decel_penalty();
257
258 if (accel > 0.0) {
259 cost = accel_penalty * accel_sq;
260 } else {
261 cost = decel_penalty * accel_sq;
262 }
263 cost += accel_sq * decel_penalty * decel_penalty /
264 (1 + std::exp(1.0 * (accel - max_dec))) +
265 accel_sq * accel_penalty * accel_penalty /
266 (1 + std::exp(-1.0 * (accel - max_acc)));
267 accel_cost_.at(accel_key) = cost;
268 } else {
269 cost = accel_cost_.at(accel_key);
270 }
271 return cost * unit_t_;
272}
273
275 const STPoint& second,
276 const STPoint& third) {
277 double accel = (first.s() + third.s() - 2 * second.s()) / (unit_t_ * unit_t_);
278 return GetAccelCost(accel);
279}
280
281double DpStCost::GetAccelCostByTwoPoints(const double pre_speed,
282 const STPoint& pre_point,
283 const STPoint& curr_point) {
284 double current_speed = (curr_point.s() - pre_point.s()) / unit_t_;
285 double accel = (current_speed - pre_speed) / unit_t_;
286 return GetAccelCost(accel);
287}
288
289double DpStCost::JerkCost(const double jerk) {
290 double cost = 0.0;
291 static constexpr double kEpsilon = 0.1;
292 static constexpr size_t kShift = 200;
293 const size_t jerk_key = static_cast<size_t>(jerk / kEpsilon + 0.5 + kShift);
294 if (jerk_key >= jerk_cost_.size()) {
295 return kInf;
296 }
297
298 if (jerk_cost_.at(jerk_key) < 0.0) {
299 double jerk_sq = jerk * jerk;
300 if (jerk > 0) {
301 cost = config_.positive_jerk_coeff() * jerk_sq * unit_t_;
302 } else {
303 cost = config_.negative_jerk_coeff() * jerk_sq * unit_t_;
304 }
305 jerk_cost_.at(jerk_key) = cost;
306 } else {
307 cost = jerk_cost_.at(jerk_key);
308 }
309
310 // TODO(All): normalize to unit_t_
311 return cost;
312}
313
315 const STPoint& second,
316 const STPoint& third,
317 const STPoint& fourth) {
318 double jerk = (fourth.s() - 3 * third.s() + 3 * second.s() - first.s()) /
319 (unit_t_ * unit_t_ * unit_t_);
320 return JerkCost(jerk);
321}
322
323double DpStCost::GetJerkCostByTwoPoints(const double pre_speed,
324 const double pre_acc,
325 const STPoint& pre_point,
326 const STPoint& curr_point) {
327 const double curr_speed = (curr_point.s() - pre_point.s()) / unit_t_;
328 const double curr_accel = (curr_speed - pre_speed) / unit_t_;
329 const double jerk = (curr_accel - pre_acc) / unit_t_;
330 return JerkCost(jerk);
331}
332
333double DpStCost::GetJerkCostByThreePoints(const double first_speed,
334 const STPoint& first,
335 const STPoint& second,
336 const STPoint& third) {
337 const double pre_speed = (second.s() - first.s()) / unit_t_;
338 const double pre_acc = (pre_speed - first_speed) / unit_t_;
339 const double curr_speed = (third.s() - second.s()) / unit_t_;
340 const double curr_acc = (curr_speed - pre_speed) / unit_t_;
341 const double jerk = (curr_acc - pre_acc) / unit_t_;
342 return JerkCost(jerk);
343}
344
345} // namespace planning
346} // namespace apollo
double GetSpatialPotentialCost(const StGraphPoint &point)
double GetAccelCostByTwoPoints(const double pre_speed, const STPoint &first, const STPoint &second)
DpStCost(const DpStSpeedOptimizerConfig &config, const double total_t, const double total_s, const std::vector< const Obstacle * > &obstacles, const STDrivableBoundary &st_drivable_boundary, const common::TrajectoryPoint &init_point)
Definition dp_st_cost.cc:36
double GetJerkCostByThreePoints(const double first_speed, const STPoint &first_point, const STPoint &second_point, const STPoint &third_point)
double GetJerkCostByTwoPoints(const double pre_speed, const double pre_acc, const STPoint &pre_point, const STPoint &curr_point)
double GetReferenceCost(const STPoint &point, const STPoint &reference_point) const
double GetSpeedCost(const STPoint &first, const STPoint &second, const double speed_limit, const double cruise_speed) const
double GetJerkCostByFourPoints(const STPoint &first, const STPoint &second, const STPoint &third, const STPoint &fourth)
double GetAccelCostByThreePoints(const STPoint &first, const STPoint &second, const STPoint &third)
double GetObstacleCost(const StGraphPoint &point)
std::uint32_t index_t() const
const STPoint & point() const
Planning module main class.
class register implement
Definition arena_queue.h:37
Defines proper safety distance the ADC should keep from target obstacle considering different informa...
repeated STDrivableBoundaryInstance st_boundary