Apollo 11.0
自动驾驶开放平台
lattice_planner.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 <limits>
24#include <memory>
25#include <utility>
26#include <vector>
27
28#include "cyber/common/log.h"
29#include "cyber/common/macros.h"
30#include "cyber/time/clock.h"
43
44namespace apollo {
45namespace planning {
46
54
55namespace {
56
57std::vector<PathPoint> ToDiscretizedReferenceLine(
58 const std::vector<ReferencePoint>& ref_points) {
59 double s = 0.0;
60 std::vector<PathPoint> path_points;
61 for (const auto& ref_point : ref_points) {
62 PathPoint path_point;
63 path_point.set_x(ref_point.x());
64 path_point.set_y(ref_point.y());
65 path_point.set_theta(ref_point.heading());
66 path_point.set_kappa(ref_point.kappa());
67 path_point.set_dkappa(ref_point.dkappa());
68
69 if (!path_points.empty()) {
70 double dx = path_point.x() - path_points.back().x();
71 double dy = path_point.y() - path_points.back().y();
72 s += std::sqrt(dx * dx + dy * dy);
73 }
74 path_point.set_s(s);
75 path_points.push_back(std::move(path_point));
76 }
77 return path_points;
78}
79
80void ComputeInitFrenetState(const PathPoint& matched_point,
81 const TrajectoryPoint& cartesian_state,
82 std::array<double, 3>* ptr_s,
83 std::array<double, 3>* ptr_d) {
85 matched_point.s(), matched_point.x(), matched_point.y(),
86 matched_point.theta(), matched_point.kappa(), matched_point.dkappa(),
87 cartesian_state.path_point().x(), cartesian_state.path_point().y(),
88 cartesian_state.v(), cartesian_state.a(),
89 cartesian_state.path_point().theta(),
90 cartesian_state.path_point().kappa(), ptr_s, ptr_d);
91}
92
93} // namespace
94
95Status LatticePlanner::Plan(const TrajectoryPoint& planning_start_point,
96 Frame* frame,
97 ADCTrajectory* ptr_computed_trajectory) {
98 size_t success_line_count = 0;
99 size_t index = 0;
100 for (auto& reference_line_info : *frame->mutable_reference_line_info()) {
101 if (index != 0) {
102 reference_line_info.SetPriorityCost(
103 FLAGS_cost_non_priority_reference_line);
104 } else {
105 reference_line_info.SetPriorityCost(0.0);
106 }
107 auto status =
108 PlanOnReferenceLine(planning_start_point, frame, &reference_line_info);
109
110 if (status != Status::OK()) {
111 if (reference_line_info.IsChangeLanePath()) {
112 AERROR << "Planner failed to change lane to "
113 << reference_line_info.Lanes().Id();
114 } else {
115 AERROR << "Planner failed to " << reference_line_info.Lanes().Id();
116 }
117 } else {
118 success_line_count += 1;
119 }
120 ++index;
121 }
122
123 if (success_line_count > 0) {
124 return Status::OK();
125 }
126 return Status(ErrorCode::PLANNING_ERROR,
127 "Failed to plan on any reference line.");
128}
129
131 const TrajectoryPoint& planning_init_point, Frame* frame,
132 ReferenceLineInfo* reference_line_info) {
133 static size_t num_planning_cycles = 0;
134 static size_t num_planning_succeeded_cycles = 0;
135
136 double start_time = Clock::NowInSeconds();
137 double current_time = start_time;
138
139 ADEBUG << "Number of planning cycles: " << num_planning_cycles << " "
140 << num_planning_succeeded_cycles;
141 ++num_planning_cycles;
142
143 reference_line_info->set_is_on_reference_line();
144 // 1. obtain a reference line and transform it to the PathPoint format.
145 auto ptr_reference_line =
146 std::make_shared<std::vector<PathPoint>>(ToDiscretizedReferenceLine(
147 reference_line_info->reference_line().reference_points()));
148
149 // 2. compute the matched point of the init planning point on the reference
150 // line.
151 PathPoint matched_point = PathMatcher::MatchToPath(
152 *ptr_reference_line, planning_init_point.path_point().x(),
153 planning_init_point.path_point().y());
154
155 // 3. according to the matched point, compute the init state in Frenet frame.
156 std::array<double, 3> init_s;
157 std::array<double, 3> init_d;
158 ComputeInitFrenetState(matched_point, planning_init_point, &init_s, &init_d);
159
160 ADEBUG << "ReferenceLine and Frenet Conversion Time = "
161 << (Clock::NowInSeconds() - current_time) * 1000;
162 current_time = Clock::NowInSeconds();
163
164 auto ptr_prediction_querier = std::make_shared<PredictionQuerier>(
165 frame->obstacles(), ptr_reference_line);
166
167 // 4. parse the decision and get the planning target.
168 auto ptr_path_time_graph = std::make_shared<PathTimeGraph>(
169 ptr_prediction_querier->GetObstacles(), *ptr_reference_line,
170 reference_line_info, init_s[0],
171 init_s[0] + FLAGS_speed_lon_decision_horizon, 0.0,
172 FLAGS_trajectory_time_length, init_d);
173
174 double speed_limit =
175 reference_line_info->reference_line().GetSpeedLimitFromS(init_s[0]);
176 reference_line_info->SetLatticeCruiseSpeed(speed_limit);
177
178 PlanningTarget planning_target = reference_line_info->planning_target();
179 if (planning_target.has_stop_point()) {
180 ADEBUG << "Planning target stop s: " << planning_target.stop_point().s()
181 << "Current ego s: " << init_s[0];
182 }
183
184 ADEBUG << "Decision_Time = " << (Clock::NowInSeconds() - current_time) * 1000;
185 current_time = Clock::NowInSeconds();
186
187 // 5. generate 1d trajectory bundle for longitudinal and lateral respectively.
188 Trajectory1dGenerator trajectory1d_generator(
189 init_s, init_d, ptr_path_time_graph, ptr_prediction_querier);
190 std::vector<std::shared_ptr<Curve1d>> lon_trajectory1d_bundle;
191 std::vector<std::shared_ptr<Curve1d>> lat_trajectory1d_bundle;
192 trajectory1d_generator.GenerateTrajectoryBundles(
193 planning_target, &lon_trajectory1d_bundle, &lat_trajectory1d_bundle);
194
195 ADEBUG << "Trajectory_Generation_Time = "
196 << (Clock::NowInSeconds() - current_time) * 1000;
197 current_time = Clock::NowInSeconds();
198
199 // 6. first, evaluate the feasibility of the 1d trajectories according to
200 // dynamic constraints.
201 // second, evaluate the feasible longitudinal and lateral trajectory pairs
202 // and sort them according to the cost.
203 TrajectoryEvaluator trajectory_evaluator(
204 init_s, planning_target, lon_trajectory1d_bundle, lat_trajectory1d_bundle,
205 ptr_path_time_graph, ptr_reference_line);
206
207 ADEBUG << "Trajectory_Evaluator_Construction_Time = "
208 << (Clock::NowInSeconds() - current_time) * 1000;
209 current_time = Clock::NowInSeconds();
210
211 ADEBUG << "number of trajectory pairs = "
212 << trajectory_evaluator.num_of_trajectory_pairs()
213 << " number_lon_traj = " << lon_trajectory1d_bundle.size()
214 << " number_lat_traj = " << lat_trajectory1d_bundle.size();
215
216 // Get instance of collision checker and constraint checker
217 CollisionChecker collision_checker(frame->obstacles(), init_s[0], init_d[0],
218 *ptr_reference_line, reference_line_info,
219 ptr_path_time_graph);
220
221 // 7. always get the best pair of trajectories to combine; return the first
222 // collision-free trajectory.
223 size_t constraint_failure_count = 0;
224 size_t collision_failure_count = 0;
225 size_t combined_constraint_failure_count = 0;
226
227 size_t lon_vel_failure_count = 0;
228 size_t lon_acc_failure_count = 0;
229 size_t lon_jerk_failure_count = 0;
230 size_t curvature_failure_count = 0;
231 size_t lat_acc_failure_count = 0;
232 size_t lat_jerk_failure_count = 0;
233
234 size_t num_lattice_traj = 0;
235
236 while (trajectory_evaluator.has_more_trajectory_pairs()) {
237 double trajectory_pair_cost =
238 trajectory_evaluator.top_trajectory_pair_cost();
239 auto trajectory_pair = trajectory_evaluator.next_top_trajectory_pair();
240
241 // combine two 1d trajectories to one 2d trajectory
242 auto combined_trajectory = TrajectoryCombiner::Combine(
243 *ptr_reference_line, *trajectory_pair.first, *trajectory_pair.second,
244 planning_init_point.relative_time());
245
246 // check longitudinal and lateral acceleration
247 // considering trajectory curvatures
248 auto result = ConstraintChecker::ValidTrajectory(combined_trajectory);
249 if (result != ConstraintChecker::Result::VALID) {
250 ++combined_constraint_failure_count;
251
252 switch (result) {
254 lon_vel_failure_count += 1;
255 break;
257 lon_acc_failure_count += 1;
258 break;
260 lon_jerk_failure_count += 1;
261 break;
263 curvature_failure_count += 1;
264 break;
266 lat_acc_failure_count += 1;
267 break;
269 lat_jerk_failure_count += 1;
270 break;
272 default:
273 // Intentional empty
274 break;
275 }
276 continue;
277 }
278
279 // check collision with other obstacles
280 if (collision_checker.InCollision(combined_trajectory)) {
281 ++collision_failure_count;
282 continue;
283 }
284
285 // put combine trajectory into debug data
286 const auto& combined_trajectory_points = combined_trajectory;
287 num_lattice_traj += 1;
288 reference_line_info->SetTrajectory(combined_trajectory);
289 reference_line_info->SetCost(reference_line_info->PriorityCost() +
290 trajectory_pair_cost);
291 reference_line_info->SetDrivable(true);
292
293 // Print the chosen end condition and start condition
294 ADEBUG << "Starting Lon. State: s = " << init_s[0] << " ds = " << init_s[1]
295 << " dds = " << init_s[2];
296 // cast
297 auto lattice_traj_ptr =
298 std::dynamic_pointer_cast<LatticeTrajectory1d>(trajectory_pair.first);
299 if (!lattice_traj_ptr) {
300 ADEBUG << "Dynamically casting trajectory1d ptr. failed.";
301 }
302
303 if (lattice_traj_ptr->has_target_position()) {
304 ADEBUG << "Ending Lon. State s = " << lattice_traj_ptr->target_position()
305 << " ds = " << lattice_traj_ptr->target_velocity()
306 << " t = " << lattice_traj_ptr->target_time();
307 }
308
309 ADEBUG << "InputPose";
310 ADEBUG << "XY: " << planning_init_point.ShortDebugString();
311 ADEBUG << "S: (" << init_s[0] << ", " << init_s[1] << "," << init_s[2]
312 << ")";
313 ADEBUG << "L: (" << init_d[0] << ", " << init_d[1] << "," << init_d[2]
314 << ")";
315
316 ADEBUG << "Reference_line_priority_cost = "
317 << reference_line_info->PriorityCost();
318 ADEBUG << "Total_Trajectory_Cost = " << trajectory_pair_cost;
319 ADEBUG << "OutputTrajectory";
320 for (uint i = 0; i < 10; ++i) {
321 ADEBUG << combined_trajectory_points[i].ShortDebugString();
322 }
323
324 break;
325 /*
326 auto combined_trajectory_path =
327 ptr_debug->mutable_planning_data()->add_trajectory_path();
328 for (uint i = 0; i < combined_trajectory_points.size(); ++i) {
329 combined_trajectory_path->add_trajectory_point()->CopyFrom(
330 combined_trajectory_points[i]);
331 }
332 combined_trajectory_path->set_lattice_trajectory_cost(trajectory_pair_cost);
333 */
334 }
335
336 ADEBUG << "Trajectory_Evaluation_Time = "
337 << (Clock::NowInSeconds() - current_time) * 1000;
338
339 ADEBUG << "Step CombineTrajectory Succeeded";
340
341 ADEBUG << "1d trajectory not valid for constraint ["
342 << constraint_failure_count << "] times";
343 ADEBUG << "Combined trajectory not valid for ["
344 << combined_constraint_failure_count << "] times";
345 ADEBUG << "Trajectory not valid for collision [" << collision_failure_count
346 << "] times";
347 ADEBUG << "Total_Lattice_Planning_Frame_Time = "
348 << (Clock::NowInSeconds() - start_time) * 1000;
349
350 if (num_lattice_traj > 0) {
351 ADEBUG << "Planning succeeded";
352 num_planning_succeeded_cycles += 1;
353 reference_line_info->SetDrivable(true);
354 return Status::OK();
355 } else {
356 AERROR << "Planning failed";
357 if (FLAGS_enable_backup_trajectory) {
358 AERROR << "Use backup trajectory";
359 BackupTrajectoryGenerator backup_trajectory_generator(
360 init_s, init_d, planning_init_point.relative_time(),
361 std::make_shared<CollisionChecker>(collision_checker),
362 &trajectory1d_generator);
363 DiscretizedTrajectory trajectory =
364 backup_trajectory_generator.GenerateTrajectory(*ptr_reference_line);
365
366 reference_line_info->AddCost(FLAGS_backup_trajectory_cost);
367 reference_line_info->SetTrajectory(trajectory);
368 reference_line_info->SetDrivable(true);
369 return Status::OK();
370
371 } else {
372 reference_line_info->SetCost(std::numeric_limits<double>::infinity());
373 }
374 return Status(ErrorCode::PLANNING_ERROR, "No feasible trajectories");
375 }
376}
377
378} // namespace planning
379} // namespace apollo
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
static void cartesian_to_frenet(const double rs, const double rx, const double ry, const double rtheta, const double rkappa, const double rdkappa, const double x, const double y, const double v, const double a, const double theta, const double kappa, std::array< double, 3 > *const ptr_s_condition, std::array< double, 3 > *const ptr_d_condition)
Convert a vehicle state in Cartesian frame to Frenet frame.
static PathPoint MatchToPath(const std::vector< PathPoint > &reference_line, const double x, const double y)
a singleton clock that can be used to get the current timestamp.
Definition clock.h:39
static double NowInSeconds()
gets the current time in second.
Definition clock.cc:56
DiscretizedTrajectory GenerateTrajectory(const std::vector< common::PathPoint > &discretized_ref_points)
bool InCollision(const DiscretizedTrajectory &discretized_trajectory)
static Result ValidTrajectory(const DiscretizedTrajectory &trajectory)
Frame holds all data for one planning cycle.
Definition frame.h:62
const std::vector< const Obstacle * > obstacles() const
Definition frame.cc:577
std::list< ReferenceLineInfo > * mutable_reference_line_info()
Definition frame.cc:127
common::Status Plan(const common::TrajectoryPoint &planning_init_point, Frame *frame, ADCTrajectory *ptr_computed_trajectory) override
Override function Plan in parent class Planner.
common::Status PlanOnReferenceLine(const common::TrajectoryPoint &planning_init_point, Frame *frame, ReferenceLineInfo *reference_line_info) override
Override function Plan in parent class Planner.
ReferenceLineInfo holds all data for one reference line.
void SetTrajectory(const DiscretizedTrajectory &trajectory)
void SetDrivable(bool drivable)
Set if the vehicle can drive following this reference line A planner need to set this value to true i...
const PlanningTarget & planning_target() const
const ReferenceLine & reference_line() const
double GetSpeedLimitFromS(const double s) const
const std::vector< ReferencePoint > & reference_points() const
void GenerateTrajectoryBundles(const PlanningTarget &planning_target, std::vector< std::shared_ptr< Curve1d > > *ptr_lon_trajectory_bundle, std::vector< std::shared_ptr< Curve1d > > *ptr_lat_trajectory_bundle)
static DiscretizedTrajectory Combine(const std::vector< common::PathPoint > &reference_line, const Curve1d &lon_trajectory, const Curve1d &lat_trajectory, const double init_relative_time)
std::pair< std::shared_ptr< Curve1d >, std::shared_ptr< Curve1d > > next_top_trajectory_pair()
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
class register implement
Definition arena_queue.h:37