Apollo 11.0
自动驾驶开放平台
optimizer.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2023 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 <iomanip>
24#include <utility>
25
26namespace apollo {
27namespace planning {
28
33
36 : config_(config) {
37 // Load config
38 AINFO << config_.DebugString();
39
40 // Initialize dual variable warm start class pointer
41 dual_variable_warm_start_.reset(
44
45 // Initialize distance approach trajectory smootherclass pointer
46 distance_approach_.reset(
48
49 // Initialize iterative anchoring smoother config class pointer
50 iterative_anchoring_smoother_.reset(
53}
54
55Status Optimizer::Plan(const OpenSpaceInfo open_space_info) {
56 // const auto start_timestamp = std::chrono::system_clock::now();
57
58 const std::vector<std::vector<Vec2d>>& obstacles_vertices_vec =
59 open_space_info.obstacles_vertices_vec();
60 const std::vector<double>& XYbounds = open_space_info.ROI_xy_boundary();
61 const Eigen::MatrixXi& obstacles_edges_num =
62 open_space_info.obstacles_edges_num();
63 const Eigen::MatrixXd& obstacles_A = open_space_info.obstacles_A();
64 const Eigen::MatrixXd& obstacles_b = open_space_info.obstacles_b();
65
66 DiscretizedTrajectory warm_start_trajectory =
67 open_space_info.path_planning_trajectory_result();
68 const double origin_angle = open_space_info.origin_heading();
69 const Vec2d origin_point = open_space_info.origin_point();
70 for (size_t i = 0; i < warm_start_trajectory.size(); i++) {
71 double x = warm_start_trajectory[i].path_point().x();
72 double y = warm_start_trajectory[i].path_point().y();
73 double theta = warm_start_trajectory[i].path_point().theta();
75 origin_point,
76 &x,
77 &y,
78 &theta);
79 warm_start_trajectory[i].mutable_path_point()->set_x(x);
80 warm_start_trajectory[i].mutable_path_point()->set_y(y);
81 warm_start_trajectory[i].mutable_path_point()->set_theta(theta);
82 }
83
84 // Containers for distance approach trajectory smoothing problem
85 Eigen::MatrixXd xWS;
86 Eigen::MatrixXd uWS;
87 Eigen::MatrixXd state_result_ds;
88 Eigen::MatrixXd control_result_ds;
89 Eigen::MatrixXd time_result_ds;
90 Eigen::MatrixXd l_warm_up;
91 Eigen::MatrixXd n_warm_up;
92 Eigen::MatrixXd dual_l_result_ds;
93 Eigen::MatrixXd dual_n_result_ds;
94
95 if (FLAGS_enable_parallel_trajectory_smoothing) {
96 std::vector<DiscretizedTrajectory> partition_trajectories;
97
98 PartitionTrajectory(warm_start_trajectory, &partition_trajectories);
99
100 size_t size = partition_trajectories.size();
101 std::vector<Eigen::MatrixXd> xWS_vec;
102 std::vector<Eigen::MatrixXd> uWS_vec;
103 std::vector<Eigen::MatrixXd> state_result_ds_vec;
104 std::vector<Eigen::MatrixXd> control_result_ds_vec;
105 std::vector<Eigen::MatrixXd> time_result_ds_vec;
106 std::vector<Eigen::MatrixXd> l_warm_up_vec;
107 std::vector<Eigen::MatrixXd> n_warm_up_vec;
108 std::vector<Eigen::MatrixXd> dual_l_result_ds_vec;
109 std::vector<Eigen::MatrixXd> dual_n_result_ds_vec;
110 xWS_vec.resize(size);
111 uWS_vec.resize(size);
112 state_result_ds_vec.resize(size);
113 control_result_ds_vec.resize(size);
114 time_result_ds_vec.resize(size);
115 l_warm_up_vec.resize(size);
116 n_warm_up_vec.resize(size);
117 dual_l_result_ds_vec.resize(size);
118 dual_n_result_ds_vec.resize(size);
119
120 // In for loop
121 ADEBUG << "Trajectories size in smoother is " << size;
122 for (size_t i = 0; i < size; ++i) {
123 LoadTrajectoryInEigen(partition_trajectories[i], xWS_vec[i],
124 uWS_vec[i]);
125 Eigen::MatrixXd last_time_u(2, 1);
126 last_time_u << 0.0, 0.0;
127 double init_v = 0.0;
128
129 // TODO(Jinyun): Further testing
130 const auto smoother_start_timestamp = std::chrono::system_clock::now();
131 if (FLAGS_use_iterative_anchoring_smoother) {
132 AINFO << "use iterative anchoring smoother";
133 if (!GenerateDecoupledTraj(
134 xWS_vec[i], last_time_u(1, 0), init_v, obstacles_vertices_vec,
135 &state_result_ds_vec[i], &control_result_ds_vec[i],
136 &time_result_ds_vec[i])) {
137 AERROR << "Smoother fail at " << i << "th trajectory";
138 AERROR << i << "th trajectory size is " << xWS_vec[i].cols();
139 return Status(
140 ErrorCode::PLANNING_ERROR,
141 "iterative anchoring smoothing problem failed to solve");
142 }
143 } else {
144 const double start_system_timestamp =
145 std::chrono::duration<double>(
146 std::chrono::system_clock::now().time_since_epoch())
147 .count();
148 AINFO << "use distance approach parallel smoother";
149 if (!GenerateDistanceApproachTraj(
150 xWS_vec[i], uWS_vec[i], XYbounds, obstacles_edges_num,
151 obstacles_A, obstacles_b, obstacles_vertices_vec, last_time_u,
152 init_v, &state_result_ds_vec[i], &control_result_ds_vec[i],
153 &time_result_ds_vec[i], &l_warm_up_vec[i], &n_warm_up_vec[i],
154 &dual_l_result_ds_vec[i], &dual_n_result_ds_vec[i])) {
155 AERROR << "Smoother fail at " << i
156 << "th trajectory with index starts from 0";
157 AERROR << i << "th trajectory size is " << xWS_vec[i].cols();
158 AERROR << "State matrix: " << xWS_vec[i];
159 AERROR << "Control matrix: " << uWS_vec[i];
160 return Status(ErrorCode::PLANNING_ERROR,
161 "distance approach smoothing problem failed to solve");
162 }
163 const auto end_system_timestamp =
164 std::chrono::duration<double>(
165 std::chrono::system_clock::now().time_since_epoch())
166 .count();
167 const auto time_diff_ms =
168 (end_system_timestamp - start_system_timestamp) * 1000;
169 ADEBUG << "total planning time spend: " << time_diff_ms << " ms.";
170 ADEBUG << i << "th trajectory size is " << xWS_vec[i].cols();
171 ADEBUG << "average time spend: " << time_diff_ms / xWS_vec[i].cols()
172 << " ms per point.";
173 ADEBUG << "average time spend after smooth: "
174 << time_diff_ms / state_result_ds_vec[i].cols()
175 << " ms per point.";
176 ADEBUG << i << "th smoothed trajectory size is "
177 << state_result_ds_vec[i].cols();
178 }
179 const auto smoother_end_timestamp = std::chrono::system_clock::now();
180 std::chrono::duration<double> smoother_diff =
181 smoother_end_timestamp - smoother_start_timestamp;
182 AINFO << "Open space trajectory smoothing total time: "
183 << smoother_diff.count() * 1000.0 << " ms at the " << i
184 << "th trajectory.";
185 AINFO << "The " << i << "th trajectory pre-smoothing size is "
186 << xWS_vec[i].cols() << "; post-smoothing size is "
187 << state_result_ds_vec[i].cols();
188 }
189
190 // Retrive the trajectory in one piece
191 CombineTrajectories(xWS_vec, uWS_vec, state_result_ds_vec,
192 control_result_ds_vec, time_result_ds_vec,
193 l_warm_up_vec, n_warm_up_vec, dual_l_result_ds_vec,
194 dual_n_result_ds_vec, &xWS, &uWS, &state_result_ds,
195 &control_result_ds, &time_result_ds, &l_warm_up,
196 &n_warm_up, &dual_l_result_ds, &dual_n_result_ds);
197
198 } else {
199 AINFO << "use distance approach smoother";
200 LoadTrajectoryInEigen(warm_start_trajectory, xWS, uWS);
201
202 Eigen::MatrixXd last_time_u(2, 1);
203 last_time_u << 0, 0;
204
205 const double init_v = 0;
206 FLAGS_use_iterative_anchoring_smoother = false;
207 if (!GenerateDistanceApproachTraj(
208 xWS, uWS, XYbounds, obstacles_edges_num, obstacles_A, obstacles_b,
209 obstacles_vertices_vec, last_time_u, init_v, &state_result_ds,
210 &control_result_ds, &time_result_ds, &l_warm_up, &n_warm_up,
211 &dual_l_result_ds, &dual_n_result_ds)) {
212 return Status(ErrorCode::PLANNING_ERROR,
213 "distance approach smoothing problem failed to solve");
214 }
215 }
216
217 // record debug info
218 if (FLAGS_enable_record_debug) {
219 open_space_debug_.Clear();
220 RecordDebugInfo(origin_point, origin_angle,
221 open_space_info.open_space_end_pose(),
222 xWS, uWS, l_warm_up, n_warm_up, dual_l_result_ds,
223 dual_n_result_ds, state_result_ds, control_result_ds,
224 time_result_ds, XYbounds, obstacles_vertices_vec);
225 }
226
227 // rescale the states to the world frame
228 size_t state_size = state_result_ds.cols();
229 for (size_t i = 0; i < state_size; ++i) {
231 origin_angle, origin_point,
232 &(state_result_ds(0, i)), &(state_result_ds(1, i)),
233 &(state_result_ds(2, i)));
234 }
235
236 LoadTrajectory(state_result_ds, control_result_ds, time_result_ds);
237
238 // const auto end_timestamp = std::chrono::system_clock::now();
239 // std::chrono::duration<double> diff = end_timestamp - start_timestamp;
240 // ADEBUG << "open space trajectory smoother total time: "
241 // << diff.count() * 1000.0 << " ms.";
242 // double temp = diff.count() * 1000.0;
243
244 return Status::OK();
245}
246
247void Optimizer::LoadTrajectoryInEigen(
248 DiscretizedTrajectory& result, Eigen::MatrixXd& xWS, Eigen::MatrixXd& uWS) {
249 size_t horizon = result.size() - 1;
250 xWS.resize(4, horizon + 1);
251 uWS.resize(2, horizon);
252
253 for (size_t i = 0; i < horizon; i++) {
254 xWS(0, i) = result[i].path_point().x();
255 xWS(1, i) = result[i].path_point().y();
256 xWS(2, i) = result[i].path_point().theta();
257 xWS(3, i) = result[i].v();
258 uWS(0, i) = result[i].steer();
259 uWS(1, i) = result[i].a();
260 }
261 xWS(0, horizon) = result.back().path_point().x();
262 xWS(1, horizon) = result.back().path_point().y();
263 xWS(2, horizon) = result.back().path_point().theta();
264 xWS(3, horizon) = result.back().v();
265}
266
267void Optimizer::CombineTrajectories(
268 const std::vector<Eigen::MatrixXd>& xWS_vec,
269 const std::vector<Eigen::MatrixXd>& uWS_vec,
270 const std::vector<Eigen::MatrixXd>& state_result_ds_vec,
271 const std::vector<Eigen::MatrixXd>& control_result_ds_vec,
272 const std::vector<Eigen::MatrixXd>& time_result_ds_vec,
273 const std::vector<Eigen::MatrixXd>& l_warm_up_vec,
274 const std::vector<Eigen::MatrixXd>& n_warm_up_vec,
275 const std::vector<Eigen::MatrixXd>& dual_l_result_ds_vec,
276 const std::vector<Eigen::MatrixXd>& dual_n_result_ds_vec,
277 Eigen::MatrixXd* xWS, Eigen::MatrixXd* uWS,
278 Eigen::MatrixXd* state_result_ds, Eigen::MatrixXd* control_result_ds,
279 Eigen::MatrixXd* time_result_ds, Eigen::MatrixXd* l_warm_up,
280 Eigen::MatrixXd* n_warm_up, Eigen::MatrixXd* dual_l_result_ds,
281 Eigen::MatrixXd* dual_n_result_ds) {
282 // Repeated midway state point are not added
283 size_t warm_start_state_size = 0;
284 for (const auto& warm_start_state : xWS_vec) {
285 warm_start_state_size += warm_start_state.cols();
286 }
287 warm_start_state_size -= xWS_vec.size() - 1;
288
289 size_t warm_start_control_size = 0;
290 for (const auto& warm_start_control : uWS_vec) {
291 warm_start_control_size += warm_start_control.cols();
292 }
293
294 // Repeated midway state point are not added
295 size_t smoothed_state_size = 0;
296 for (const auto& smoothed_state : state_result_ds_vec) {
297 smoothed_state_size += smoothed_state.cols();
298 }
299 smoothed_state_size -= state_result_ds_vec.size() - 1;
300
301 size_t smoothed_control_size = 0;
302 for (const auto& smoothed_control : control_result_ds_vec) {
303 smoothed_control_size += smoothed_control.cols();
304 }
305
306 size_t time_size = 0;
307 for (const auto& smoothed_time : time_result_ds_vec) {
308 time_size += smoothed_time.cols();
309 }
310
311 size_t l_warm_start_size = 0;
312 for (const auto& l_warm_start : l_warm_up_vec) {
313 l_warm_start_size += l_warm_start.cols();
314 }
315
316 size_t n_warm_start_size = 0;
317 for (const auto& n_warm_start : n_warm_up_vec) {
318 n_warm_start_size += n_warm_start.cols();
319 }
320
321 size_t l_smoothed_size = 0;
322 for (const auto& l_smoothed : dual_l_result_ds_vec) {
323 l_smoothed_size += l_smoothed.cols();
324 }
325
326 size_t n_smoothed_size = 0;
327 for (const auto& n_smoothed : dual_n_result_ds_vec) {
328 n_smoothed_size += n_smoothed.cols();
329 }
330
331 Eigen::MatrixXd xWS_ =
332 Eigen::MatrixXd::Zero(xWS_vec[0].rows(), warm_start_state_size);
333 Eigen::MatrixXd uWS_ =
334 Eigen::MatrixXd::Zero(uWS_vec[0].rows(), warm_start_control_size);
335 Eigen::MatrixXd state_result_ds_ =
336 Eigen::MatrixXd::Zero(state_result_ds_vec[0].rows(), smoothed_state_size);
337 Eigen::MatrixXd control_result_ds_ = Eigen::MatrixXd::Zero(
338 control_result_ds_vec[0].rows(), smoothed_control_size);
339 Eigen::MatrixXd time_result_ds_ =
340 Eigen::MatrixXd::Zero(time_result_ds_vec[0].rows(), time_size);
341 Eigen::MatrixXd l_warm_up_ =
342 Eigen::MatrixXd::Zero(l_warm_up_vec[0].rows(), l_warm_start_size);
343 Eigen::MatrixXd n_warm_up_ =
344 Eigen::MatrixXd::Zero(n_warm_up_vec[0].rows(), n_warm_start_size);
345 Eigen::MatrixXd dual_l_result_ds_ =
346 Eigen::MatrixXd::Zero(dual_l_result_ds_vec[0].rows(), l_smoothed_size);
347 Eigen::MatrixXd dual_n_result_ds_ =
348 Eigen::MatrixXd::Zero(dual_n_result_ds_vec[0].rows(), n_smoothed_size);
349
350 size_t traj_size = xWS_vec.size();
351
352 uint64_t counter = 0;
353 for (size_t i = 0; i < traj_size; ++i) {
354 // leave out the last repeated point so set column minus one
355 uint64_t warm_start_state_cols = xWS_vec[i].cols() - 1;
356 for (size_t j = 0; j < warm_start_state_cols; ++j) {
357 xWS_.col(counter) = xWS_vec[i].col(j);
358 ++counter;
359 }
360 }
361 xWS_.col(counter) = xWS_vec.back().col(xWS_vec.back().cols() - 1);
362 ++counter;
363 CHECK_EQ(counter, warm_start_state_size);
364
365 counter = 0;
366 for (size_t i = 0; i < traj_size; ++i) {
367 // leave out the last repeated point so set column minus one
368 uint64_t warm_start_control_cols = uWS_vec[i].cols();
369 for (size_t j = 0; j < warm_start_control_cols; ++j) {
370 uWS_.col(counter) = uWS_vec[i].col(j);
371 ++counter;
372 }
373 }
374 CHECK_EQ(counter, warm_start_control_size);
375
376 counter = 0;
377 for (size_t i = 0; i < traj_size; ++i) {
378 // leave out the last repeated point so set column minus one
379 uint64_t smoothed_state_cols = state_result_ds_vec[i].cols() - 1;
380 for (size_t j = 0; j < smoothed_state_cols; ++j) {
381 state_result_ds_.col(counter) = state_result_ds_vec[i].col(j);
382 ++counter;
383 }
384 }
385 state_result_ds_.col(counter) =
386 state_result_ds_vec.back().col(state_result_ds_vec.back().cols() - 1);
387 ++counter;
388 CHECK_EQ(counter, smoothed_state_size);
389
390 counter = 0;
391 for (size_t i = 0; i < traj_size; ++i) {
392 // leave out the last repeated point so set column minus one
393 uint64_t smoothed_control_cols = control_result_ds_vec[i].cols();
394 for (size_t j = 0; j < smoothed_control_cols; ++j) {
395 control_result_ds_.col(counter) = control_result_ds_vec[i].col(j);
396 ++counter;
397 }
398 }
399 CHECK_EQ(counter, smoothed_control_size);
400
401 counter = 0;
402 for (size_t i = 0; i < traj_size; ++i) {
403 // leave out the last repeated point so set column minus one
404 uint64_t time_cols = time_result_ds_vec[i].cols();
405 for (size_t j = 0; j < time_cols; ++j) {
406 time_result_ds_.col(counter) = time_result_ds_vec[i].col(j);
407 ++counter;
408 }
409 }
410 CHECK_EQ(counter, time_size);
411
412 counter = 0;
413 for (size_t i = 0; i < traj_size; ++i) {
414 // leave out the last repeated point so set column minus one
415 uint64_t l_warm_up_cols = l_warm_up_vec[i].cols();
416 for (size_t j = 0; j < l_warm_up_cols; ++j) {
417 l_warm_up_.col(counter) = l_warm_up_vec[i].col(j);
418 ++counter;
419 }
420 }
421 CHECK_EQ(counter, l_warm_start_size);
422
423 counter = 0;
424 for (size_t i = 0; i < traj_size; ++i) {
425 // leave out the last repeated point so set column minus one
426 uint64_t n_warm_up_cols = n_warm_up_vec[i].cols();
427 for (size_t j = 0; j < n_warm_up_cols; ++j) {
428 n_warm_up_.col(counter) = n_warm_up_vec[i].col(j);
429 ++counter;
430 }
431 }
432 CHECK_EQ(counter, n_warm_start_size);
433
434 counter = 0;
435 for (size_t i = 0; i < traj_size; ++i) {
436 // leave out the last repeated point so set column minus one
437 uint64_t dual_l_result_ds_cols = dual_l_result_ds_vec[i].cols();
438 for (size_t j = 0; j < dual_l_result_ds_cols; ++j) {
439 dual_l_result_ds_.col(counter) = dual_l_result_ds_vec[i].col(j);
440 ++counter;
441 }
442 }
443 CHECK_EQ(counter, l_smoothed_size);
444
445 counter = 0;
446 for (size_t i = 0; i < traj_size; ++i) {
447 // leave out the last repeated point so set column minus one
448 uint64_t dual_n_result_ds_cols = dual_n_result_ds_vec[i].cols();
449 for (size_t j = 0; j < dual_n_result_ds_cols; ++j) {
450 dual_n_result_ds_.col(counter) = dual_n_result_ds_vec[i].col(j);
451 ++counter;
452 }
453 }
454 CHECK_EQ(counter, n_smoothed_size);
455
456 *xWS = std::move(xWS_);
457 *uWS = std::move(uWS_);
458 *state_result_ds = std::move(state_result_ds_);
459 *control_result_ds = std::move(control_result_ds_);
460 *time_result_ds = std::move(time_result_ds_);
461 *l_warm_up = std::move(l_warm_up_);
462 *n_warm_up = std::move(n_warm_up_);
463 *dual_l_result_ds = std::move(dual_l_result_ds_);
464 *dual_n_result_ds = std::move(dual_n_result_ds_);
465}
466
467bool Optimizer::GenerateDistanceApproachTraj(
468 const Eigen::MatrixXd& xWS, const Eigen::MatrixXd& uWS,
469 const std::vector<double>& XYbounds,
470 const Eigen::MatrixXi& obstacles_edges_num,
471 const Eigen::MatrixXd& obstacles_A, const Eigen::MatrixXd& obstacles_b,
472 const std::vector<std::vector<Vec2d>>& obstacles_vertices_vec,
473 const Eigen::MatrixXd& last_time_u, const double init_v,
474 Eigen::MatrixXd* state_result_ds, Eigen::MatrixXd* control_result_ds,
475 Eigen::MatrixXd* time_result_ds, Eigen::MatrixXd* l_warm_up,
476 Eigen::MatrixXd* n_warm_up, Eigen::MatrixXd* dual_l_result_ds,
477 Eigen::MatrixXd* dual_n_result_ds) {
478 size_t horizon = xWS.cols() - 1;
479 Eigen::MatrixXd x0(4, 1);
480 x0 << xWS(0, 0), xWS(1, 0), xWS(2, 0), init_v;
481
482 Eigen::MatrixXd xF(4, 1);
483 xF << xWS(0, horizon), xWS(1, horizon), xWS(2, horizon), xWS(3, horizon);
484
485 // load vehicle configuration
486 const common::VehicleParam& vehicle_param_ =
488 double front_to_center = vehicle_param_.front_edge_to_center();
489 double back_to_center = vehicle_param_.back_edge_to_center();
490 double left_to_center = vehicle_param_.left_edge_to_center();
491 double right_to_center = vehicle_param_.right_edge_to_center();
492 Eigen::MatrixXd ego(4, 1);
493 ego << front_to_center, right_to_center, back_to_center, left_to_center;
494
495 // Get obstacle num
496 size_t obstacles_num = obstacles_vertices_vec.size();
497
498 // Get timestep delta t
499 double ts = FLAGS_open_space_delta_t;
500
501 // slack_warm_up, temp usage
502 Eigen::MatrixXd s_warm_up = Eigen::MatrixXd::Zero(obstacles_num, horizon + 1);
503
504 // Dual variable warm start for distance approach problem
505 if (FLAGS_use_dual_variable_warm_start) {
506 if (dual_variable_warm_start_->Solve(
507 horizon, ts, ego, obstacles_num, obstacles_edges_num, obstacles_A,
508 obstacles_b, xWS, l_warm_up, n_warm_up, &s_warm_up)) {
509 ADEBUG << "Dual variable problem solved successfully!";
510 } else {
511 AERROR << "Dual variable problem failed to solve";
512 return false;
513 }
514 } else {
515 *l_warm_up =
516 0.5 * Eigen::MatrixXd::Ones(obstacles_edges_num.sum(), horizon + 1);
517 *n_warm_up = 0.5 * Eigen::MatrixXd::Ones(4 * obstacles_num, horizon + 1);
518 }
519
520 // Distance approach trajectory smoothing
521 if (distance_approach_->Solve(
522 x0, xF, last_time_u, horizon, ts, ego, xWS, uWS, *l_warm_up,
523 *n_warm_up, s_warm_up, XYbounds, obstacles_num, obstacles_edges_num,
524 obstacles_A, obstacles_b, state_result_ds, control_result_ds,
525 time_result_ds, dual_l_result_ds, dual_n_result_ds)) {
526 ADEBUG << "Distance approach problem solved successfully!";
527 } else {
528 AERROR << "Distance approach problem failed to solve";
529 if (FLAGS_enable_smoother_failsafe) {
530 UseWarmStartAsResult(xWS, uWS, *l_warm_up, *n_warm_up, state_result_ds,
531 control_result_ds, time_result_ds, dual_l_result_ds,
532 dual_n_result_ds);
533 } else {
534 return false;
535 }
536 }
537 return true;
538}
539
540bool Optimizer::GenerateDecoupledTraj(
541 const Eigen::MatrixXd& xWS, const double init_a, const double init_v,
542 const std::vector<std::vector<Vec2d>>& obstacles_vertices_vec,
543 Eigen::MatrixXd* state_result_dc, Eigen::MatrixXd* control_result_dc,
544 Eigen::MatrixXd* time_result_dc) {
545 DiscretizedTrajectory smoothed_trajectory;
546 if (!iterative_anchoring_smoother_->Smooth(
547 xWS, init_a, init_v, obstacles_vertices_vec, &smoothed_trajectory)) {
548 return false;
549 }
550
551 LoadResult(smoothed_trajectory, state_result_dc, control_result_dc,
552 time_result_dc);
553 return true;
554}
555
556void Optimizer::UseWarmStartAsResult(
557 const Eigen::MatrixXd& xWS, const Eigen::MatrixXd& uWS,
558 const Eigen::MatrixXd& l_warm_up, const Eigen::MatrixXd& n_warm_up,
559 Eigen::MatrixXd* state_result_ds, Eigen::MatrixXd* control_result_ds,
560 Eigen::MatrixXd* time_result_ds, Eigen::MatrixXd* dual_l_result_ds,
561 Eigen::MatrixXd* dual_n_result_ds) {
562 AERROR << "Use warm start as trajectory output";
563
564 *state_result_ds = xWS;
565 *control_result_ds = uWS;
566 *dual_l_result_ds = l_warm_up;
567 *dual_n_result_ds = n_warm_up;
568
569 size_t time_result_horizon = xWS.cols() - 1;
570 *time_result_ds = Eigen::MatrixXd::Constant(
571 1, time_result_horizon, FLAGS_open_space_delta_t);
572}
573
574void Optimizer::PartitionTrajectory(
575 const DiscretizedTrajectory& raw_trajectory,
576 std::vector<DiscretizedTrajectory>* partitioned_trajectories) {
577 size_t horizon = raw_trajectory.size();
578
579 partitioned_trajectories->clear();
580 partitioned_trajectories->emplace_back();
581 DiscretizedTrajectory* current_trajectory =
582 &(partitioned_trajectories->back());
583
584 // Decide initial gear
585 const auto& first_path_point = raw_trajectory.front().path_point();
586 const auto& second_path_point = raw_trajectory[1].path_point();
587 double heading_angle = first_path_point.theta();
588 const Vec2d init_tracking_vector(
589 second_path_point.x() - first_path_point.x(),
590 second_path_point.y() - first_path_point.y());
591 double tracking_angle = init_tracking_vector.Angle();
592 auto gear =
593 std::abs(common::math::NormalizeAngle(tracking_angle - heading_angle)) <
594 (M_PI_2)
596 : canbus::Chassis::GEAR_REVERSE;
597
598 // Set accumulated distance
599 Vec2d last_pos_vec(first_path_point.x(), first_path_point.y());
600 double distance_s = 0.0;
601 bool is_trajectory_last_point = false;
602
603 for (size_t i = 0; i < horizon - 1; ++i) {
604 current_trajectory->push_back(raw_trajectory.at(i));
605 const TrajectoryPoint& trajectory_point = raw_trajectory.at(i);
606 const TrajectoryPoint& next_trajectory_point = raw_trajectory.at(i + 1);
607
608 // Check gear change
609 heading_angle = trajectory_point.path_point().theta();
610 const Vec2d tracking_vector(next_trajectory_point.path_point().x() -
611 trajectory_point.path_point().x(),
612 next_trajectory_point.path_point().y() -
613 trajectory_point.path_point().y());
614 tracking_angle = tracking_vector.Angle();
615 auto cur_gear =
616 std::abs(common::math::NormalizeAngle(tracking_angle - heading_angle)) <
617 (M_PI_2)
619 : canbus::Chassis::GEAR_REVERSE;
620
621 if (cur_gear != gear) {
622 gear = cur_gear;
623 partitioned_trajectories->emplace_back();
624 current_trajectory = &(partitioned_trajectories->back());
625 current_trajectory->push_back(raw_trajectory.at(i));
626 }
627 }
628 current_trajectory->push_back(raw_trajectory.back());
629}
630
631void Optimizer::LoadTrajectory(
632 const Eigen::MatrixXd& state_result, const Eigen::MatrixXd& control_result,
633 const Eigen::MatrixXd& time_result) {
634 optimized_trajectory_.clear();
635
636 // Optimizer doesn't take end condition control state into consideration for
637 // now
638 size_t states_size = state_result.cols();
639 size_t times_size = time_result.cols();
640 size_t controls_size = control_result.cols();
641 CHECK_EQ(states_size, times_size + 1);
642 CHECK_EQ(states_size, controls_size + 1);
643 double relative_time = 0.0;
644 double relative_s = 0.0;
645 Vec2d last_path_point(state_result(0, 0), state_result(1, 0));
646 for (size_t i = 0; i < states_size; ++i) {
647 TrajectoryPoint point;
648 point.mutable_path_point()->set_x(state_result(0, i));
649 point.mutable_path_point()->set_y(state_result(1, i));
650 point.mutable_path_point()->set_theta(state_result(2, i));
651 point.set_v(state_result(3, i));
652 Vec2d cur_path_point(state_result(0, i), state_result(1, i));
653 relative_s += cur_path_point.DistanceTo(last_path_point);
654 point.mutable_path_point()->set_s(relative_s);
655 // TODO(Jinyun): Evaluate how to set end states control input
656 if (i == controls_size) {
657 point.set_steer(0.0);
658 point.set_a(0.0);
659 } else {
660 point.set_steer(control_result(0, i));
661 point.set_a(control_result(1, i));
662 }
663
664 if (i == 0) {
665 point.set_relative_time(relative_time);
666 } else {
667 relative_time += time_result(0, i - 1);
668 point.set_relative_time(relative_time);
669 }
670
671 optimized_trajectory_.emplace_back(point);
672 last_path_point = cur_path_point;
673 }
674}
675
676void Optimizer::LoadResult(
677 const DiscretizedTrajectory& discretized_trajectory,
678 Eigen::MatrixXd* state_result_dc, Eigen::MatrixXd* control_result_dc,
679 Eigen::MatrixXd* time_result_dc) {
680 const size_t points_size = discretized_trajectory.size();
681 CHECK_GT(points_size, 1U);
682 *state_result_dc = Eigen::MatrixXd::Zero(4, points_size);
683 *control_result_dc = Eigen::MatrixXd::Zero(2, points_size - 1);
684 *time_result_dc = Eigen::MatrixXd::Zero(1, points_size - 1);
685
686 auto& state_result = *state_result_dc;
687 for (size_t i = 0; i < points_size; ++i) {
688 state_result(0, i) = discretized_trajectory[i].path_point().x();
689 state_result(1, i) = discretized_trajectory[i].path_point().y();
690 state_result(2, i) = discretized_trajectory[i].path_point().theta();
691 state_result(3, i) = discretized_trajectory[i].v();
692 }
693
694 auto& control_result = *control_result_dc;
695 auto& time_result = *time_result_dc;
696 const double wheel_base = common::VehicleConfigHelper::Instance()
697 ->GetConfig()
698 .vehicle_param()
699 .wheel_base();
700 for (size_t i = 0; i + 1 < points_size; ++i) {
701 control_result(0, i) =
702 std::atan(discretized_trajectory[i].path_point().kappa() * wheel_base);
703 control_result(1, i) = discretized_trajectory[i].a();
704 time_result(0, i) = discretized_trajectory[i + 1].relative_time() -
705 discretized_trajectory[i].relative_time();
706 }
707}
708
709void Optimizer::RecordDebugInfo(
710 const Vec2d& translate_origin, const double rotate_angle,
711 const std::vector<double>& end_pose, const Eigen::MatrixXd& xWS,
712 const Eigen::MatrixXd& uWS, const Eigen::MatrixXd& l_warm_up,
713 const Eigen::MatrixXd& n_warm_up, const Eigen::MatrixXd& dual_l_result_ds,
714 const Eigen::MatrixXd& dual_n_result_ds,
715 const Eigen::MatrixXd& state_result_ds,
716 const Eigen::MatrixXd& control_result_ds,
717 const Eigen::MatrixXd& time_result_ds,
718 const std::vector<double> XYbounds,
719 const std::vector<std::vector<Vec2d>>& obstacles_vertices_vec) {
720 // load information about trajectory stitching point
721 common::TrajectoryPoint point;
722 point.mutable_path_point()->set_x(0.0);
723 point.mutable_path_point()->set_y(0.0);
724 point.mutable_path_point()->set_z(0.0);
725 point.mutable_path_point()->set_theta(0.0);
726 point.mutable_path_point()->set_s(0.0);
727 point.mutable_path_point()->set_kappa(0.0);
728 point.mutable_path_point()->set_dkappa(0.0);
729 point.mutable_path_point()->set_ddkappa(0.0);
730 point.set_v(0.0);
731 point.set_a(0.0);
732 point.set_relative_time(0.0);
733
734 open_space_debug_.mutable_trajectory_stitching_point()->CopyFrom(
735 point);
736
737 // load translation origin and heading angle
738 auto roi_shift_point = open_space_debug_.mutable_roi_shift_point();
739 // open_space_debug_.mutable_roi_shift_point()->mutable_path_point()->set_x();
740 roi_shift_point->mutable_path_point()->set_x(translate_origin.x());
741 roi_shift_point->mutable_path_point()->set_y(translate_origin.y());
742 roi_shift_point->mutable_path_point()->set_theta(rotate_angle);
743
744 // load end_pose into debug
745 auto* end_point = open_space_debug_.mutable_end_point();
746 end_point->mutable_path_point()->set_x(end_pose[0]);
747 end_point->mutable_path_point()->set_y(end_pose[1]);
748 end_point->mutable_path_point()->set_theta(end_pose[2]);
749 end_point->set_v(end_pose[3]);
750
751 // load warm start trajectory
752 size_t horizon = xWS.cols() - 1;
753 auto* warm_start_trajectory =
754 open_space_debug_.mutable_warm_start_trajectory();
755 for (size_t i = 0; i < horizon; ++i) {
756 auto* warm_start_point = warm_start_trajectory->add_vehicle_motion_point();
757 warm_start_point->mutable_trajectory_point()->mutable_path_point()->set_x(
758 xWS(0, i));
759 warm_start_point->mutable_trajectory_point()->mutable_path_point()->set_y(
760 xWS(1, i));
761 warm_start_point->mutable_trajectory_point()
762 ->mutable_path_point()
763 ->set_theta(xWS(2, i));
764 warm_start_point->mutable_trajectory_point()->set_v(xWS(3, i));
765 warm_start_point->set_steer(uWS(0, i));
766 warm_start_point->mutable_trajectory_point()->set_a(uWS(1, i));
767 }
768 auto* warm_start_point = warm_start_trajectory->add_vehicle_motion_point();
769 warm_start_point->mutable_trajectory_point()->mutable_path_point()->set_x(
770 xWS(0, horizon));
771 warm_start_point->mutable_trajectory_point()->mutable_path_point()->set_y(
772 xWS(1, horizon));
773 warm_start_point->mutable_trajectory_point()->mutable_path_point()->set_theta(
774 xWS(2, horizon));
775 warm_start_point->mutable_trajectory_point()->set_v(xWS(3, horizon));
776
777 // load warm start dual variables
778 size_t l_warm_up_rows = l_warm_up.rows();
779 for (size_t i = 0; i < horizon; ++i) {
780 for (size_t j = 0; j < l_warm_up_rows; j++) {
781 open_space_debug_.add_warm_start_dual_lambda(l_warm_up(j, i));
782 }
783 }
784 size_t n_warm_up_rows = n_warm_up.rows();
785 for (size_t i = 0; i < horizon; ++i) {
786 for (size_t j = 0; j < n_warm_up_rows; j++) {
787 open_space_debug_.add_warm_start_dual_miu(n_warm_up(j, i));
788 }
789 }
790
791 // load optimized dual variables
792 size_t dual_l_result_ds_rows = dual_l_result_ds.rows();
793 for (size_t i = 0; i < horizon; ++i) {
794 for (size_t j = 0; j < dual_l_result_ds_rows; j++) {
795 open_space_debug_.add_optimized_dual_lambda(dual_l_result_ds(j, i));
796 }
797 }
798 size_t dual_n_result_ds_rows = dual_n_result_ds.rows();
799 for (size_t i = 0; i < horizon; ++i) {
800 for (size_t j = 0; j < dual_n_result_ds_rows; j++) {
801 open_space_debug_.add_optimized_dual_miu(dual_n_result_ds(j, i));
802 }
803 }
804
805 double relative_time = 0;
806
807 // load smoothed trajectory
808 horizon = state_result_ds.cols() - 1;
809 auto* smoothed_trajectory = open_space_debug_.mutable_smoothed_trajectory();
810 for (size_t i = 0; i < horizon; ++i) {
811 auto* smoothed_point = smoothed_trajectory->add_vehicle_motion_point();
812 smoothed_point->mutable_trajectory_point()->mutable_path_point()->set_x(
813 state_result_ds(0, i));
814 smoothed_point->mutable_trajectory_point()->mutable_path_point()->set_y(
815 state_result_ds(1, i));
816 smoothed_point->mutable_trajectory_point()->mutable_path_point()->set_theta(
817 state_result_ds(2, i));
818 smoothed_point->mutable_trajectory_point()->set_v(state_result_ds(3, i));
819 smoothed_point->set_steer(control_result_ds(0, i));
820 smoothed_point->mutable_trajectory_point()->set_a(control_result_ds(1, i));
821 relative_time += time_result_ds(0, i);
822 smoothed_point->mutable_trajectory_point()->set_relative_time(
823 relative_time);
824 }
825 auto* smoothed_point = smoothed_trajectory->add_vehicle_motion_point();
826 smoothed_point->mutable_trajectory_point()->mutable_path_point()->set_x(
827 state_result_ds(0, horizon));
828 smoothed_point->mutable_trajectory_point()->mutable_path_point()->set_y(
829 state_result_ds(1, horizon));
830 smoothed_point->mutable_trajectory_point()->mutable_path_point()->set_theta(
831 state_result_ds(2, horizon));
832 smoothed_point->mutable_trajectory_point()->set_v(
833 state_result_ds(3, horizon));
834
835 // load xy boundary (xmin, xmax, ymin, ymax)
836 open_space_debug_.add_xy_boundary(XYbounds[0]);
837 open_space_debug_.add_xy_boundary(XYbounds[1]);
838 open_space_debug_.add_xy_boundary(XYbounds[2]);
839 open_space_debug_.add_xy_boundary(XYbounds[3]);
840
841 // load obstacles
842 for (const auto& obstacle_vertices : obstacles_vertices_vec) {
843 auto* obstacle_ptr = open_space_debug_.add_obstacles();
844 for (const auto& vertex : obstacle_vertices) {
845 obstacle_ptr->add_vertices_x_coords(vertex.x());
846 obstacle_ptr->add_vertices_y_coords(vertex.y());
847 }
848 }
849}
850
852 planning_internal::OpenSpaceDebug* open_space_debug) {
853 open_space_debug->MergeFrom(open_space_debug_);
854}
855
856} // namespace planning
857} // 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 const VehicleConfig & GetConfig()
Get the current vehicle configuration.
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
const std::vector< double > & ROI_xy_boundary() const
const std::vector< double > & open_space_end_pose() const
const common::math::Vec2d & origin_point() const
const Eigen::MatrixXd & obstacles_A() const
const std::vector< std::vector< common::math::Vec2d > > & obstacles_vertices_vec() const
const Eigen::MatrixXd & obstacles_b() const
const Eigen::MatrixXi & obstacles_edges_num() const
const DiscretizedTrajectory & path_planning_trajectory_result() const
static void PathPointNormalizing(double rotate_angle, const common::math::Vec2d &translate_origin, double *x, double *y, double *phi)
static void PathPointDeNormalizing(double rotate_angle, const common::math::Vec2d &translate_origin, double *x, double *y, double *phi)
void UpdateDebugInfo(planning_internal::OpenSpaceDebug *open_space_debug)
Definition optimizer.cc:851
Optimizer(const OpenSpaceTrajectoryOptimizerParkConfig &config)
Definition optimizer.cc:34
common::Status Plan(const OpenSpaceInfo open_space_info)
Definition optimizer.cc:55
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
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