21#include <unordered_map>
45bool IsLaneSequenceInReferenceLine(
46 const LaneSequence& lane_sequence,
47 const ADCTrajectoryContainer* ego_trajectory_container) {
48 for (
const auto& lane_segment : lane_sequence.lane_segment()) {
49 std::string lane_id = lane_segment.lane_id();
50 if (ego_trajectory_container->IsLaneIdInTargetReferenceLine(lane_id)) {
57int NearestFrontObstacleIdOnLaneSequence(
const LaneSequence& lane_sequence) {
58 int nearest_front_obstacle_id = std::numeric_limits<int>::min();
59 double smallest_relative_s = std::numeric_limits<double>::max();
60 for (
const auto& nearby_obs : lane_sequence.nearby_obstacle()) {
61 if (nearby_obs.s() < 0.0 ||
62 nearby_obs.s() > FLAGS_caution_search_distance_ahead) {
65 if (nearby_obs.s() < smallest_relative_s) {
66 smallest_relative_s = nearby_obs.s();
67 nearest_front_obstacle_id = nearby_obs.id();
70 return nearest_front_obstacle_id;
73int NearestBackwardObstacleIdOnLaneSequence(
const LaneSequence& lane_sequence) {
74 int nearest_backward_obstacle_id = std::numeric_limits<int>::min();
75 double smallest_relative_s = std::numeric_limits<double>::max();
76 for (
const auto& nearby_obs : lane_sequence.nearby_obstacle()) {
77 if (nearby_obs.s() > 0.0 ||
78 nearby_obs.s() < -FLAGS_caution_search_distance_backward) {
81 if (-nearby_obs.s() < smallest_relative_s) {
82 smallest_relative_s = -nearby_obs.s();
83 nearest_backward_obstacle_id = nearby_obs.id();
86 return nearest_backward_obstacle_id;
92 const std::shared_ptr<ContainerManager>& container_manager)
93 : container_manager_(container_manager) {}
96 auto obstacles_container =
99 if (obstacles_container ==
nullptr) {
100 AERROR <<
"Obstacles container pointer is a null pointer.";
105 obstacles_container->GetObstacle(FLAGS_ego_vehicle_id);
106 if (ego_obstacle_ptr ==
nullptr) {
107 AERROR <<
"Ego obstacle nullptr found";
112 double ego_theta = ego_feature.
theta();
113 double ego_x = ego_feature.
position().
x();
114 double ego_y = ego_feature.
position().
y();
115 ADEBUG <<
"Get pose (" << ego_x <<
", " << ego_y <<
", " << ego_theta <<
")";
118 Box2d scan_box({ego_x + FLAGS_scan_length / 2.0 * std::cos(ego_theta),
119 ego_y + FLAGS_scan_length / 2.0 * std::sin(ego_theta)},
120 ego_theta, FLAGS_scan_length, FLAGS_scan_width);
122 const auto& obstacle_ids =
123 obstacles_container->curr_frame_movable_obstacle_ids();
124 for (
const int obstacle_id : obstacle_ids) {
125 Obstacle* obstacle_ptr = obstacles_container->GetObstacle(obstacle_id);
126 if (obstacle_ptr ==
nullptr) {
127 AERROR <<
"Null obstacle pointer found.";
131 AERROR <<
"Obstacle [" << obstacle_ptr->
id() <<
"] has no feature.";
135 double obstacle_x = latest_feature_ptr->
position().
x();
136 double obstacle_y = latest_feature_ptr->
position().
y();
137 Vec2d ego_to_obstacle_vec(obstacle_x - ego_x, obstacle_y - ego_y);
139 double s = ego_to_obstacle_vec.
InnerProd(ego_vec);
141 double pedestrian_like_nearby_lane_radius =
142 FLAGS_pedestrian_nearby_lane_search_radius;
144 obstacle_x, obstacle_y, pedestrian_like_nearby_lane_radius);
147 bool is_in_scan_area = scan_box.IsPointIn({obstacle_x, obstacle_y});
148 bool is_on_lane = obstacle_ptr->
IsOnLane();
149 bool is_pedestrian_like_in_front_near_lanes =
150 s > FLAGS_back_dist_ignore_ped &&
158 bool need_consider = is_in_scan_area || is_on_lane || is_near_junction ||
159 is_pedestrian_like_in_front_near_lanes;
161 if (!need_consider) {
162 latest_feature_ptr->mutable_priority()->set_priority(
165 latest_feature_ptr->mutable_priority()->set_priority(
169 obstacles_container->SetConsideredObstacleIds();
173 auto obstacles_container =
176 if (obstacles_container ==
nullptr) {
177 AERROR <<
"Obstacles container pointer is a null pointer.";
181 obstacles_container->GetObstacle(FLAGS_ego_vehicle_id);
182 if (ego_vehicle ==
nullptr) {
183 AERROR <<
"Ego vehicle not found";
187 AERROR <<
"Ego vehicle has no history";
190 auto storytelling_container =
193 if (storytelling_container->ADCDistanceToJunction() <
194 FLAGS_junction_distance_threshold) {
195 AssignCautionLevelInJunction(*ego_vehicle, obstacles_container,
196 storytelling_container->ADCJunctionId());
198 AssignCautionLevelCruiseKeepLane(*ego_vehicle, obstacles_container);
199 AssignCautionLevelCruiseChangeLane(*ego_vehicle, obstacles_container);
200 AssignCautionLevelByEgoReferenceLine(*ego_vehicle, obstacles_container);
201 AssignCautionLevelPedestrianByEgoReferenceLine(*ego_vehicle,
202 obstacles_container);
203 if (FLAGS_enable_all_pedestrian_caution_in_front) {
204 AssignCautionLevelPedestrianInFront(*ego_vehicle, obstacles_container);
206 if (FLAGS_enable_rank_caution_obstacles) {
207 RankingCautionLevelObstacles(*ego_vehicle, obstacles_container);
211void ObstaclesPrioritizer::AssignCautionLevelInJunction(
213 const std::string& junction_id) {
215 const auto& obstacle_ids =
217 for (
const int obstacle_id : obstacle_ids) {
219 if (obstacle_ptr ==
nullptr) {
220 AERROR <<
"Null obstacle pointer found.";
224 SetCautionIfCloseToEgo(ego_vehicle, FLAGS_caution_distance_threshold,
230void ObstaclesPrioritizer::AssignCautionLevelCruiseKeepLane(
231 const Obstacle& ego_vehicle, ObstaclesContainer* obstacles_container) {
232 const Feature& ego_latest_feature = ego_vehicle.latest_feature();
233 for (
const LaneSequence& lane_sequence :
234 ego_latest_feature.lane().lane_graph().lane_sequence()) {
235 int nearest_front_obstacle_id =
236 NearestFrontObstacleIdOnLaneSequence(lane_sequence);
237 if (nearest_front_obstacle_id < 0) {
240 Obstacle* obstacle_ptr =
241 obstacles_container->GetObstacle(nearest_front_obstacle_id);
242 if (obstacle_ptr ==
nullptr) {
243 AERROR <<
"Obstacle [" << nearest_front_obstacle_id <<
"] Not found";
246 SetCautionIfCloseToEgo(ego_vehicle, FLAGS_caution_distance_threshold,
251void ObstaclesPrioritizer::AssignCautionLevelCruiseChangeLane(
252 const Obstacle& ego_vehicle, ObstaclesContainer* obstacles_container) {
253 ADCTrajectoryContainer* ego_trajectory_container =
254 container_manager_->GetContainer<ADCTrajectoryContainer>(
256 const Feature& ego_latest_feature = ego_vehicle.latest_feature();
257 for (
const LaneSequence& lane_sequence :
258 ego_latest_feature.lane().lane_graph().lane_sequence()) {
259 if (lane_sequence.vehicle_on_lane()) {
260 int nearest_front_obstacle_id =
261 NearestFrontObstacleIdOnLaneSequence(lane_sequence);
262 if (nearest_front_obstacle_id < 0) {
265 Obstacle* obstacle_ptr =
266 obstacles_container->GetObstacle(nearest_front_obstacle_id);
267 if (obstacle_ptr ==
nullptr) {
268 AERROR <<
"Obstacle [" << nearest_front_obstacle_id <<
"] Not found";
271 SetCautionIfCloseToEgo(ego_vehicle, FLAGS_caution_distance_threshold,
273 }
else if (IsLaneSequenceInReferenceLine(lane_sequence,
274 ego_trajectory_container)) {
275 int nearest_front_obstacle_id =
276 NearestFrontObstacleIdOnLaneSequence(lane_sequence);
277 int nearest_backward_obstacle_id =
278 NearestBackwardObstacleIdOnLaneSequence(lane_sequence);
279 if (nearest_front_obstacle_id >= 0) {
280 Obstacle* front_obstacle_ptr =
281 obstacles_container->GetObstacle(nearest_front_obstacle_id);
282 if (front_obstacle_ptr !=
nullptr) {
283 SetCautionIfCloseToEgo(ego_vehicle, FLAGS_caution_distance_threshold,
287 if (nearest_backward_obstacle_id >= 0) {
288 Obstacle* backward_obstacle_ptr =
289 obstacles_container->GetObstacle(nearest_backward_obstacle_id);
290 if (backward_obstacle_ptr !=
nullptr) {
291 SetCautionIfCloseToEgo(ego_vehicle, FLAGS_caution_distance_threshold,
292 backward_obstacle_ptr);
299void ObstaclesPrioritizer::AssignCautionLevelByEgoReferenceLine(
300 const Obstacle& ego_vehicle, ObstaclesContainer* obstacles_container) {
301 ADCTrajectoryContainer* adc_trajectory_container =
302 container_manager_->GetContainer<ADCTrajectoryContainer>(
304 if (adc_trajectory_container ==
nullptr) {
305 AERROR <<
"adc_trajectory_container is nullptr";
308 const std::vector<std::string>& lane_ids =
309 adc_trajectory_container->GetADCTargetLaneIDSequence();
310 if (lane_ids.empty()) {
314 const Feature& ego_feature = ego_vehicle.latest_feature();
315 double ego_x = ego_feature.position().x();
316 double ego_y = ego_feature.position().y();
317 double ego_vehicle_s = std::numeric_limits<double>::max();
318 double ego_vehicle_l = std::numeric_limits<double>::max();
319 double accumulated_s = 0.0;
321 for (
const std::string& lane_id : lane_ids) {
322 std::shared_ptr<const LaneInfo> lane_info_ptr =
324 if (lane_info_ptr ==
nullptr) {
325 AERROR <<
"Null lane info pointer found.";
331 if (std::fabs(l) < std::fabs(ego_vehicle_l)) {
332 ego_vehicle_s = accumulated_s + s;
334 ego_lane_id_ = lane_id;
338 accumulated_s += lane_info_ptr->total_length();
343 for (
const std::string& lane_id : lane_ids) {
344 if (lane_id == ego_lane_id_) {
347 ego_back_lane_id_set_.insert(lane_id);
350 std::unordered_set<std::string> visited_lanes(lane_ids.begin(),
354 for (
const std::string& lane_id : lane_ids) {
355 if (ego_back_lane_id_set_.find(lane_id) != ego_back_lane_id_set_.end()) {
358 std::shared_ptr<const LaneInfo> lane_info_ptr =
360 if (lane_info_ptr ==
nullptr) {
361 AERROR <<
"Null lane info pointer found.";
364 accumulated_s += lane_info_ptr->total_length();
365 if (lane_id != ego_lane_id_) {
366 AssignCautionByMerge(ego_vehicle, lane_info_ptr, &visited_lanes,
367 obstacles_container);
369 AssignCautionByOverlap(ego_vehicle, lane_info_ptr, &visited_lanes,
370 obstacles_container);
371 if (accumulated_s > FLAGS_caution_search_distance_ahead + ego_vehicle_s) {
377void ObstaclesPrioritizer::AssignCautionLevelPedestrianByEgoReferenceLine(
378 const Obstacle& ego_vehicle, ObstaclesContainer* obstacles_container) {
379 ADCTrajectoryContainer* adc_trajectory_container =
380 container_manager_->GetContainer<ADCTrajectoryContainer>(
382 if (adc_trajectory_container ==
nullptr) {
383 AERROR <<
"adc_trajectory_container is nullptr";
386 for (
const int obstacle_id :
387 obstacles_container->curr_frame_movable_obstacle_ids()) {
388 Obstacle* obstacle_ptr = obstacles_container->GetObstacle(obstacle_id);
389 if (obstacle_ptr ==
nullptr) {
390 AERROR <<
"Null obstacle pointer found.";
393 if (obstacle_ptr->history_size() == 0) {
394 AERROR <<
"Obstacle [" << obstacle_ptr->id() <<
"] has no feature.";
397 Feature* latest_feature_ptr = obstacle_ptr->mutable_latest_feature();
404 double start_x = latest_feature_ptr->position().x();
405 double start_y = latest_feature_ptr->position().y();
406 double end_x = start_x + FLAGS_caution_pedestrian_approach_time *
407 latest_feature_ptr->raw_velocity().x();
408 double end_y = start_y + FLAGS_caution_pedestrian_approach_time *
409 latest_feature_ptr->raw_velocity().y();
411 {start_x, start_y}, FLAGS_pedestrian_nearby_lane_search_radius);
412 if (nearby_lane_ids.empty()) {
415 for (
const std::string& lane_id : nearby_lane_ids) {
416 if (!adc_trajectory_container->IsLaneIdInTargetReferenceLine(lane_id)) {
419 std::shared_ptr<const LaneInfo> lane_info_ptr =
421 if (lane_info_ptr ==
nullptr) {
422 AERROR <<
"Null lane info pointer found.";
425 double start_s = 0.0;
426 double start_l = 0.0;
430 &start_s, &start_l) &&
433 if (std::fabs(start_l) < FLAGS_pedestrian_nearby_lane_search_radius ||
434 std::fabs(end_l) < FLAGS_pedestrian_nearby_lane_search_radius ||
435 start_l * end_l < 0.0) {
436 SetCautionIfCloseToEgo(ego_vehicle, FLAGS_caution_distance_threshold,
444void ObstaclesPrioritizer::AssignCautionLevelPedestrianInFront(
445 const Obstacle& ego_vehicle, ObstaclesContainer* obstacles_container) {
446 const Point3D& ego_position = ego_vehicle.latest_feature().position();
447 double ego_heading = ego_vehicle.latest_feature().theta();
448 const auto& obstacle_ids =
449 obstacles_container->curr_frame_movable_obstacle_ids();
450 for (
const int obstacle_id : obstacle_ids) {
451 Obstacle* obstacle_ptr = obstacles_container->GetObstacle(obstacle_id);
455 if (!obstacle_ptr->IsPedestrian() || obstacle_ptr->history_size() == 0) {
458 const Feature& obs_feature = obstacle_ptr->latest_feature();
459 double obs_x = obs_feature.position().x();
460 double obs_y = obs_feature.position().y();
461 double diff_x = obs_x - ego_position.x();
462 double diff_y = obs_y - ego_position.y();
464 std::cos(ego_heading) * diff_x + std::sin(ego_heading) * diff_y;
465 if (inner_prod < 0.0) {
468 SetCautionIfCloseToEgo(ego_vehicle, FLAGS_caution_distance_threshold,
473void ObstaclesPrioritizer::RankingCautionLevelObstacles(
474 const Obstacle& ego_vehicle, ObstaclesContainer* obstacles_container) {
475 const Point3D& ego_position = ego_vehicle.latest_feature().position();
476 const auto& obstacle_ids =
477 obstacles_container->curr_frame_movable_obstacle_ids();
478 std::priority_queue<std::pair<double, Obstacle*>> caution_obstacle_queue;
479 for (
const int obstacle_id : obstacle_ids) {
480 Obstacle* obstacle_ptr = obstacles_container->GetObstacle(obstacle_id);
481 if (obstacle_ptr ==
nullptr) {
482 AERROR <<
"Obstacle [" << obstacle_id <<
"] Not found";
485 if (!obstacle_ptr->IsCaution()) {
488 const Point3D& obstacle_position =
489 obstacle_ptr->latest_feature().position();
490 double distance = std::hypot(obstacle_position.x() - ego_position.x(),
491 obstacle_position.y() - ego_position.y());
492 caution_obstacle_queue.push({distance, obstacle_ptr});
494 while (
static_cast<int>(caution_obstacle_queue.size()) >
495 FLAGS_caution_obs_max_nums) {
496 Obstacle* obstacle_ptr = caution_obstacle_queue.top().second;
497 obstacle_ptr->mutable_latest_feature()->mutable_priority()->set_priority(
499 caution_obstacle_queue.pop();
503void ObstaclesPrioritizer::AssignCautionByMerge(
504 const Obstacle& ego_vehicle, std::shared_ptr<const LaneInfo> lane_info_ptr,
505 std::unordered_set<std::string>*
const visited_lanes,
506 ObstaclesContainer* obstacles_container) {
507 SetCautionBackward(FLAGS_caution_search_distance_backward_for_merge,
508 ego_vehicle, lane_info_ptr, visited_lanes,
509 obstacles_container);
512void ObstaclesPrioritizer::AssignCautionByOverlap(
513 const Obstacle& ego_vehicle, std::shared_ptr<const LaneInfo> lane_info_ptr,
514 std::unordered_set<std::string>*
const visited_lanes,
515 ObstaclesContainer* obstacles_container) {
516 std::string lane_id = lane_info_ptr->id().id();
517 const std::vector<std::shared_ptr<const OverlapInfo>> cross_lanes =
518 lane_info_ptr->cross_lanes();
519 for (
const auto overlap_ptr : cross_lanes) {
520 bool consider_overlap =
true;
521 for (
const auto&
object : overlap_ptr->overlap().object()) {
522 if (
object.
id().
id() == lane_info_ptr->id().id() &&
523 object.lane_overlap_info().end_s() < ego_lane_s_) {
524 consider_overlap =
false;
528 if (!consider_overlap) {
532 for (
const auto&
object : overlap_ptr->overlap().object()) {
533 const auto& object_id =
object.id().id();
534 if (object_id == lane_info_ptr->id().id()) {
537 std::shared_ptr<const LaneInfo> overlap_lane_ptr =
540 double ahead_s = overlap_lane_ptr->total_length() -
541 object.lane_overlap_info().start_s();
543 ahead_s + FLAGS_caution_search_distance_backward_for_overlap,
544 ego_vehicle, overlap_lane_ptr, visited_lanes, obstacles_container);
549void ObstaclesPrioritizer::SetCautionBackward(
550 const double max_distance,
const Obstacle& ego_vehicle,
551 std::shared_ptr<const LaneInfo> start_lane_info_ptr,
552 std::unordered_set<std::string>*
const visited_lanes,
553 ObstaclesContainer* obstacles_container) {
554 std::string start_lane_id = start_lane_info_ptr->id().id();
555 if (ego_back_lane_id_set_.find(start_lane_id) !=
556 ego_back_lane_id_set_.end()) {
559 std::unordered_map<std::string, std::vector<LaneObstacle>> lane_obstacles =
560 obstacles_container->GetClustersPtr()->GetLaneObstacles();
561 std::queue<std::pair<ConstLaneInfoPtr, double>> lane_info_queue;
562 lane_info_queue.emplace(start_lane_info_ptr,
563 start_lane_info_ptr->total_length());
564 while (!lane_info_queue.empty()) {
566 double cumu_distance = lane_info_queue.front().second;
567 lane_info_queue.pop();
568 const std::string& lane_id = curr_lane->id().id();
569 if (visited_lanes->find(lane_id) == visited_lanes->end() &&
570 lane_obstacles.find(lane_id) != lane_obstacles.end() &&
571 !lane_obstacles[lane_id].empty()) {
572 visited_lanes->insert(lane_id);
574 int obstacle_id = lane_obstacles[lane_id].front().obstacle_id();
575 double obstacle_s = lane_obstacles[lane_id].front().lane_s();
576 for (
const LaneObstacle& lane_obstacle : lane_obstacles[lane_id]) {
577 if (lane_obstacle.lane_s() > obstacle_s) {
578 obstacle_id = lane_obstacle.obstacle_id();
579 obstacle_s = lane_obstacle.lane_s();
582 Obstacle* obstacle_ptr = obstacles_container->GetObstacle(obstacle_id);
583 if (obstacle_ptr ==
nullptr) {
584 AERROR <<
"Obstacle [" << obstacle_id <<
"] Not found";
587 SetCautionIfCloseToEgo(ego_vehicle, FLAGS_caution_distance_threshold,
591 if (cumu_distance > max_distance) {
594 for (
const auto& pre_lane_id : curr_lane->lane().predecessor_id()) {
595 if (ego_back_lane_id_set_.find(pre_lane_id.id()) !=
596 ego_back_lane_id_set_.end()) {
600 lane_info_queue.emplace(pre_lane_ptr,
601 cumu_distance + pre_lane_ptr->total_length());
606void ObstaclesPrioritizer::SetCautionIfCloseToEgo(
607 const Obstacle& ego_vehicle,
const double distance_threshold,
608 Obstacle* obstacle_ptr) {
609 const Point3D& obstacle_position = obstacle_ptr->latest_feature().position();
610 const Point3D& ego_position = ego_vehicle.latest_feature().position();
611 double diff_x = obstacle_position.x() - ego_position.x();
612 double diff_y = obstacle_position.y() - ego_position.y();
613 double distance = std::hypot(diff_x, diff_y);
614 if (distance < distance_threshold) {
615 obstacle_ptr->SetCaution();
Rectangular (undirected) bounding box in 2-D.
Implements a class of 2-dimensional vectors.
static Vec2d CreateUnitVec2d(const double angle)
Creates a unit-vector with a given angle to the positive x semi-axis
double InnerProd(const Vec2d &other) const
Returns the inner product between these two Vec2d.
bool IsInJunction(const std::string &junction_id) const
Check if the obstacle is a junction.
bool IsNearJunction()
Check if the obstacle is near a junction.
Feature * mutable_latest_feature()
Get a pointer to the latest feature.
int id() const
Get the obstacle's ID.
size_t history_size() const
Get the number of historical features.
bool IsOnLane() const
Check if the obstacle is on any lane.
const Feature & latest_feature() const
Get the latest feature.
const std::vector< int > & curr_frame_movable_obstacle_ids()
Get movable obstacle IDs in the current frame
Obstacle * GetObstacle(const int id)
Get obstacle pointer
ObstaclesPrioritizer()=delete
void AssignCautionLevel()
static std::vector< std::string > NearbyLaneIds(const Eigen::Vector2d &point, const double radius)
Get nearby lanes by a position.
static bool HasNearbyLane(const double x, const double y, const double radius)
If there is a lane in the range with radius
static std::shared_ptr< const hdmap::LaneInfo > LaneById(const std::string &id)
Get a shared pointer to a lane by lane ID.
static bool GetProjection(const Eigen::Vector2d &position, const std::shared_ptr< const hdmap::LaneInfo > lane_info, double *s, double *l)
Get the frenet coordinates (s, l) on a lane by a position.
std::shared_ptr< const LaneInfo > ConstLaneInfoPtr
optional apollo::perception::PerceptionObstacle::Type type
optional apollo::common::Point3D position