Apollo 11.0
自动驾驶开放平台
open_space_trajectory_post_process.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
21
22#include <algorithm>
23#include <memory>
24#include <queue>
25
26#include "absl/strings/str_cat.h"
27
28#include "cyber/time/clock.h"
32
33namespace apollo {
34namespace planning {
35
45
47 const std::string& config_dir, const std::string& name,
48 const std::shared_ptr<DependencyInjector>& injector) {
49 if (!Task::Init(config_dir, name, injector)) {
50 return false;
51 }
52 // Load the config this task.
53 bool res = Task::LoadConfig<OpenSpaceTrajectoryPostProcessConfig>(&config_);
54 heading_search_range_ = config_.heading_search_range();
55 heading_track_range_ = config_.heading_track_range();
56 distance_search_range_ = config_.distance_search_range();
57 heading_offset_to_midpoint_ = config_.heading_offset_to_midpoint();
58 lateral_offset_to_midpoint_ = config_.lateral_offset_to_midpoint();
59 longitudinal_offset_to_midpoint_ = config_.longitudinal_offset_to_midpoint();
60 vehicle_box_iou_threshold_to_midpoint_ =
62 scale_destination_ = config_.scale_destination();
63 stop_check_window_ = config_.stop_check_window();
64 vehicle_param_ =
65 common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param();
66 ego_length_ = vehicle_param_.length();
67 ego_width_ = vehicle_param_.width();
68 shift_distance_ = ego_length_ / 2.0 - vehicle_param_.back_edge_to_center();
69 wheel_base_ = vehicle_param_.wheel_base();
70 AINFO << config_.DebugString();
71 return res;
72}
73
74Status OpenSpaceTrajectoryPostProcess::Process() {
75 const auto& open_space_info = frame_->open_space_info();
76 auto open_space_info_ptr = frame_->mutable_open_space_info();
77 if (open_space_info_ptr->optimizer_trajectory_data().empty()) {
78 AINFO << "optimize trajectory empty";
79 return Status::OK();
80 }
81
82 const Frame* previous_frame = injector_->frame_history()->Latest();
83 if (previous_frame != nullptr) {
84 *(open_space_info_ptr->mutable_partitioned_trajectories()) =
85 previous_frame->open_space_info().partitioned_trajectories();
86 *(open_space_info_ptr->mutable_interpolated_trajectory_result()) =
87 previous_frame->open_space_info().interpolated_trajectory_result();
88 }
89
90 if (open_space_info_ptr->partitioned_trajectories().empty()) {
91 const auto& optimized_trajectory_result =
92 open_space_info.optimizer_trajectory_data();
93
94 auto* interpolated_trajectory_result_ptr =
95 open_space_info_ptr->mutable_interpolated_trajectory_result();
96
97 InterpolateTrajectory(optimized_trajectory_result,
98 interpolated_trajectory_result_ptr);
99
100 auto* partitioned_trajectories =
101 open_space_info_ptr->mutable_partitioned_trajectories();
102
103 PartitionTrajectory(*interpolated_trajectory_result_ptr,
104 partitioned_trajectories);
105
106 auto* open_space_status = injector_->planning_context()
107 ->mutable_planning_status()
108 ->mutable_open_space();
109 open_space_status->set_position_init(true);
110 auto* chosen_partitioned_trajectory =
111 open_space_info_ptr->mutable_chosen_partitioned_trajectory();
112 AdjustRelativeTimeAndS(open_space_info.partitioned_trajectories(), 0, 0,
113 chosen_partitioned_trajectory);
114 current_trajectory_index_ = 0;
115 fail_search_fallback_ = false;
116 last_index_ = -1;
117 return Status::OK();
118 }
119
120 auto* partitioned_trajectories =
121 open_space_info_ptr->mutable_partitioned_trajectories();
122 // Choose the one to follow based on the closest partitioned trajectory
123 size_t trajectories_size = partitioned_trajectories->size();
124 // may get stop trajecotry;
125 current_trajectory_index_ =
126 std::min<size_t>(trajectories_size - 1, current_trajectory_index_);
127 size_t current_trajectory_point_index = 0;
128 bool flag_change_to_next = false;
129
130 // Vehicle related information used to choose closest point
131 UpdateVehicleInfo();
132 AINFO << "current_trajectory_index_" << current_trajectory_index_;
133 const auto& gear =
134 partitioned_trajectories->at(current_trajectory_index_).second;
135 const auto& cur_trajectory =
136 partitioned_trajectories->at(current_trajectory_index_).first;
137 size_t trajectory_size = cur_trajectory.size();
138 CHECK_GT(trajectory_size, 0U);
139 flag_change_to_next = CheckReachTrajectoryEnd(
140 cur_trajectory, gear, trajectories_size, &current_trajectory_point_index);
141 AINFO << "current_trajectory_index_" << current_trajectory_index_ << ","
142 << current_trajectory_point_index << "time index" << last_index_
143 << "flag_change_to_next" << flag_change_to_next;
144 auto* chosen_partitioned_trajectory =
145 open_space_info_ptr->mutable_chosen_partitioned_trajectory();
146
147 // check if ego arrive destination
148 if (current_trajectory_index_ == partitioned_trajectories->size() - 1
149 && current_trajectory_point_index == cur_trajectory.size() - 1) {
150 AINFO << "reach destination";
152 GenerateStopTrajectory(
153 frame_->local_view().chassis->gear_location(),
154 chosen_partitioned_trajectory);
155 return Status::OK();
156 }
157
158 auto chosen_trajectory = &(chosen_partitioned_trajectory->first);
159 AINFO << "Before InsertGearShiftTrajectory [" << chosen_trajectory->size();
160 if (config_.use_gear_shift_trajectory()) {
161 if (InsertGearShiftTrajectory(flag_change_to_next,
162 current_trajectory_index_,
163 open_space_info.partitioned_trajectories(),
164 chosen_partitioned_trajectory) &&
165 chosen_partitioned_trajectory->first.size() != 0) {
166 chosen_trajectory = &(chosen_partitioned_trajectory->first);
167 ADEBUG << "After InsertGearShiftTrajectory [" << chosen_trajectory->size()
168 << "]";
169 last_index_ = -1;
170 return Status::OK();
171 }
172 }
173 AINFO << "Before InsertStopTrajectory [" << chosen_trajectory->size();
174 // Choose the closest point to track
175 std::priority_queue<std::pair<size_t, double>,
176 std::vector<std::pair<size_t, double>>, comp_>
177 closest_point;
178 AINFO << "ego:" << std::fixed << ego_x_ << "," << ego_y_ << ","
179 << vehicle_moving_direction_;
180 for (size_t j = 0; j < trajectory_size; ++j) {
181 const TrajectoryPoint& trajectory_point = cur_trajectory.at(j);
182 const PathPoint& path_point = trajectory_point.path_point();
183 const double path_point_x = path_point.x();
184 const double path_point_y = path_point.y();
185 const double path_point_theta = path_point.theta();
186 const Vec2d tracking_vector(path_point_x - ego_x_, path_point_y - ego_y_);
187 const double distance = tracking_vector.Length();
188 // const double tracking_direction = tracking_vector.Angle();
189 const double traj_point_moving_direction =
191 ? NormalizeAngle(path_point_theta + M_PI)
192 : path_point_theta;
193 // const double head_track_difference = std::abs(
194 // NormalizeAngle(tracking_direction - vehicle_moving_direction_));
195 const double heading_search_difference = std::abs(NormalizeAngle(
196 traj_point_moving_direction - vehicle_moving_direction_));
197 // AINFO << "XY" << std::fixed << path_point_x << "," << path_point_y << ","
198 // << path_point_theta << "," << distance << ","
199 // << heading_search_difference << "ego heading"
200 // << vehicle_moving_direction_;
201 if (distance < distance_search_range_ &&
202 heading_search_difference < heading_search_range_) {
203 // get vehicle box and path point box, compute IOU
204 Box2d path_point_box({path_point_x, path_point_y}, path_point_theta,
205 ego_length_, ego_width_);
206 Vec2d shift_vec{shift_distance_ * std::cos(path_point_theta),
207 shift_distance_ * std::sin(path_point_theta)};
208 path_point_box.Shift(shift_vec);
209 double iou_ratio =
210 Polygon2d(ego_box_).ComputeIoU(Polygon2d(path_point_box));
211 AINFO << std::fixed << "get closetst point" << path_point_x << ","
212 << path_point_y << " distance" << distance << "iou" << iou_ratio
213 << "pt theta" << traj_point_moving_direction;
214 closest_point.emplace(j, iou_ratio);
215 }
216 }
217
218 AINFO << "closest_point size" << closest_point.size() << " stop_check_count_: " << stop_check_count_;
219 static constexpr int stop_count_replan_threshold = 300;
220 if (closest_point.empty() || fail_search_fallback_ || stop_check_count_ > stop_count_replan_threshold) {
222 mutable_optimizer_trajectory_data()->clear();
224 mutable_path_planning_trajectory_result()->clear();
226 mutable_interpolated_trajectory_result()->clear();
228 mutable_partitioned_trajectories()->clear();
230 mutable_chosen_partitioned_trajectory()->first.clear();
231 const std::string msg =
232 "Fail to find nearest trajectory point to follow stop to fallback "
233 "replan";
234 AERROR << msg;
235 stop_check_count_ = 0;
236 return Status::OK();
237 }
238 current_trajectory_point_index = closest_point.top().first;
239 if (!flag_change_to_next) {
240 double veh_rel_time;
241 size_t time_match_index;
242 double now_time = Clock::Instance()->NowInSeconds();
243 auto& traj = partitioned_trajectories->at(current_trajectory_index_).first;
244 if (last_index_ != -1) {
245 veh_rel_time = traj[last_index_].relative_time() + now_time - last_time_;
246 AINFO << std::fixed << now_time << "," << last_time_;
247 time_match_index = traj.QueryLowerBoundPoint(veh_rel_time);
248 } else {
249 time_match_index = current_trajectory_point_index;
250 last_index_ = time_match_index;
251 last_time_ = now_time;
252 }
253
254 AINFO << "time_match_index" << time_match_index << "pos match index"
255 << current_trajectory_point_index;
256 AINFO << "TRAJ CLOSEST" << std::fixed
257 << traj.at(current_trajectory_point_index).path_point().x() << ","
258 << traj.at(current_trajectory_point_index).path_point().y();
259 if (std::abs(traj[time_match_index].path_point().s() -
260 traj.at(current_trajectory_point_index).path_point().s()) <
261 config_.speed_replan_distance()) {
262 current_trajectory_point_index = time_match_index;
263 } else {
264 AINFO << "reset speed because matched point too far";
265 last_index_ = current_trajectory_point_index;
266 last_time_ = now_time;
267 }
268 } else {
269 last_index_ = -1;
270 }
271
272 AINFO << "current_trajectory_point_index" << current_trajectory_point_index;
273 AdjustRelativeTimeAndS(open_space_info.partitioned_trajectories(),
274 current_trajectory_index_,
275 current_trajectory_point_index,
276 chosen_partitioned_trajectory);
277 return Status::OK();
278}
279
280void OpenSpaceTrajectoryPostProcess::InterpolateTrajectory(
281 const DiscretizedTrajectory& optimized_trajectory_result,
282 DiscretizedTrajectory* interpolated_trajectory) {
283 if (FLAGS_use_iterative_anchoring_smoother) {
284 *interpolated_trajectory = optimized_trajectory_result;
285 return;
286 }
287 interpolated_trajectory->clear();
288 size_t interpolated_pieces_num = config_.interpolated_pieces_num();
289 CHECK_GT(optimized_trajectory_result.size(), 0U);
290 CHECK_GT(interpolated_pieces_num, 0U);
291 size_t trajectory_to_be_partitioned_intervals_num =
292 optimized_trajectory_result.size() - 1;
293 size_t interpolated_points_num = interpolated_pieces_num - 1;
294 for (size_t i = 0; i < trajectory_to_be_partitioned_intervals_num; ++i) {
295 double relative_time_interval =
296 (optimized_trajectory_result.at(i + 1).relative_time() -
297 optimized_trajectory_result.at(i).relative_time()) /
298 static_cast<double>(interpolated_pieces_num);
299 interpolated_trajectory->push_back(optimized_trajectory_result.at(i));
300 for (size_t j = 0; j < interpolated_points_num; ++j) {
301 double relative_time =
302 optimized_trajectory_result.at(i).relative_time() +
303 (static_cast<double>(j) + 1.0) * relative_time_interval;
304 interpolated_trajectory->emplace_back(
306 optimized_trajectory_result.at(i),
307 optimized_trajectory_result.at(i + 1), relative_time));
308 }
309 }
310 interpolated_trajectory->push_back(optimized_trajectory_result.back());
311}
312
313void OpenSpaceTrajectoryPostProcess::UpdateVehicleInfo() {
314 const common::VehicleState& vehicle_state = frame_->vehicle_state();
315 ego_theta_ = vehicle_state.heading();
316 ego_x_ = vehicle_state.x();
317 ego_y_ = vehicle_state.y();
318 ego_v_ = vehicle_state.linear_velocity();
319 ego_gear_ = vehicle_state.gear();
320 Box2d box({ego_x_, ego_y_}, ego_theta_, ego_length_, ego_width_);
321 ego_box_ = std::move(box);
322 Vec2d ego_shift_vec{shift_distance_ * std::cos(ego_theta_),
323 shift_distance_ * std::sin(ego_theta_)};
324 ego_box_.Shift(ego_shift_vec);
325 vehicle_moving_direction_ =
326 vehicle_state.gear() == canbus::Chassis::GEAR_REVERSE
327 ? NormalizeAngle(ego_theta_ + M_PI)
328 : ego_theta_;
329 AINFO << fabs(ego_v_) << "speed" << vehicle_param_.max_abs_speed_when_stopped() << " " << stop_check_count_;
330 stop_check_count_ = fabs(ego_v_) < vehicle_param_.max_abs_speed_when_stopped() ?
331 stop_check_count_ + 1 : 0;
332}
333
334bool OpenSpaceTrajectoryPostProcess::EncodeTrajectory(
335 const DiscretizedTrajectory& trajectory, std::string* const encoding) {
336 if (trajectory.empty()) {
337 AERROR << "Fail to encode trajectory because it is empty";
338 return false;
339 }
340 static constexpr double encoding_origin_x = 58700.0;
341 static constexpr double encoding_origin_y = 4141000.0;
342 const auto& init_path_point = trajectory.front().path_point();
343 const auto& last_path_point = trajectory.back().path_point();
344
345 const int init_point_x =
346 static_cast<int>((init_path_point.x() - encoding_origin_x) * 1000.0);
347 const int init_point_y =
348 static_cast<int>((init_path_point.y() - encoding_origin_y) * 1000.0);
349 const int init_point_heading =
350 static_cast<int>(init_path_point.theta() * 10000.0);
351 const int last_point_x =
352 static_cast<int>((last_path_point.x() - encoding_origin_x) * 1000.0);
353 const int last_point_y =
354 static_cast<int>((last_path_point.y() - encoding_origin_y) * 1000.0);
355 const int last_point_heading =
356 static_cast<int>(last_path_point.theta() * 10000.0);
357
358 *encoding = absl::StrCat(
359 // init point
360 init_point_x, "_", init_point_y, "_", init_point_heading, "/",
361 // last point
362 last_point_x, "_", last_point_y, "_", last_point_heading);
363 return true;
364}
365
366bool OpenSpaceTrajectoryPostProcess::CheckTrajTraversed(
367 const std::string& trajectory_encoding_to_check) {
368 const auto& open_space_status =
369 injector_->planning_context()->planning_status().open_space();
370 const int index_history_size =
371 open_space_status.partitioned_trajectories_index_history_size();
372
373 if (index_history_size <= 1) {
374 return false;
375 }
376 for (int i = 0; i < index_history_size - 1; i++) {
377 const auto& index_history =
378 open_space_status.partitioned_trajectories_index_history(i);
379 if (index_history == trajectory_encoding_to_check) {
380 return true;
381 }
382 }
383 return false;
384}
385
386void OpenSpaceTrajectoryPostProcess::UpdateTrajHistory(
387 const std::string& chosen_trajectory_encoding) {
388 auto* open_space_status = injector_->planning_context()
389 ->mutable_planning_status()
390 ->mutable_open_space();
391
392 const auto& trajectory_history =
393 injector_->planning_context()
394 ->planning_status()
395 .open_space()
396 .partitioned_trajectories_index_history();
397 if (trajectory_history.empty()) {
398 open_space_status->add_partitioned_trajectories_index_history(
399 chosen_trajectory_encoding);
400 return;
401 }
402 if (*(trajectory_history.rbegin()) == chosen_trajectory_encoding) {
403 return;
404 }
405 open_space_status->add_partitioned_trajectories_index_history(
406 chosen_trajectory_encoding);
407}
408
409void OpenSpaceTrajectoryPostProcess::PartitionTrajectory(
410 const DiscretizedTrajectory& raw_trajectory,
411 std::vector<TrajGearPair>* partitioned_trajectories) {
412 CHECK_NOTNULL(partitioned_trajectories);
413
414 size_t horizon = raw_trajectory.size();
415
416 partitioned_trajectories->clear();
417 partitioned_trajectories->emplace_back();
418 TrajGearPair* current_trajectory_gear = &(partitioned_trajectories->back());
419
420 auto* trajectory = &(current_trajectory_gear->first);
421 auto* gear = &(current_trajectory_gear->second);
422
423 // Decide initial gear
424 const auto& first_path_point = raw_trajectory.front().path_point();
425 const auto& second_path_point = raw_trajectory[1].path_point();
426 double heading_angle = first_path_point.theta();
427 const Vec2d init_tracking_vector(
428 second_path_point.x() - first_path_point.x(),
429 second_path_point.y() - first_path_point.y());
430 double tracking_angle = init_tracking_vector.Angle();
431 *gear =
432 std::abs(common::math::NormalizeAngle(tracking_angle - heading_angle)) <
433 (M_PI_2)
435 : canbus::Chassis::GEAR_REVERSE;
436
437 // Set accumulated distance
438 Vec2d last_pos_vec(first_path_point.x(), first_path_point.y());
439 double distance_s = 0.0;
440 bool is_trajectory_last_point = false;
441
442 for (size_t i = 0; i < horizon - 1; ++i) {
443 const TrajectoryPoint& trajectory_point = raw_trajectory.at(i);
444 const TrajectoryPoint& next_trajectory_point = raw_trajectory.at(i + 1);
445
446 // Check gear change
447 heading_angle = trajectory_point.path_point().theta();
448 const Vec2d tracking_vector(next_trajectory_point.path_point().x() -
449 trajectory_point.path_point().x(),
450 next_trajectory_point.path_point().y() -
451 trajectory_point.path_point().y());
452 tracking_angle = tracking_vector.Angle();
453 auto cur_gear =
454 std::abs(common::math::NormalizeAngle(tracking_angle - heading_angle)) <
455 (M_PI_2)
457 : canbus::Chassis::GEAR_REVERSE;
458
459 if (cur_gear != *gear) {
460 is_trajectory_last_point = true;
461 LoadTrajectoryPoint(trajectory_point, is_trajectory_last_point, *gear,
462 &last_pos_vec, &distance_s, trajectory);
463 partitioned_trajectories->emplace_back();
464 current_trajectory_gear = &(partitioned_trajectories->back());
465 current_trajectory_gear->second = cur_gear;
466 distance_s = 0.0;
467 is_trajectory_last_point = false;
468 }
469
470 trajectory = &(current_trajectory_gear->first);
471 gear = &(current_trajectory_gear->second);
472
473 LoadTrajectoryPoint(trajectory_point, is_trajectory_last_point, *gear,
474 &last_pos_vec, &distance_s, trajectory);
475 }
476 is_trajectory_last_point = true;
477 const TrajectoryPoint& last_trajectory_point = raw_trajectory.back();
478 LoadTrajectoryPoint(last_trajectory_point, is_trajectory_last_point, *gear,
479 &last_pos_vec, &distance_s, trajectory);
480}
481
482void OpenSpaceTrajectoryPostProcess::LoadTrajectoryPoint(
483 const TrajectoryPoint& trajectory_point,
484 const bool is_trajectory_last_point,
485 const canbus::Chassis::GearPosition& gear, Vec2d* last_pos_vec,
486 double* distance_s, DiscretizedTrajectory* current_trajectory) {
487 current_trajectory->emplace_back();
488 TrajectoryPoint* point = &(current_trajectory->back());
489 point->set_relative_time(trajectory_point.relative_time());
490 point->mutable_path_point()->set_x(trajectory_point.path_point().x());
491 point->mutable_path_point()->set_y(trajectory_point.path_point().y());
492 point->mutable_path_point()->set_theta(trajectory_point.path_point().theta());
493 point->set_v(trajectory_point.v());
494 point->mutable_path_point()->set_s(*distance_s);
495 Vec2d cur_pos_vec(trajectory_point.path_point().x(),
496 trajectory_point.path_point().y());
497 *distance_s += (gear == canbus::Chassis::GEAR_REVERSE ? -1.0 : 1.0) *
498 (cur_pos_vec.DistanceTo(*last_pos_vec));
499 *last_pos_vec = cur_pos_vec;
500 point->mutable_path_point()->set_kappa((is_trajectory_last_point ? -1 : 1) *
501 std::tan(trajectory_point.steer()) /
502 wheel_base_);
503 point->set_a(trajectory_point.a());
504
505 AINFO << "Load trajectory point: " << point->DebugString();
506}
507
508bool OpenSpaceTrajectoryPostProcess::CheckReachTrajectoryEnd(
509 const DiscretizedTrajectory& trajectory,
510 const canbus::Chassis::GearPosition& gear, const size_t trajectories_size,
511 size_t* current_trajectory_point_index) {
512 // Check if have reached endpoint of trajectory
513 const TrajectoryPoint& trajectory_end_point = trajectory.back();
514 const size_t trajectory_size = trajectory.size();
515 const PathPoint& path_end_point = trajectory_end_point.path_point();
516 AINFO << "scale_destination_:" << scale_destination_;
517 double scale = current_trajectory_index_ == frame_->open_space_info().partitioned_trajectories().size() - 1
518 ? scale_destination_
519 : 1.0;
520 AINFO << "Scale: " << scale;
521 if (CheckArrivePoint(
522 gear,
523 path_end_point,
524 scale * lateral_offset_to_midpoint_,
525 scale * longitudinal_offset_to_midpoint_,
526 scale * heading_offset_to_midpoint_)) {
527 if (current_trajectory_index_ + 1 >= trajectories_size) {
528 current_trajectory_index_ = trajectories_size - 1;
529 *current_trajectory_point_index = trajectory_size - 1;
530 } else {
531 current_trajectory_index_ += 1;
532 *current_trajectory_point_index = 0;
533 }
534 stop_check_count_ = 0;
535 AINFO << "Reach the end of a trajectory, switching to next one";
536 return true;
537 } else {
538 return false;
539 }
540}
541
542bool OpenSpaceTrajectoryPostProcess::UseFailSafeSearch(
543 const std::vector<TrajGearPair>& partitioned_trajectories,
544 const std::vector<std::string>& trajectories_encodings,
545 size_t* current_trajectory_index, size_t* current_trajectory_point_index) {
546 AERROR << "Trajectory partition fail, using failsafe search";
547 const size_t trajectories_size = partitioned_trajectories.size();
548 std::priority_queue<std::pair<std::pair<size_t, size_t>, double>,
549 std::vector<std::pair<std::pair<size_t, size_t>, double>>,
550 pair_comp_>
551 failsafe_closest_point_on_trajs;
552 for (size_t i = 0; i < trajectories_size; ++i) {
553 const auto& trajectory = partitioned_trajectories.at(i).first;
554 size_t trajectory_size = trajectory.size();
555 CHECK_GT(trajectory_size, 0U);
556 std::priority_queue<std::pair<size_t, double>,
557 std::vector<std::pair<size_t, double>>, comp_>
558 failsafe_closest_point;
559
560 for (size_t j = 0; j < trajectory_size; ++j) {
561 const TrajectoryPoint& trajectory_point = trajectory.at(j);
562 const PathPoint& path_point = trajectory_point.path_point();
563 const double path_point_x = path_point.x();
564 const double path_point_y = path_point.y();
565 const double path_point_theta = path_point.theta();
566 const Vec2d tracking_vector(path_point_x - ego_x_, path_point_y - ego_y_);
567 const double distance = tracking_vector.Length();
568 if (distance < distance_search_range_) {
569 // get vehicle box and path point box, compute IOU
570 Box2d path_point_box({path_point_x, path_point_y}, path_point_theta,
571 ego_length_, ego_width_);
572 Vec2d shift_vec{shift_distance_ * std::cos(path_point_theta),
573 shift_distance_ * std::sin(path_point_theta)};
574 path_point_box.Shift(shift_vec);
575 double iou_ratio =
576 Polygon2d(ego_box_).ComputeIoU(Polygon2d(path_point_box));
577 failsafe_closest_point.emplace(j, iou_ratio);
578 }
579 }
580 if (!failsafe_closest_point.empty()) {
581 size_t closest_point_index = failsafe_closest_point.top().first;
582 double max_iou_ratio = failsafe_closest_point.top().second;
583 failsafe_closest_point_on_trajs.emplace(
584 std::make_pair(i, closest_point_index), max_iou_ratio);
585 }
586 }
587 if (failsafe_closest_point_on_trajs.empty()) {
588 return false;
589 } else {
590 bool closest_and_not_repeated_traj_found = false;
591 while (!failsafe_closest_point_on_trajs.empty()) {
592 *current_trajectory_index =
593 failsafe_closest_point_on_trajs.top().first.first;
594 *current_trajectory_point_index =
595 failsafe_closest_point_on_trajs.top().first.second;
596 if (CheckTrajTraversed(
597 trajectories_encodings[*current_trajectory_index])) {
598 failsafe_closest_point_on_trajs.pop();
599 } else {
600 closest_and_not_repeated_traj_found = true;
601 UpdateTrajHistory(trajectories_encodings[*current_trajectory_index]);
602 return true;
603 }
604 }
605 if (!closest_and_not_repeated_traj_found) {
606 return false;
607 }
608
609 return true;
610 }
611}
612
613bool OpenSpaceTrajectoryPostProcess::InsertGearShiftTrajectory(
614 const bool flag_change_to_next, const size_t current_trajectory_index,
615 const std::vector<TrajGearPair>& partitioned_trajectories,
616 TrajGearPair* gear_switch_idle_time_trajectory) {
617 const auto* last_frame = injector_->frame_history()->Latest();
618 auto* current_gear_status =
620 if (last_frame) {
621 const auto& last_gear_status =
622 last_frame->open_space_info().gear_switch_states();
623 *(current_gear_status) = last_gear_status;
624 } else {
625 AERROR << "Lost last frame";
626 }
627 const auto& curr_gear =
628 partitioned_trajectories.at(current_trajectory_index).second;
629 if (flag_change_to_next || !current_gear_status->gear_shift_period_finished ||
630 curr_gear != ego_gear_) {
631 current_gear_status->gear_shift_period_finished = false;
632 if (current_gear_status->gear_shift_period_started) {
633 current_gear_status->gear_shift_start_time =
634 Clock::Instance()->NowInSeconds();
635 current_gear_status->gear_shift_position =
636 partitioned_trajectories.at(current_trajectory_index).second;
637 current_gear_status->gear_shift_period_started = false;
638 current_gear_status->gear_shift_period_time = 0.0;
639 }
640 if (current_gear_status->gear_shift_period_time >
641 config_.gear_shift_period_duration() &&
642 current_gear_status->gear_shift_position == ego_gear_) {
643 current_gear_status->gear_shift_period_finished = true;
644 current_gear_status->gear_shift_period_started = true;
645 stop_check_count_ = 0;
646 AINFO << "finished gear shift";
647 } else {
648 double init_kappa = partitioned_trajectories.at(current_trajectory_index)
649 .first[0]
650 .path_point()
651 .kappa();
652 GenerateGearShiftTrajectory(current_gear_status->gear_shift_position,
653 init_kappa, gear_switch_idle_time_trajectory);
654 AINFO << "change gear: " << current_gear_status->gear_shift_position;
655 current_gear_status->gear_shift_period_time =
656 Clock::Instance()->NowInSeconds() -
657 current_gear_status->gear_shift_start_time;
658 return true;
659 }
660 }
661
662 return true;
663}
664
665void OpenSpaceTrajectoryPostProcess::GenerateGearShiftTrajectory(
666 const canbus::Chassis::GearPosition& gear_position, double init_kappa,
667 TrajGearPair* gear_switch_idle_time_trajectory) {
668 gear_switch_idle_time_trajectory->first.clear();
669 const double gear_shift_max_t = config_.gear_shift_max_t();
670 const double gear_shift_unit_t = config_.gear_shift_unit_t();
671 // TrajectoryPoint point;
672 for (double t = 0.0; t < gear_shift_max_t; t += gear_shift_unit_t) {
673 TrajectoryPoint point;
674 point.mutable_path_point()->set_x(frame_->vehicle_state().x());
675 point.mutable_path_point()->set_y(frame_->vehicle_state().y());
676 point.mutable_path_point()->set_theta(frame_->vehicle_state().heading());
677 point.mutable_path_point()->set_s(0.0);
678 point.mutable_path_point()->set_kappa(init_kappa);
679 point.set_relative_time(t);
680 point.set_v(0.0);
681 point.set_a(0.0);
682 gear_switch_idle_time_trajectory->first.emplace_back(point);
683 }
684 ADEBUG << "gear_switch_idle_time_trajectory"
685 << gear_switch_idle_time_trajectory->first.size();
686 gear_switch_idle_time_trajectory->second = gear_position;
687}
688
689void OpenSpaceTrajectoryPostProcess::GenerateStopTrajectory(
690 const canbus::Chassis::GearPosition& gear_position,
691 TrajGearPair* stop_trajectory) {
692 stop_trajectory->first.clear();
693 int alpha = gear_position == canbus::Chassis::GEAR_DRIVE ? 1 : -1;
694 // TrajectoryPoint point;
695 for (double t = 0.0; t < 2.0; t += 0.1) {
696 TrajectoryPoint point;
697 point.mutable_path_point()->set_x(frame_->vehicle_state().x());
698 point.mutable_path_point()->set_y(frame_->vehicle_state().y());
699 point.mutable_path_point()->set_theta(frame_->vehicle_state().heading());
700 point.mutable_path_point()->set_s(0.0);
701 point.mutable_path_point()->set_kappa(0.0);
702 point.set_relative_time(t);
703 point.set_v(0.0);
704 point.set_a(alpha * -0.2);
705 stop_trajectory->first.emplace_back(point);
706 }
707 ADEBUG << "stop_trajectory"
708 << stop_trajectory->first.size();
709 stop_trajectory->second = gear_position;
710}
711
712void OpenSpaceTrajectoryPostProcess::AdjustRelativeTimeAndS(
713 const std::vector<TrajGearPair>& partitioned_trajectories,
714 const size_t current_trajectory_index,
715 const size_t closest_trajectory_point_index,
716 TrajGearPair* current_partitioned_trajectory) {
717 const size_t partitioned_trajectories_size = partitioned_trajectories.size();
718 CHECK_GT(partitioned_trajectories_size, current_trajectory_index);
719
720 // Reassign relative time and relative s to have the closest point as origin
721 // point
722 *(current_partitioned_trajectory) =
723 partitioned_trajectories.at(current_trajectory_index);
724 auto trajectory = &(current_partitioned_trajectory->first);
725
726 for (int i = 0; i < trajectory->size(); i++) {
727 ADEBUG << "trajectory: " << i << " " << std::setprecision(9) <<
728 trajectory->at(i).path_point().x() << " " <<
729 trajectory->at(i).path_point().y();
730 }
731
732 double time_shift =
733 trajectory->at(closest_trajectory_point_index).relative_time();
734 double s_shift =
735 trajectory->at(closest_trajectory_point_index).path_point().s();
736 const size_t trajectory_size = trajectory->size();
737 for (size_t i = 0; i < trajectory_size; ++i) {
738 TrajectoryPoint* trajectory_point = &(trajectory->at(i));
739 trajectory_point->set_relative_time(trajectory_point->relative_time() -
740 time_shift);
741 trajectory_point->mutable_path_point()->set_s(
742 trajectory_point->path_point().s() - s_shift);
743 }
744
745 // Reassign relative t and s on stitched_trajectory_result for accurate next
746 // frame stitching
747 // size_t interpolated_pieces_num =
748 // config_.interpolated_pieces_num();
749 // if (FLAGS_use_iterative_anchoring_smoother) {
750 // interpolated_pieces_num = 1;
751 // }
752 // const size_t unpartitioned_trajectory_size =
753 // unpartitioned_trajectory_result->size();
754 // size_t index_estimate = 0;
755 // for (size_t i = 0; i < current_trajectory_index; ++i) {
756 // index_estimate += partitioned_trajectories.at(i).first.size();
757 // }
758 // index_estimate += closest_trajectory_point_index;
759 // index_estimate /= interpolated_pieces_num;
760 // if (index_estimate >= unpartitioned_trajectory_size) {
761 // index_estimate = unpartitioned_trajectory_size - 1;
762 // }
763 // time_shift =
764 // unpartitioned_trajectory_result->at(index_estimate).relative_time();
765 // s_shift =
766 // unpartitioned_trajectory_result->at(index_estimate).path_point().s();
767 // for (size_t i = 0; i < unpartitioned_trajectory_size; ++i) {
768 // TrajectoryPoint* trajectory_point =
769 // &(unpartitioned_trajectory_result->at(i));
770 // trajectory_point->set_relative_time(trajectory_point->relative_time() -
771 // time_shift);
772 // trajectory_point->mutable_path_point()->set_s(
773 // trajectory_point->path_point().s() - s_shift);
774 // }
775}
776
777bool OpenSpaceTrajectoryPostProcess::CheckArrivePoint(
779 const PathPoint& path_end_point,
780 const double& lateral_offset_to_midpoint,
781 const double& longitudinal_offset_to_midpoint,
782 const double& heading_offset_to_midpoint) {
783 AINFO << "path_end_point " << path_end_point.DebugString();
784 AINFO << "ego_x_: " << ego_x_
785 << ", ego_y_: " << ego_y_
786 << " heading: " << vehicle_moving_direction_;
787 const double path_end_point_x = path_end_point.x();
788 const double path_end_point_y = path_end_point.y();
789 const Vec2d tracking_vector(ego_x_ - path_end_point_x, ego_y_ - path_end_point_y);
790 const double path_end_point_theta = path_end_point.theta();
791 const double included_angle = NormalizeAngle(path_end_point_theta - tracking_vector.Angle());
792 const double distance_to_trajs_end = std::sqrt(
793 (path_end_point_x - ego_x_) * (path_end_point_x - ego_x_)
794 + (path_end_point_y - ego_y_) * (path_end_point_y - ego_y_));
795 const double lateral_offset = std::abs(distance_to_trajs_end * std::sin(included_angle));
796 const double longitudinal_offset = std::abs(distance_to_trajs_end * std::cos(included_angle));
797 const double traj_end_point_moving_direction
798 = ego_gear_ == canbus::Chassis::GEAR_REVERSE ? NormalizeAngle(path_end_point_theta + M_PI) : path_end_point_theta;
799
800 const double heading_search_to_trajs_end
801 = std::abs(NormalizeAngle(traj_end_point_moving_direction - vehicle_moving_direction_));
802
803 // If close to the end point, start on the next trajectory
804 double end_point_iou_ratio = 0.0;
805 if (lateral_offset < lateral_offset_to_midpoint && longitudinal_offset < longitudinal_offset_to_midpoint
806 && heading_search_to_trajs_end < heading_offset_to_midpoint
807 && stop_check_count_ > stop_check_window_) {
808 // get vehicle box and path point box, compare with a threadhold in IOU
809 Box2d path_end_point_box({path_end_point_x, path_end_point_y}, path_end_point_theta, ego_length_, ego_width_);
810 Vec2d shift_vec{shift_distance_ * std::cos(path_end_point_theta), shift_distance_ * std::sin(path_end_point_theta)};
811 path_end_point_box.Shift(shift_vec);
812 end_point_iou_ratio = Polygon2d(ego_box_).ComputeIoU(Polygon2d(path_end_point_box));
813
814 if (end_point_iou_ratio > vehicle_box_iou_threshold_to_midpoint_) {
815 AINFO << "ego reach point";
816 return true;
817 }
818 }
819
820 AINFO << "Vehicle did not reach end of a trajectory with conditions for "
821 "lateral distance_check: "
822 << (lateral_offset < lateral_offset_to_midpoint) << " and actual lateral distance: " << lateral_offset
823 << "; longitudinal distance_check: " << (longitudinal_offset < longitudinal_offset_to_midpoint)
824 << " and actual longitudinal distance: " << longitudinal_offset
825 << "; heading_check: " << (heading_search_to_trajs_end < heading_offset_to_midpoint)
826 << " with actual heading: " << heading_search_to_trajs_end
827 << "; stop_check: " << (stop_check_count_ > stop_check_window_)
828 << " with actual stop count: " << stop_check_count_
829 << "; velocity_check: " << (std::abs(ego_v_) < vehicle_param_.max_abs_speed_when_stopped())
830 << " with actual linear velocity: " << ego_v_
831 << "; iou_check: " << (end_point_iou_ratio > vehicle_box_iou_threshold_to_midpoint_)
832 << " with actual iou: " << end_point_iou_ratio;
833 return false;
834}
835
836// bool OpenSpaceTrajectoryPostProcess::SpeedOptimizer(
837// const std::vector<TrajGearPair>& partitioned_trajectories,
838// const size_t current_trajectory_index,
839// const size_t closest_trajectory_point_index,
840// DiscretizedTrajectory* unpartitioned_trajectory_result,
841// TrajGearPair* current_partitioned_trajectory) {
842// *(current_partitioned_trajectory) =
843// partitioned_trajectories.at(current_trajectory_index);
844// }
845
846} // namespace planning
847} // 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
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
The class of polygon in 2-D.
Definition polygon2d.h:42
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
a singleton clock that can be used to get the current timestamp.
Definition clock.h:39
const OpenSpaceInfo & open_space_info() const
Definition frame.h:167
const LocalView & local_view() const
Definition frame.h:163
const common::VehicleState & vehicle_state() const
Definition frame.cc:83
OpenSpaceInfo * mutable_open_space_info()
Definition frame.h:169
void set_destination_reached(const bool flag)
GearSwitchStates * mutable_gear_switch_states()
const std::vector< TrajGearPair > & partitioned_trajectories() const
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
std::shared_ptr< DependencyInjector > injector_
Definition task.h:59
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
Definition task.cc:40
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
SLPoint InterpolateUsingLinearApproximation(const SLPoint &p0, const SLPoint &p1, const double w)
float tan(Angle16 a)
Definition angle.cc:47
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
Definition math_utils.cc:53
std::pair< DiscretizedTrajectory, canbus::Chassis::GearPosition > TrajGearPair
class register implement
Definition arena_queue.h:37
Definition future.h:29
Define the Polygon2d class.
std::shared_ptr< canbus::Chassis > chassis
Definition local_view.h:42