Apollo 11.0
自动驾驶开放平台
trajectory_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
22
23#include "modules/common_msgs/basic_msgs/pnc_point.pb.h"
24
29
30namespace apollo {
31namespace planning {
32
33TrajectoryCost::TrajectoryCost(const DpPolyPathConfig &config,
34 const ReferenceLine &reference_line,
35 const bool is_change_lane_path,
36 const std::vector<const Obstacle *> &obstacles,
37 const common::VehicleParam &vehicle_param,
38 const SpeedData &heuristic_speed_data,
39 const common::SLPoint &init_sl_point,
40 const SLBoundary &adc_sl_boundary)
41 : config_(config),
42 reference_line_(&reference_line),
43 is_change_lane_path_(is_change_lane_path),
44 vehicle_param_(vehicle_param),
45 heuristic_speed_data_(heuristic_speed_data),
46 init_sl_point_(init_sl_point),
47 adc_sl_boundary_(adc_sl_boundary) {
48 const double total_time =
49 std::min(heuristic_speed_data_.TotalTime(), FLAGS_prediction_total_time);
50
51 num_of_time_stamps_ = static_cast<uint32_t>(
52 std::floor(total_time / config.eval_time_interval()));
53
54 for (const auto *ptr_obstacle : obstacles) {
55 if (ptr_obstacle->IsIgnore()) {
56 continue;
57 } else if (ptr_obstacle->LongitudinalDecision().has_stop()) {
58 continue;
59 }
60 const auto &sl_boundary = ptr_obstacle->PerceptionSLBoundary();
61
62 const double adc_left_l =
63 init_sl_point_.l() + vehicle_param_.left_edge_to_center();
64 const double adc_right_l =
65 init_sl_point_.l() - vehicle_param_.right_edge_to_center();
66
67 if (adc_left_l + FLAGS_lateral_ignore_buffer < sl_boundary.start_l() ||
68 adc_right_l - FLAGS_lateral_ignore_buffer > sl_boundary.end_l()) {
69 continue;
70 }
71
72 bool is_bycycle_or_pedestrian =
73 (ptr_obstacle->Perception().type() ==
75 ptr_obstacle->Perception().type() ==
77
78 if (ptr_obstacle->IsVirtual()) {
79 // Virtual obstacle
80 continue;
81 } else if (ptr_obstacle->IsStatic() || is_bycycle_or_pedestrian) {
82 static_obstacle_sl_boundaries_.push_back(std::move(sl_boundary));
83 } else {
84 std::vector<Box2d> box_by_time;
85 for (uint32_t t = 0; t <= num_of_time_stamps_; ++t) {
86 TrajectoryPoint trajectory_point =
87 ptr_obstacle->GetPointAtTime(t * config.eval_time_interval());
88
89 Box2d obstacle_box = ptr_obstacle->GetBoundingBox(trajectory_point);
90 static constexpr double kBuff = 0.5;
91 Box2d expanded_obstacle_box =
92 Box2d(obstacle_box.center(), obstacle_box.heading(),
93 obstacle_box.length() + kBuff, obstacle_box.width() + kBuff);
94 box_by_time.push_back(expanded_obstacle_box);
95 }
96 dynamic_obstacle_boxes_.push_back(std::move(box_by_time));
97 }
98 }
99}
100
101ComparableCost TrajectoryCost::CalculatePathCost(
102 const QuinticPolynomialCurve1d &curve, const double start_s,
103 const double end_s, const uint32_t curr_level, const uint32_t total_level) {
104 ComparableCost cost;
105 double path_cost = 0.0;
106 std::function<double(const double)> quasi_softmax = [this](const double x) {
107 const double l0 = this->config_.path_l_cost_param_l0();
108 const double b = this->config_.path_l_cost_param_b();
109 const double k = this->config_.path_l_cost_param_k();
110 return (b + std::exp(-k * (x - l0))) / (1.0 + std::exp(-k * (x - l0)));
111 };
112
113 for (double curve_s = 0.0; curve_s < (end_s - start_s);
114 curve_s += config_.path_resolution()) {
115 const double l = curve.Evaluate(0, curve_s);
116
117 path_cost += l * l * config_.path_l_cost() * quasi_softmax(std::fabs(l));
118
119 const double dl = std::fabs(curve.Evaluate(1, curve_s));
120 if (IsOffRoad(curve_s + start_s, l, dl, is_change_lane_path_)) {
122 }
123
124 path_cost += dl * dl * config_.path_dl_cost();
125
126 const double ddl = std::fabs(curve.Evaluate(2, curve_s));
127 path_cost += ddl * ddl * config_.path_ddl_cost();
128 }
129 path_cost *= config_.path_resolution();
130
131 if (curr_level == total_level) {
132 const double end_l = curve.Evaluate(0, end_s - start_s);
133 path_cost +=
134 std::sqrt(end_l - init_sl_point_.l() / 2.0) * config_.path_end_l_cost();
135 }
136 cost.smoothness_cost = path_cost;
137 return cost;
138}
139
140bool TrajectoryCost::IsOffRoad(const double ref_s, const double l,
141 const double dl,
142 const bool is_change_lane_path) {
143 static constexpr double kIgnoreDistance = 5.0;
144 if (ref_s - init_sl_point_.s() < kIgnoreDistance) {
145 return false;
146 }
147 Vec2d rear_center(0.0, l);
148
150 Vec2d vec_to_center(
151 (param.front_edge_to_center() - param.back_edge_to_center()) / 2.0,
152 (param.left_edge_to_center() - param.right_edge_to_center()) / 2.0);
153
154 Vec2d rear_center_to_center = vec_to_center.rotate(std::atan(dl));
155 Vec2d center = rear_center + rear_center_to_center;
156 Vec2d front_center = center + rear_center_to_center;
157
158 const double buffer = 0.1; // in meters
159 const double r_w =
160 (param.left_edge_to_center() + param.right_edge_to_center()) / 2.0;
161 const double r_l = param.back_edge_to_center();
162 const double r = std::sqrt(r_w * r_w + r_l * r_l);
163
164 double left_width = 0.0;
165 double right_width = 0.0;
166 reference_line_->GetLaneWidth(ref_s, &left_width, &right_width);
167
168 double left_bound = std::max(init_sl_point_.l() + r + buffer, left_width);
169 double right_bound = std::min(init_sl_point_.l() - r - buffer, -right_width);
170 if (rear_center.y() + r + buffer / 2.0 > left_bound ||
171 rear_center.y() - r - buffer / 2.0 < right_bound) {
172 return true;
173 }
174 if (front_center.y() + r + buffer / 2.0 > left_bound ||
175 front_center.y() - r - buffer / 2.0 < right_bound) {
176 return true;
177 }
178
179 return false;
180}
181
182ComparableCost TrajectoryCost::CalculateStaticObstacleCost(
183 const QuinticPolynomialCurve1d &curve, const double start_s,
184 const double end_s) {
185 ComparableCost obstacle_cost;
186 for (double curr_s = start_s; curr_s <= end_s;
187 curr_s += config_.path_resolution()) {
188 const double curr_l = curve.Evaluate(0, curr_s - start_s);
189 for (const auto &obs_sl_boundary : static_obstacle_sl_boundaries_) {
190 obstacle_cost += GetCostFromObsSL(curr_s, curr_l, obs_sl_boundary);
191 }
192 }
193 obstacle_cost.safety_cost *= config_.path_resolution();
194 return obstacle_cost;
195}
196
197ComparableCost TrajectoryCost::CalculateDynamicObstacleCost(
198 const QuinticPolynomialCurve1d &curve, const double start_s,
199 const double end_s) const {
200 ComparableCost obstacle_cost;
201 if (dynamic_obstacle_boxes_.empty()) {
202 return obstacle_cost;
203 }
204
205 double time_stamp = 0.0;
206 for (size_t index = 0; index < num_of_time_stamps_;
207 ++index, time_stamp += config_.eval_time_interval()) {
208 common::SpeedPoint speed_point;
209 heuristic_speed_data_.EvaluateByTime(time_stamp, &speed_point);
210 double ref_s = speed_point.s() + init_sl_point_.s();
211 if (ref_s < start_s) {
212 continue;
213 }
214 if (ref_s > end_s) {
215 break;
216 }
217
218 const double s = ref_s - start_s; // s on spline curve
219 const double l = curve.Evaluate(0, s);
220 const double dl = curve.Evaluate(1, s);
221
222 const common::SLPoint sl = common::util::PointFactory::ToSLPoint(ref_s, l);
223 const Box2d ego_box = GetBoxFromSLPoint(sl, dl);
224 for (const auto &obstacle_trajectory : dynamic_obstacle_boxes_) {
225 obstacle_cost +=
226 GetCostBetweenObsBoxes(ego_box, obstacle_trajectory.at(index));
227 }
228 }
229 static constexpr double kDynamicObsWeight = 1e-6;
230 obstacle_cost.safety_cost *=
231 (config_.eval_time_interval() * kDynamicObsWeight);
232 return obstacle_cost;
233}
234
235ComparableCost TrajectoryCost::GetCostFromObsSL(
236 const double adc_s, const double adc_l, const SLBoundary &obs_sl_boundary) {
237 const auto &vehicle_param =
238 common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param();
239
240 ComparableCost obstacle_cost;
241 if (obs_sl_boundary.start_l() * obs_sl_boundary.end_l() <= 0.0) {
242 return obstacle_cost;
243 }
244
245 const double adc_front_s = adc_s + vehicle_param.front_edge_to_center();
246 const double adc_end_s = adc_s - vehicle_param.back_edge_to_center();
247 const double adc_left_l = adc_l + vehicle_param.left_edge_to_center();
248 const double adc_right_l = adc_l - vehicle_param.right_edge_to_center();
249
250 if (adc_left_l + FLAGS_lateral_ignore_buffer < obs_sl_boundary.start_l() ||
251 adc_right_l - FLAGS_lateral_ignore_buffer > obs_sl_boundary.end_l()) {
252 return obstacle_cost;
253 }
254
255 bool no_overlap = ((adc_front_s < obs_sl_boundary.start_s() ||
256 adc_end_s > obs_sl_boundary.end_s()) || // longitudinal
257 (adc_left_l + 0.1 < obs_sl_boundary.start_l() ||
258 adc_right_l - 0.1 > obs_sl_boundary.end_l())); // lateral
259
260 if (!no_overlap) {
261 obstacle_cost.cost_items[ComparableCost::HAS_COLLISION] = true;
262 }
263
264 // if obstacle is behind ADC, ignore its cost contribution.
265 if (adc_front_s > obs_sl_boundary.end_s()) {
266 return obstacle_cost;
267 }
268
269 const double delta_l = std::fmax(adc_right_l - obs_sl_boundary.end_l(),
270 obs_sl_boundary.start_l() - adc_left_l);
271 /*
272 AWARN << "adc_s: " << adc_s << "; adc_left_l: " << adc_left_l
273 << "; adc_right_l: " << adc_right_l << "; delta_l = " << delta_l;
274 AWARN << obs_sl_boundary.ShortDebugString();
275 */
276
277 static constexpr double kSafeDistance = 0.6;
278 if (delta_l < kSafeDistance) {
279 obstacle_cost.safety_cost +=
280 config_.obstacle_collision_cost() *
281 Sigmoid(config_.obstacle_collision_distance() - delta_l);
282 }
283
284 return obstacle_cost;
285}
286
287// Simple version: calculate obstacle cost by distance
288ComparableCost TrajectoryCost::GetCostBetweenObsBoxes(
289 const Box2d &ego_box, const Box2d &obstacle_box) const {
290 ComparableCost obstacle_cost;
291
292 const double distance = obstacle_box.DistanceTo(ego_box);
293 if (distance > config_.obstacle_ignore_distance()) {
294 return obstacle_cost;
295 }
296
297 obstacle_cost.safety_cost +=
298 config_.obstacle_collision_cost() *
299 Sigmoid(config_.obstacle_collision_distance() - distance);
300 obstacle_cost.safety_cost +=
301 20.0 * Sigmoid(config_.obstacle_risk_distance() - distance);
302 return obstacle_cost;
303}
304
305Box2d TrajectoryCost::GetBoxFromSLPoint(const common::SLPoint &sl,
306 const double dl) const {
307 Vec2d xy_point;
308 reference_line_->SLToXY(sl, &xy_point);
309
310 ReferencePoint reference_point = reference_line_->GetReferencePoint(sl.s());
311
312 const double one_minus_kappa_r_d = 1 - reference_point.kappa() * sl.l();
313 const double delta_theta = std::atan2(dl, one_minus_kappa_r_d);
314 const double theta =
315 common::math::NormalizeAngle(delta_theta + reference_point.heading());
316 return Box2d(xy_point, theta, vehicle_param_.length(),
317 vehicle_param_.width());
318}
319
320// TODO(All): optimize obstacle cost calculation time
322 const double start_s,
323 const double end_s,
324 const uint32_t curr_level,
325 const uint32_t total_level) {
326 ComparableCost total_cost;
327 // path cost
328 total_cost +=
329 CalculatePathCost(curve, start_s, end_s, curr_level, total_level);
330
331 // static obstacle cost
332 total_cost += CalculateStaticObstacleCost(curve, start_s, end_s);
333
334 // dynamic obstacle cost
335 total_cost += CalculateDynamicObstacleCost(curve, start_s, end_s);
336 return total_cost;
337}
338
339} // namespace planning
340} // namespace apollo
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
double width() const
Getter of the width
Definition box2d.h:130
const Vec2d & center() const
Getter of the center of the box
Definition box2d.h:106
double length() const
Getter of the length
Definition box2d.h:124
double heading() const
Getter of the heading
Definition box2d.h:148
static SLPoint ToSLPoint(const double s, const double l)
double Evaluate(const std::uint32_t order, const double p) const override
ReferencePoint GetReferencePoint(const double s) const
bool SLToXY(const common::SLPoint &sl_point, common::math::Vec2d *const xy_point) const
bool GetLaneWidth(const double s, double *const lane_left_width, double *const lane_right_width) const
bool EvaluateByTime(const double time, common::SpeedPoint *const speed_point) const
Definition speed_data.cc:60
ComparableCost Calculate(const QuinticPolynomialCurve1d &curve, const double start_s, const double end_s, const uint32_t curr_level, const uint32_t total_level)
Planning module main class.
double Sigmoid(const double x)
Definition math_utils.h:171
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
Definition math_utils.cc:53
class register implement
Definition arena_queue.h:37
optional VehicleParam vehicle_param
Defines the Vec2d class.