Apollo 11.0
自动驾驶开放平台
trajectory_evaluator.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 "cyber/common/log.h"
32
33namespace apollo {
34namespace planning {
35
39
41using PtrTrajectory1d = std::shared_ptr<Trajectory1d>;
43 std::pair<std::shared_ptr<Curve1d>, std::shared_ptr<Curve1d>>;
44
46 const std::array<double, 3>& init_s, const PlanningTarget& planning_target,
47 const std::vector<PtrTrajectory1d>& lon_trajectories,
48 const std::vector<PtrTrajectory1d>& lat_trajectories,
49 std::shared_ptr<PathTimeGraph> path_time_graph,
50 std::shared_ptr<std::vector<PathPoint>> reference_line)
51 : path_time_graph_(path_time_graph),
52 reference_line_(reference_line),
53 init_s_(init_s) {
54 const double start_time = 0.0;
55 const double end_time = FLAGS_trajectory_time_length;
56 path_time_intervals_ = path_time_graph_->GetPathBlockingIntervals(
57 start_time, end_time, FLAGS_trajectory_time_resolution);
58
59 reference_s_dot_ = ComputeLongitudinalGuideVelocity(planning_target);
60
61 // if we have a stop point along the reference line,
62 // filter out the lon. trajectories that pass the stop point.
63 double stop_point = std::numeric_limits<double>::max();
64 if (planning_target.has_stop_point()) {
65 stop_point = planning_target.stop_point().s();
66 }
67 for (const auto& lon_trajectory : lon_trajectories) {
68 double lon_end_s = lon_trajectory->Evaluate(0, end_time);
69 if (init_s[0] < stop_point &&
70 lon_end_s + FLAGS_lattice_stop_buffer > stop_point) {
71 continue;
72 }
73
75 continue;
76 }
77 for (const auto& lat_trajectory : lat_trajectories) {
85 double cost = Evaluate(planning_target, lon_trajectory, lat_trajectory);
86 cost_queue_.emplace(Trajectory1dPair(lon_trajectory, lat_trajectory),
87 cost);
88 }
89 }
90 ADEBUG << "Number of valid 1d trajectory pairs: " << cost_queue_.size();
91}
92
94 return !cost_queue_.empty();
95}
96
98 return cost_queue_.size();
99}
100
101std::pair<PtrTrajectory1d, PtrTrajectory1d>
104 auto top = cost_queue_.top();
105 cost_queue_.pop();
106 return top.first;
107}
108
110 return cost_queue_.top().second;
111}
112
113double TrajectoryEvaluator::Evaluate(
114 const PlanningTarget& planning_target,
115 const PtrTrajectory1d& lon_trajectory,
116 const PtrTrajectory1d& lat_trajectory,
117 std::vector<double>* cost_components) const {
118 // Costs:
119 // 1. Cost of missing the objective, e.g., cruise, stop, etc.
120 // 2. Cost of longitudinal jerk
121 // 3. Cost of longitudinal collision
122 // 4. Cost of lateral offsets
123 // 5. Cost of lateral comfort
124
125 // Longitudinal costs
126 double lon_objective_cost =
127 LonObjectiveCost(lon_trajectory, planning_target, reference_s_dot_);
128
129 double lon_jerk_cost = LonComfortCost(lon_trajectory);
130
131 double lon_collision_cost = LonCollisionCost(lon_trajectory);
132
133 double centripetal_acc_cost = CentripetalAccelerationCost(lon_trajectory);
134
135 // decides the longitudinal evaluation horizon for lateral trajectories.
136 double evaluation_horizon =
137 std::min(FLAGS_speed_lon_decision_horizon,
138 lon_trajectory->Evaluate(0, lon_trajectory->ParamLength()));
139 std::vector<double> s_values;
140 for (double s = 0.0; s < evaluation_horizon;
141 s += FLAGS_trajectory_space_resolution) {
142 s_values.emplace_back(s);
143 }
144
145 // Lateral costs
146 double lat_offset_cost = LatOffsetCost(lat_trajectory, s_values);
147
148 double lat_comfort_cost = LatComfortCost(lon_trajectory, lat_trajectory);
149
150 if (cost_components != nullptr) {
151 cost_components->emplace_back(lon_objective_cost);
152 cost_components->emplace_back(lon_jerk_cost);
153 cost_components->emplace_back(lon_collision_cost);
154 cost_components->emplace_back(lat_offset_cost);
155 }
156
157 return lon_objective_cost * FLAGS_weight_lon_objective +
158 lon_jerk_cost * FLAGS_weight_lon_jerk +
159 lon_collision_cost * FLAGS_weight_lon_collision +
160 centripetal_acc_cost * FLAGS_weight_centripetal_acceleration +
161 lat_offset_cost * FLAGS_weight_lat_offset +
162 lat_comfort_cost * FLAGS_weight_lat_comfort;
163}
164
165double TrajectoryEvaluator::LatOffsetCost(
166 const PtrTrajectory1d& lat_trajectory,
167 const std::vector<double>& s_values) const {
168 double lat_offset_start = lat_trajectory->Evaluate(0, 0.0);
169 double cost_sqr_sum = 0.0;
170 double cost_abs_sum = 0.0;
171 for (const auto& s : s_values) {
172 double lat_offset = lat_trajectory->Evaluate(0, s);
173 double cost = lat_offset / FLAGS_lat_offset_bound;
174 if (lat_offset * lat_offset_start < 0.0) {
175 cost_sqr_sum += cost * cost * FLAGS_weight_opposite_side_offset;
176 cost_abs_sum += std::fabs(cost) * FLAGS_weight_opposite_side_offset;
177 } else {
178 cost_sqr_sum += cost * cost * FLAGS_weight_same_side_offset;
179 cost_abs_sum += std::fabs(cost) * FLAGS_weight_same_side_offset;
180 }
181 }
182 return cost_sqr_sum / (cost_abs_sum + FLAGS_numerical_epsilon);
183}
184
185double TrajectoryEvaluator::LatComfortCost(
186 const PtrTrajectory1d& lon_trajectory,
187 const PtrTrajectory1d& lat_trajectory) const {
188 double max_cost = 0.0;
189 for (double t = 0.0; t < FLAGS_trajectory_time_length;
190 t += FLAGS_trajectory_time_resolution) {
191 double s = lon_trajectory->Evaluate(0, t);
192 double s_dot = lon_trajectory->Evaluate(1, t);
193 double s_dotdot = lon_trajectory->Evaluate(2, t);
194
195 double relative_s = s - init_s_[0];
196 double l_prime = lat_trajectory->Evaluate(1, relative_s);
197 double l_primeprime = lat_trajectory->Evaluate(2, relative_s);
198 double cost = l_primeprime * s_dot * s_dot + l_prime * s_dotdot;
199 max_cost = std::max(max_cost, std::fabs(cost));
200 }
201 return max_cost;
202}
203
204double TrajectoryEvaluator::LonComfortCost(
205 const PtrTrajectory1d& lon_trajectory) const {
206 double cost_sqr_sum = 0.0;
207 double cost_abs_sum = 0.0;
208 for (double t = 0.0; t < FLAGS_trajectory_time_length;
209 t += FLAGS_trajectory_time_resolution) {
210 double jerk = lon_trajectory->Evaluate(3, t);
211 double cost = jerk / FLAGS_longitudinal_jerk_upper_bound;
212 cost_sqr_sum += cost * cost;
213 cost_abs_sum += std::fabs(cost);
214 }
215 return cost_sqr_sum / (cost_abs_sum + FLAGS_numerical_epsilon);
216}
217
218double TrajectoryEvaluator::LonObjectiveCost(
219 const PtrTrajectory1d& lon_trajectory,
220 const PlanningTarget& planning_target,
221 const std::vector<double>& ref_s_dots) const {
222 double t_max = lon_trajectory->ParamLength();
223 double dist_s =
224 lon_trajectory->Evaluate(0, t_max) - lon_trajectory->Evaluate(0, 0.0);
225
226 double speed_cost_sqr_sum = 0.0;
227 double speed_cost_weight_sum = 0.0;
228 for (size_t i = 0; i < ref_s_dots.size(); ++i) {
229 double t = static_cast<double>(i) * FLAGS_trajectory_time_resolution;
230 double cost = ref_s_dots[i] - lon_trajectory->Evaluate(1, t);
231 speed_cost_sqr_sum += t * t * std::fabs(cost);
232 speed_cost_weight_sum += t * t;
233 }
234 double speed_cost =
235 speed_cost_sqr_sum / (speed_cost_weight_sum + FLAGS_numerical_epsilon);
236 double dist_travelled_cost = 1.0 / (1.0 + dist_s);
237 return (speed_cost * FLAGS_weight_target_speed +
238 dist_travelled_cost * FLAGS_weight_dist_travelled) /
239 (FLAGS_weight_target_speed + FLAGS_weight_dist_travelled);
240}
241
242// TODO(all): consider putting pointer of reference_line_info and frame
243// while constructing trajectory evaluator
244double TrajectoryEvaluator::LonCollisionCost(
245 const PtrTrajectory1d& lon_trajectory) const {
246 double cost_sqr_sum = 0.0;
247 double cost_abs_sum = 0.0;
248 for (size_t i = 0; i < path_time_intervals_.size(); ++i) {
249 const auto& pt_interval = path_time_intervals_[i];
250 if (pt_interval.empty()) {
251 continue;
252 }
253 double t = static_cast<double>(i) * FLAGS_trajectory_time_resolution;
254 double traj_s = lon_trajectory->Evaluate(0, t);
255 double sigma = FLAGS_lon_collision_cost_std;
256 for (const auto& m : pt_interval) {
257 double dist = 0.0;
258 if (traj_s < m.first - FLAGS_lon_collision_yield_buffer) {
259 dist = m.first - FLAGS_lon_collision_yield_buffer - traj_s;
260 } else if (traj_s > m.second + FLAGS_lon_collision_overtake_buffer) {
261 dist = traj_s - m.second - FLAGS_lon_collision_overtake_buffer;
262 }
263 double cost = std::exp(-dist * dist / (2.0 * sigma * sigma));
264
265 cost_sqr_sum += cost * cost;
266 cost_abs_sum += cost;
267 }
268 }
269 return cost_sqr_sum / (cost_abs_sum + FLAGS_numerical_epsilon);
270}
271
272double TrajectoryEvaluator::CentripetalAccelerationCost(
273 const PtrTrajectory1d& lon_trajectory) const {
274 // Assumes the vehicle is not obviously deviate from the reference line.
275 double centripetal_acc_sum = 0.0;
276 double centripetal_acc_sqr_sum = 0.0;
277 for (double t = 0.0; t < FLAGS_trajectory_time_length;
278 t += FLAGS_trajectory_time_resolution) {
279 double s = lon_trajectory->Evaluate(0, t);
280 double v = lon_trajectory->Evaluate(1, t);
281 PathPoint ref_point = PathMatcher::MatchToPath(*reference_line_, s);
282 ACHECK(ref_point.has_kappa());
283 double centripetal_acc = v * v * ref_point.kappa();
284 centripetal_acc_sum += std::fabs(centripetal_acc);
285 centripetal_acc_sqr_sum += centripetal_acc * centripetal_acc;
286 }
287
288 return centripetal_acc_sqr_sum /
289 (centripetal_acc_sum + FLAGS_numerical_epsilon);
290}
291
292std::vector<double> TrajectoryEvaluator::ComputeLongitudinalGuideVelocity(
293 const PlanningTarget& planning_target) const {
294 std::vector<double> reference_s_dot;
295
296 double cruise_v = planning_target.cruise_speed();
297
298 if (!planning_target.has_stop_point()) {
299 PiecewiseAccelerationTrajectory1d lon_traj(init_s_[0], cruise_v);
300 lon_traj.AppendSegment(
301 0.0, FLAGS_trajectory_time_length + FLAGS_numerical_epsilon);
302
303 for (double t = 0.0; t < FLAGS_trajectory_time_length;
304 t += FLAGS_trajectory_time_resolution) {
305 reference_s_dot.emplace_back(lon_traj.Evaluate(1, t));
306 }
307 } else {
308 double dist_s = planning_target.stop_point().s() - init_s_[0];
309 if (dist_s < FLAGS_numerical_epsilon) {
310 PiecewiseAccelerationTrajectory1d lon_traj(init_s_[0], 0.0);
311 lon_traj.AppendSegment(
312 0.0, FLAGS_trajectory_time_length + FLAGS_numerical_epsilon);
313
314 for (double t = 0.0; t < FLAGS_trajectory_time_length;
315 t += FLAGS_trajectory_time_resolution) {
316 reference_s_dot.emplace_back(lon_traj.Evaluate(1, t));
317 }
318 return reference_s_dot;
319 }
320
321 double a_comfort = FLAGS_longitudinal_acceleration_upper_bound *
322 FLAGS_comfort_acceleration_factor;
323 double d_comfort = -FLAGS_longitudinal_acceleration_lower_bound *
324 FLAGS_comfort_acceleration_factor;
325
326 std::shared_ptr<Trajectory1d> lon_ref_trajectory =
328 planning_target.stop_point().s(), init_s_[0],
329 planning_target.cruise_speed(), init_s_[1], a_comfort, d_comfort,
330 FLAGS_trajectory_time_length + FLAGS_numerical_epsilon);
331
332 for (double t = 0.0; t < FLAGS_trajectory_time_length;
333 t += FLAGS_trajectory_time_resolution) {
334 reference_s_dot.emplace_back(lon_ref_trajectory->Evaluate(1, t));
335 }
336 }
337 return reference_s_dot;
338}
339
340bool TrajectoryEvaluator::InterpolateDenseStPoints(
341 const std::vector<SpeedPoint>& st_points, double t, double* traj_s) const {
342 CHECK_GT(st_points.size(), 1U);
343 if (t < st_points[0].t() || t > st_points[st_points.size() - 1].t()) {
344 AERROR << "AutoTuning InterpolateDenseStPoints Error";
345 return false;
346 }
347 for (uint i = 1; i < st_points.size(); ++i) {
348 if (t <= st_points[i].t()) {
349 *traj_s = st_points[i].t();
350 return true;
351 }
352 }
353 return false;
354}
355
356} // namespace planning
357} // namespace apollo
static PathPoint MatchToPath(const std::vector< PathPoint > &reference_line, const double x, const double y)
static bool IsValidLongitudinalTrajectory(const Curve1d &lon_trajectory)
static std::shared_ptr< Curve1d > Generate(const double s_target, const double s_curr, const double v_target, const double v_curr, const double a_comfort, const double d_comfort, const double max_time)
TrajectoryEvaluator(const std::array< double, 3 > &init_s, const PlanningTarget &planning_target, const std::vector< std::shared_ptr< Curve1d > > &lon_trajectories, const std::vector< std::shared_ptr< Curve1d > > &lat_trajectories, std::shared_ptr< PathTimeGraph > path_time_graph, std::shared_ptr< std::vector< apollo::common::PathPoint > > reference_line)
std::pair< std::shared_ptr< Curve1d >, std::shared_ptr< Curve1d > > next_top_trajectory_pair()
Planning module main class.
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
std::pair< std::shared_ptr< Curve1d >, std::shared_ptr< Curve1d > > Trajectory1dPair
std::shared_ptr< Trajectory1d > PtrTrajectory1d
class register implement
Definition arena_queue.h:37