40double Damp(
const double x,
const double sigma) {
41 return 1.0 / (1.0 + std::exp(1.0 / (std::fabs(x) + sigma)));
44bool IsClosed(
const double x0,
const double y0,
const double theta0,
45 const double x1,
const double y1,
const double theta1) {
47 double distance = std::hypot(x0 - x1, y0 - y1);
48 return distance < FLAGS_distance_threshold_to_junction_exit &&
49 angle_diff < FLAGS_angle_threshold_to_junction_exit;
63 ACHECK(!feature_history_.empty());
64 return feature_history_.front().timestamp();
68 ACHECK(i < feature_history_.size());
69 return feature_history_[i];
73 ACHECK(!feature_history_.empty());
74 ACHECK(i < feature_history_.size());
75 return &feature_history_[i];
79 ACHECK(!feature_history_.empty());
80 return feature_history_.front();
84 ACHECK(!feature_history_.empty());
85 return feature_history_.back();
89 ACHECK(!feature_history_.empty());
90 return &(feature_history_.front());
96 if (feature_history_.size() > 0) {
97 return feature_history_.front().is_still();
104 return feature.
speed() < FLAGS_slow_obstacle_speed_threshold;
119 ADEBUG <<
"Obstacle [" << id_ <<
"] is on lane.";
124 if (feature_history_.empty()) {
131 if (feature_history_.empty()) {
137 FLAGS_junction_search_radius);
141 const double timestamp,
142 const int prediction_obstacle_id) {
143 if (!perception_obstacle.has_id() || !perception_obstacle.has_type()) {
144 AERROR <<
"Perception obstacle has incomplete information; "
150 AERROR <<
"Obstacle [" << id_ <<
"] received an older frame ["
152 <<
"] than the most recent timestamp [ " << this->
timestamp()
159 if (!SetId(perception_obstacle, &
feature, prediction_obstacle_id)) {
163 SetType(perception_obstacle, &
feature);
173 if (FLAGS_prediction_offline_mode ==
175 SetSurroundingLaneIds(&
feature, FLAGS_surrounding_lane_search_radius);
178 if (FLAGS_adjust_vehicle_heading_by_lane &&
184 InsertFeatureToHistory(
feature);
187 if (FLAGS_use_navigation_mode) {
188 SetMotionStatusBySpeed();
194 DiscardOutdatedHistory();
199 InsertFeatureToHistory(
feature);
206 if (feature_history_.size() <= 1) {
209 feature_history_[1].clear_predicted_trajectory();
210 Lane* lane = feature_history_[1].mutable_lane();
211 lane->clear_current_lane_feature();
212 lane->clear_nearby_lane_feature();
213 lane->clear_lane_graph();
214 lane->clear_lane_graph_ordered();
218 if (feature_history_.size() > remain_size) {
219 feature_history_.resize(remain_size);
225 if (feature_history_.empty()) {
226 AERROR <<
"Obstacle [" << id_ <<
"] has no history";
229 if (junction_id.empty()) {
232 std::shared_ptr<const JunctionInfo> junction_info_ptr =
234 if (junction_info_ptr ==
nullptr) {
244 if (feature_history_.empty()) {
245 AERROR <<
"Obstacle [" << id_ <<
"] has no history";
249 const std::string& junction_id = junction_analyzer_->
GetJunctionId();
251 ADEBUG <<
"Obstacle [" << id_ <<
"] is not in junction [" << junction_id
258 if (feature_history_.size() == 1) {
259 SetJunctionFeatureWithoutEnterLane(latest_feature_ptr);
265 std::string enter_lane_id =
268 SetJunctionFeatureWithoutEnterLane(latest_feature_ptr);
270 SetJunctionFeatureWithoutEnterLane(latest_feature_ptr);
276 AERROR <<
"No junction feature found";
287 double exit_x = junction_exit.exit_position().x();
288 double exit_y = junction_exit.exit_position().y();
289 double exit_heading = junction_exit.exit_heading();
290 if (IsClosed(position_x, position_y, raw_velocity_heading, exit_x, exit_y,
298void Obstacle::SetJunctionFeatureWithEnterLane(
const std::string& enter_lane_id,
300 feature_ptr->mutable_junction_feature()->CopyFrom(
304void Obstacle::SetJunctionFeatureWithoutEnterLane(Feature*
const feature_ptr) {
306 if (!feature_ptr->has_lane()) {
307 ADEBUG <<
"Obstacle [" << id_ <<
"] has no lane.";
313 std::vector<std::string> start_lane_ids;
314 if (feature_ptr->lane().current_lane_feature_size() > 0) {
315 for (
const auto& lane_feature :
316 feature_ptr->lane().current_lane_feature()) {
317 start_lane_ids.push_back(lane_feature.lane_id());
320 if (feature_ptr->lane().nearby_lane_feature_size() > 0) {
321 for (
const auto& lane_feature : feature_ptr->lane().nearby_lane_feature()) {
322 start_lane_ids.push_back(lane_feature.lane_id());
325 if (start_lane_ids.empty()) {
326 ADEBUG <<
"Obstacle [" << id_ <<
"] has no lane in junction";
330 feature_ptr->mutable_junction_feature()->CopyFrom(
334void Obstacle::SetStatus(
const PerceptionObstacle& perception_obstacle,
335 const double timestamp, Feature* feature) {
337 SetPolygonPoints(perception_obstacle,
feature);
338 SetPosition(perception_obstacle,
feature);
339 SetVelocity(perception_obstacle,
feature);
341 SetTheta(perception_obstacle,
feature);
342 SetLengthWidthHeight(perception_obstacle,
feature);
343 SetIsNearJunction(perception_obstacle,
feature);
346bool Obstacle::SetId(
const PerceptionObstacle& perception_obstacle,
347 Feature* feature,
const int prediction_obstacle_id) {
348 int id = prediction_obstacle_id > 0 ? prediction_obstacle_id
349 : perception_obstacle.id();
352 ADEBUG <<
"Obstacle has id [" << id_ <<
"].";
355 AERROR <<
"Obstacle [" << id_ <<
"] has a mismatched ID [" <<
id
356 <<
"] from perception obstacle.";
364void Obstacle::SetType(
const PerceptionObstacle& perception_obstacle,
366 type_ = perception_obstacle.type();
367 ADEBUG <<
"Obstacle [" << id_ <<
"] has type [" << type_ <<
"].";
371void Obstacle::SetTimestamp(
const PerceptionObstacle& perception_obstacle,
372 const double timestamp, Feature* feature) {
376 ADEBUG <<
"Obstacle [" << id_ <<
"] has timestamp [" << std::fixed
377 << std::setprecision(6) << ts <<
"].";
380void Obstacle::SetPolygonPoints(
const PerceptionObstacle& perception_obstacle,
382 for (
const auto& polygon_point : perception_obstacle.polygon_point()) {
383 *
feature->add_polygon_point() = polygon_point;
384 ADEBUG <<
"Obstacle [" << id_
385 <<
"] has new corner point:" << polygon_point.DebugString();
389void Obstacle::SetPosition(
const PerceptionObstacle& perception_obstacle,
392 ADEBUG <<
"Obstacle [" << id_
393 <<
"] has position:" << perception_obstacle.position().DebugString();
396void Obstacle::SetVelocity(
const PerceptionObstacle& perception_obstacle,
398 double velocity_x = 0.0;
399 double velocity_y = 0.0;
400 double velocity_z = 0.0;
402 if (perception_obstacle.has_velocity()) {
403 if (perception_obstacle.velocity().has_x()) {
404 velocity_x = perception_obstacle.velocity().x();
405 if (std::isnan(velocity_x)) {
406 AERROR <<
"Found nan velocity_x from perception obstacle";
408 }
else if (velocity_x > 50.0 || velocity_x < -50.0) {
409 AERROR <<
"Found unreasonable velocity_x from perception obstacle";
412 if (perception_obstacle.velocity().has_y()) {
413 velocity_y = perception_obstacle.velocity().y();
414 if (std::isnan(velocity_y)) {
415 AERROR <<
"Found nan velocity_y from perception obstacle";
417 }
else if (velocity_y > 50.0 || velocity_y < -50.0) {
418 AERROR <<
"Found unreasonable velocity_y from perception obstacle";
421 if (perception_obstacle.velocity().has_z()) {
422 velocity_z = perception_obstacle.velocity().z();
423 if (std::isnan(velocity_z)) {
424 AERROR <<
"Found nan velocity z from perception obstacle";
426 }
else if (velocity_z > 50.0 || velocity_z < -50.0) {
427 AERROR <<
"Found unreasonable velocity_z from perception obstacle";
432 feature->mutable_raw_velocity()->set_x(velocity_x);
433 feature->mutable_raw_velocity()->set_y(velocity_y);
434 feature->mutable_raw_velocity()->set_z(velocity_z);
436 double speed = std::hypot(velocity_x, velocity_y);
437 double velocity_heading = std::atan2(velocity_y, velocity_x);
438 if (FLAGS_adjust_velocity_by_obstacle_heading || speed < 0.1) {
439 velocity_heading = perception_obstacle.theta();
442 if (!FLAGS_use_navigation_mode && FLAGS_adjust_velocity_by_position_shift &&
448 double prev_obstacle_size = std::fmax(feature_history_.front().length(),
449 feature_history_.front().width());
450 double obstacle_size =
451 std::fmax(perception_obstacle.length(), perception_obstacle.width());
452 double size_diff = std::abs(obstacle_size - prev_obstacle_size);
454 std::fmax(obstacle_size * FLAGS_valid_position_diff_rate_threshold,
455 FLAGS_valid_position_diff_threshold);
456 double size_diff_thred =
457 FLAGS_split_rate * std::min(obstacle_size, prev_obstacle_size);
458 if (std::fabs(diff_x) > shift_thred && std::fabs(diff_y) > shift_thred &&
459 size_diff < size_diff_thred) {
460 double shift_heading = std::atan2(diff_y, diff_x);
463 if (std::fabs(angle_diff) > FLAGS_max_lane_angle_diff) {
464 ADEBUG <<
"Shift velocity heading to be " << shift_heading;
465 velocity_heading = shift_heading;
468 velocity_x = speed * std::cos(velocity_heading);
469 velocity_y = speed * std::sin(velocity_heading);
472 feature->mutable_velocity()->set_x(velocity_x);
473 feature->mutable_velocity()->set_y(velocity_y);
474 feature->mutable_velocity()->set_z(velocity_z);
475 feature->set_velocity_heading(velocity_heading);
478 ADEBUG <<
"Obstacle [" << id_ <<
"] has velocity [" << std::fixed
479 << std::setprecision(6) << velocity_x <<
", " << std::fixed
480 << std::setprecision(6) << velocity_y <<
", " << std::fixed
481 << std::setprecision(6) << velocity_z <<
"]";
482 ADEBUG <<
"Obstacle [" << id_ <<
"] has velocity heading [" << std::fixed
483 << std::setprecision(6) << velocity_heading <<
"] ";
484 ADEBUG <<
"Obstacle [" << id_ <<
"] has speed [" << std::fixed
485 << std::setprecision(6) << speed <<
"].";
488void Obstacle::AdjustHeadingByLane(Feature* feature) {
493 double lane_heading =
feature->
lane().lane_feature().lane_heading();
494 double angle_diff =
feature->
lane().lane_feature().angle_diff();
495 if (std::abs(angle_diff) < FLAGS_max_angle_diff_to_adjust_velocity) {
496 velocity_heading = lane_heading;
498 feature->mutable_velocity()->set_x(speed * std::cos(velocity_heading));
499 feature->mutable_velocity()->set_y(speed * std::sin(velocity_heading));
500 feature->set_velocity_heading(velocity_heading);
504void Obstacle::UpdateVelocity(
const double theta,
double* velocity_x,
505 double* velocity_y,
double* velocity_heading,
507 *speed = std::hypot(*velocity_x, *velocity_y);
509 if (std::fabs(angle_diff) <= FLAGS_max_lane_angle_diff) {
510 *velocity_heading = theta;
511 *velocity_x = *speed * std::cos(*velocity_heading);
512 *velocity_y = *speed * std::sin(*velocity_heading);
516void Obstacle::SetAcceleration(Feature* feature) {
522 if (feature_history_.size() > 0) {
524 double prev_ts = feature_history_.front().timestamp();
527 const Point3D& prev_velocity = feature_history_.front().velocity();
529 if (curr_ts > prev_ts) {
531 double damping_x = Damp(curr_velocity.x(), 0.001);
532 double damping_y = Damp(curr_velocity.y(), 0.001);
533 double damping_z = Damp(curr_velocity.z(), 0.001);
535 acc_x = (curr_velocity.x() - prev_velocity.x()) / (curr_ts - prev_ts);
536 acc_y = (curr_velocity.y() - prev_velocity.y()) / (curr_ts - prev_ts);
537 acc_z = (curr_velocity.z() - prev_velocity.z()) / (curr_ts - prev_ts);
544 FLAGS_vehicle_max_linear_acc);
546 FLAGS_vehicle_max_linear_acc);
548 FLAGS_vehicle_max_linear_acc);
551 acc = acc_x * std::cos(heading) + acc_y * std::sin(heading);
555 feature->mutable_acceleration()->set_x(acc_x);
556 feature->mutable_acceleration()->set_y(acc_y);
557 feature->mutable_acceleration()->set_z(acc_z);
560 ADEBUG <<
"Obstacle [" << id_ <<
"] has acceleration [" << std::fixed
561 << std::setprecision(6) << acc_x <<
", " << std::fixed
562 << std::setprecision(6) << acc_y <<
", " << std::fixed
563 << std::setprecision(6) << acc_z <<
"]";
564 ADEBUG <<
"Obstacle [" << id_ <<
"] has acceleration value [" << std::fixed
565 << std::setprecision(6) << acc <<
"].";
568void Obstacle::SetTheta(
const PerceptionObstacle& perception_obstacle,
571 if (perception_obstacle.has_theta()) {
572 theta = perception_obstacle.theta();
576 ADEBUG <<
"Obstacle [" << id_ <<
"] has theta [" << std::fixed
577 << std::setprecision(6) << theta <<
"].";
580void Obstacle::SetLengthWidthHeight(
581 const PerceptionObstacle& perception_obstacle, Feature* feature) {
586 if (perception_obstacle.has_length()) {
587 length = perception_obstacle.length();
589 if (perception_obstacle.has_width()) {
590 width = perception_obstacle.width();
592 if (perception_obstacle.has_height()) {
593 height = perception_obstacle.height();
600 ADEBUG <<
"Obstacle [" << id_ <<
"] has dimension [" << std::fixed
601 << std::setprecision(6) << length <<
", " << std::fixed
602 << std::setprecision(6) <<
width <<
", " << std::fixed
603 << std::setprecision(6) <<
height <<
"].";
606void Obstacle::SetIsNearJunction(
const PerceptionObstacle& perception_obstacle,
608 if (!perception_obstacle.has_position()) {
611 if (!perception_obstacle.position().has_x() ||
612 !perception_obstacle.position().has_y()) {
615 double x = perception_obstacle.position().x();
616 double y = perception_obstacle.position().y();
617 bool is_near_junction =
619 feature->set_is_near_junction(is_near_junction);
630void Obstacle::SetCurrentLanes(
Feature* feature) {
633 int max_num_lane = FLAGS_max_num_current_lane;
634 double max_angle_diff = FLAGS_max_lane_angle_diff;
635 double lane_search_radius = FLAGS_lane_search_radius;
637 max_num_lane = FLAGS_max_num_current_lane_in_junction;
638 max_angle_diff = FLAGS_max_lane_angle_diff_in_junction;
639 lane_search_radius = FLAGS_lane_search_radius_in_junction;
641 std::vector<std::shared_ptr<const LaneInfo>> current_lanes;
643 true, max_num_lane, max_angle_diff, ¤t_lanes);
644 current_lanes_ = current_lanes;
645 if (current_lanes_.empty()) {
646 ADEBUG <<
"Obstacle [" << id_ <<
"] has no current lanes.";
653 double min_heading_diff = std::numeric_limits<double>::infinity();
655 for (std::shared_ptr<const LaneInfo> current_lane : current_lanes) {
656 if (current_lane ==
nullptr) {
661 std::string lane_id = current_lane->id().id();
669 common::math::Vec2d vec_point(point[0], point[1]);
670 double distance = 0.0;
671 common::PointENU nearest_point =
672 current_lane->GetNearestPoint(vec_point, &distance);
673 double nearest_point_heading =
678 current_lane->GetWidth(s, &left, &right);
679 LaneFeature* lane_feature = lane.add_current_lane_feature();
680 lane_feature->set_lane_turn_type(turn_type);
681 lane_feature->set_lane_id(lane_id);
682 lane_feature->set_lane_s(s);
683 lane_feature->set_lane_l(l);
684 lane_feature->set_angle_diff(angle_diff);
685 lane_feature->set_lane_heading(nearest_point_heading);
686 lane_feature->set_dist_to_left_boundary(left - l);
687 lane_feature->set_dist_to_right_boundary(right + l);
688 lane_feature->set_lane_type(current_lane->lane().type());
689 if (std::fabs(angle_diff) < min_heading_diff) {
690 lane.mutable_lane_feature()->CopyFrom(*lane_feature);
691 min_heading_diff = std::fabs(angle_diff);
694 ADEBUG <<
"Obstacle [" << id_ <<
"] has current lanes ["
695 << lane_feature->ShortDebugString() <<
"].";
698 if (lane.has_lane_feature()) {
699 ADEBUG <<
"Obstacle [" << id_ <<
"] has one current lane ["
700 << lane.lane_feature().ShortDebugString() <<
"].";
703 feature->mutable_lane()->CopyFrom(lane);
706void Obstacle::SetNearbyLanes(Feature* feature) {
708 int max_num_lane = FLAGS_max_num_nearby_lane;
709 double lane_search_radius = FLAGS_lane_search_radius;
711 max_num_lane = FLAGS_max_num_nearby_lane_in_junction;
712 lane_search_radius = FLAGS_lane_search_radius_in_junction;
715 std::vector<std::shared_ptr<const LaneInfo>> nearby_lanes;
717 current_lanes_, max_num_lane,
719 if (nearby_lanes.empty()) {
720 ADEBUG <<
"Obstacle [" << id_ <<
"] has no nearby lanes.";
724 for (std::shared_ptr<const LaneInfo> nearby_lane : nearby_lanes) {
725 if (nearby_lane ==
nullptr) {
731 nearby_lane->lane().has_type() &&
734 ADEBUG <<
"Obstacle [" << id_ <<
"] ignores disqualified lanes.";
741 if (s < 0.0 || s >= nearby_lane->total_length()) {
746 double angle_diff = 0.0;
747 hdmap::MapPathPoint nearest_point;
754 nearby_lane->GetWidth(s, &left, &right);
756 LaneFeature* lane_feature =
757 feature->mutable_lane()->add_nearby_lane_feature();
759 lane_feature->set_lane_turn_type(turn_type);
760 lane_feature->set_lane_id(nearby_lane->id().id());
761 lane_feature->set_lane_s(s);
762 lane_feature->set_lane_l(l);
763 lane_feature->set_angle_diff(angle_diff);
764 lane_feature->set_dist_to_left_boundary(left - l);
765 lane_feature->set_dist_to_right_boundary(right + l);
766 lane_feature->set_lane_type(nearby_lane->lane().type());
767 ADEBUG <<
"Obstacle [" << id_ <<
"] has nearby lanes ["
768 << lane_feature->ShortDebugString() <<
"]";
772void Obstacle::SetSurroundingLaneIds(Feature* feature,
const double radius) {
774 std::vector<std::string> lane_ids =
776 for (
const auto& lane_id : lane_ids) {
777 feature->add_surrounding_lane_id(lane_id);
778 std::shared_ptr<const LaneInfo> lane_info =
780 if (lane_info->IsOnLane(
781 {feature->position().x(), feature->position().y()})) {
782 feature->add_within_lane_id(lane_id);
787bool Obstacle::HasJunctionExitLane(
788 const LaneSequence& lane_sequence,
789 const std::unordered_set<std::string>& exit_lane_id_set) {
791 if (!
feature.has_junction_feature()) {
792 AERROR <<
"Obstacle [" << id_ <<
"] has no junction feature.";
795 for (
const LaneSegment& lane_segment : lane_sequence.lane_segment()) {
796 if (exit_lane_id_set.find(lane_segment.lane_id()) !=
797 exit_lane_id_set.end()) {
807 AERROR <<
"No feature found.";
814 ADEBUG <<
"Not build lane graph for still obstacle";
817 if (
feature->
lane().lane_graph().lane_sequence_size() > 0) {
818 ADEBUG <<
"Not build lane graph for an old obstacle";
822 double t_max = FLAGS_prediction_trajectory_time_length;
823 auto estimated_move_distance = speed * t_max;
825 double road_graph_search_distance = std::fmax(
826 estimated_move_distance, FLAGS_min_prediction_trajectory_spatial_length);
829 std::unordered_set<std::string> exit_lane_id_set;
830 if (is_in_junction) {
832 exit_lane_id_set.insert(exit.exit_lane_id());
840 int curr_lane_count = 0;
841 for (
auto& lane :
feature->
lane().current_lane_feature()) {
842 std::shared_ptr<const LaneInfo> lane_info =
845 lane.lane_s(), road_graph_search_distance,
true, lane_info);
846 if (lane_graph.lane_sequence_size() > 0) {
850 if (is_in_junction && !HasJunctionExitLane(lane_seq, exit_lane_id_set)) {
854 feature->mutable_lane()->mutable_lane_graph()->add_lane_sequence();
855 lane_seq_ptr->CopyFrom(lane_seq);
856 lane_seq_ptr->set_lane_sequence_id(seq_id++);
857 lane_seq_ptr->set_lane_s(lane.lane_s());
858 lane_seq_ptr->set_lane_l(lane.lane_l());
859 lane_seq_ptr->set_vehicle_on_lane(
true);
860 lane_seq_ptr->set_lane_type(lane.lane_type());
861 SetLaneSequenceStopSign(lane_seq_ptr);
862 ADEBUG <<
"Obstacle [" << id_ <<
"] set a lane sequence ["
863 << lane_seq.ShortDebugString() <<
"].";
865 if (curr_lane_count >= FLAGS_max_num_current_lane) {
871 int nearby_lane_count = 0;
872 for (
auto& lane :
feature->
lane().nearby_lane_feature()) {
873 std::shared_ptr<const LaneInfo> lane_info =
876 lane.lane_s(), road_graph_search_distance,
false, lane_info);
877 if (lane_graph.lane_sequence_size() > 0) {
881 if (is_in_junction && !HasJunctionExitLane(lane_seq, exit_lane_id_set)) {
885 feature->mutable_lane()->mutable_lane_graph()->add_lane_sequence();
886 lane_seq_ptr->CopyFrom(lane_seq);
887 lane_seq_ptr->set_lane_sequence_id(seq_id++);
888 lane_seq_ptr->set_lane_s(lane.lane_s());
889 lane_seq_ptr->set_lane_l(lane.lane_l());
890 lane_seq_ptr->set_vehicle_on_lane(
false);
891 lane_seq_ptr->set_lane_type(lane.lane_type());
892 SetLaneSequenceStopSign(lane_seq_ptr);
893 ADEBUG <<
"Obstacle [" << id_ <<
"] set a lane sequence ["
894 << lane_seq.ShortDebugString() <<
"].";
896 if (nearby_lane_count >= FLAGS_max_num_nearby_lane) {
903 SetLaneSequencePath(
feature->mutable_lane()->mutable_lane_graph());
905 ADEBUG <<
"Obstacle [" << id_ <<
"] set lane graph features.";
908void Obstacle::SetLaneSequenceStopSign(
LaneSequence* lane_sequence_ptr) {
913 double accumulate_s = 0.0;
914 for (
const LaneSegment& lane_segment : lane_sequence_ptr->lane_segment()) {
915 const StopSign& stop_sign =
917 if (stop_sign.has_stop_sign_id() &&
918 stop_sign.lane_s() + accumulate_s > lane_sequence_ptr->
lane_s()) {
919 lane_sequence_ptr->mutable_stop_sign()->CopyFrom(stop_sign);
920 lane_sequence_ptr->mutable_stop_sign()->set_lane_sequence_s(
921 stop_sign.lane_s() + accumulate_s);
922 ADEBUG <<
"Set StopSign for LaneSequence ["
926 accumulate_s += lane_segment.total_length();
930void Obstacle::GetNeighborLaneSegments(
931 std::shared_ptr<const LaneInfo> center_lane_info,
bool is_left,
932 int recursion_depth, std::list<std::string>*
const lane_ids_ordered,
933 std::unordered_set<std::string>*
const existing_lane_ids) {
935 if (recursion_depth <= 0) {
939 std::vector<std::string> curr_left_lane_ids;
940 for (
const auto& left_lane_id :
941 center_lane_info->lane().left_neighbor_forward_lane_id()) {
942 if (left_lane_id.has_id()) {
943 const std::string& lane_id = left_lane_id.id();
945 if (existing_lane_ids->count(lane_id) == 0) {
946 existing_lane_ids->insert(lane_id);
947 lane_ids_ordered->push_front(lane_id);
948 curr_left_lane_ids.push_back(lane_id);
953 for (
const std::string& lane_id : curr_left_lane_ids) {
955 recursion_depth - 1, lane_ids_ordered,
959 std::vector<std::string> curr_right_lane_ids;
960 for (
const auto& right_lane_id :
961 center_lane_info->lane().right_neighbor_forward_lane_id()) {
962 if (right_lane_id.has_id()) {
963 const std::string& lane_id = right_lane_id.id();
965 if (existing_lane_ids->count(lane_id) == 0) {
966 existing_lane_ids->insert(lane_id);
967 lane_ids_ordered->push_back(lane_id);
968 curr_right_lane_ids.push_back(lane_id);
973 for (
const std::string& lane_id : curr_right_lane_ids) {
975 recursion_depth - 1, lane_ids_ordered,
984 AERROR <<
"No feature found.";
991 ADEBUG <<
"Don't build lane graph for non-moving obstacle.";
994 if (
feature->
lane().lane_graph_ordered().lane_sequence_size() > 0) {
995 ADEBUG <<
"Don't build lane graph for an old obstacle.";
999 double road_graph_search_distance = 50.0 * 0.95;
1013 std::unordered_set<std::string> exit_lane_id_set;
1014 if (is_in_junction) {
1016 exit_lane_id_set.insert(exit.exit_lane_id());
1020 std::shared_ptr<const LaneInfo> center_lane_info =
1022 std::list<std::string> lane_ids_ordered_list;
1023 std::unordered_set<std::string> existing_lane_ids;
1024 GetNeighborLaneSegments(center_lane_info,
true, 2, &lane_ids_ordered_list,
1025 &existing_lane_ids);
1026 lane_ids_ordered_list.push_back(
feature->
lane().lane_feature().lane_id());
1027 existing_lane_ids.insert(
feature->
lane().lane_feature().lane_id());
1028 GetNeighborLaneSegments(center_lane_info,
false, 2, &lane_ids_ordered_list,
1029 &existing_lane_ids);
1031 const std::vector<std::string> lane_ids_ordered(lane_ids_ordered_list.begin(),
1032 lane_ids_ordered_list.end());
1037 for (
const std::string& lane_id : lane_ids_ordered) {
1039 bool vehicle_is_on_lane = (lane_id == center_lane_info->lane().id().id());
1040 std::shared_ptr<const LaneInfo> curr_lane_info =
1043 feature->
lane().lane_feature().lane_s(), road_graph_search_distance,
1044 true, curr_lane_info);
1046 for (
const auto& lane_seq : local_lane_graph.
lane_sequence()) {
1047 if (is_in_junction && !HasJunctionExitLane(lane_seq, exit_lane_id_set)) {
1051 ->mutable_lane_graph_ordered()
1052 ->add_lane_sequence();
1053 lane_seq_ptr->CopyFrom(lane_seq);
1054 lane_seq_ptr->set_lane_sequence_id(seq_id++);
1055 lane_seq_ptr->set_lane_s(
feature->
lane().lane_feature().lane_s());
1056 lane_seq_ptr->set_lane_l(
feature->
lane().lane_feature().lane_l());
1057 lane_seq_ptr->set_vehicle_on_lane(vehicle_is_on_lane);
1058 ADEBUG <<
"Obstacle [" << id_ <<
"] set a lane sequence ["
1059 << lane_seq.ShortDebugString() <<
"].";
1065 SetLanePoints(
feature, 0.5, 100,
true,
1066 feature->mutable_lane()->mutable_lane_graph_ordered());
1067 SetLaneSequencePath(
feature->mutable_lane()->mutable_lane_graph_ordered());
1069 ADEBUG <<
"Obstacle [" << id_ <<
"] set lane graph features.";
1074void Obstacle::SetLanePoints(
Feature* feature) {
1076 SetLanePoints(
feature, FLAGS_target_lane_gap, FLAGS_max_num_lane_point,
false,
1081void Obstacle::SetLanePoints(
const Feature* feature,
1082 const double lane_point_spacing,
1083 const uint64_t max_num_lane_point,
1084 const bool is_bidirection,
1085 LaneGraph*
const lane_graph) {
1086 ADEBUG <<
"Spacing = " << lane_point_spacing;
1089 AERROR <<
"Null feature or no velocity heading.";
1095 Eigen::Vector2d position(x, y);
1098 for (
int i = 0; i < lane_graph->lane_sequence_size(); ++i) {
1099 LaneSequence* lane_sequence = lane_graph->mutable_lane_sequence(i);
1100 if (lane_sequence->lane_segment().empty()) {
1107 if (is_bidirection) {
1109 double lane_seg_s = lane_sequence->lane_segment(lane_index).start_s();
1110 while (lane_index < lane_sequence->lane_segment_size()) {
1112 LaneSegment* lane_segment =
1113 lane_sequence->mutable_lane_segment(lane_index);
1116 if (lane_index == lane_sequence->adc_lane_segment_idx() &&
1117 lane_seg_s > lane_segment->adc_s()) {
1118 lane_segment->set_adc_lane_point_idx(lane_segment->lane_point_size());
1122 if (lane_seg_s > lane_segment->end_s()) {
1125 ADEBUG <<
"Move on to the next lane-segment.";
1126 lane_seg_s = lane_seg_s - lane_segment->end_s();
1131 std::string lane_id = lane_segment->lane_id();
1132 lane_segment->set_lane_turn_type(
1134 ADEBUG <<
"Currently on " << lane_id;
1136 if (lane_info ==
nullptr) {
1140 ADEBUG <<
"Lane-segment s = " << lane_seg_s;
1141 Eigen::Vector2d lane_point_pos =
1143 double lane_point_heading =
1145 double lane_point_width =
1147 double lane_point_angle_diff =
1150 ADEBUG << lane_point_pos[0] <<
" " << lane_point_pos[1];
1151 LanePoint lane_point;
1152 lane_point.mutable_position()->set_x(lane_point_pos[0]);
1153 lane_point.mutable_position()->set_y(lane_point_pos[1]);
1154 lane_point.set_heading(lane_point_heading);
1155 lane_point.set_width(lane_point_width);
1156 lane_point.set_angle_diff(lane_point_angle_diff);
1158 lane_segment->add_lane_point()->CopyFrom(lane_point);
1159 lane_seg_s += lane_point_spacing;
1165 int lane_index = lane_sequence->adc_lane_segment_idx();
1166 double total_s = 0.0;
1167 double lane_seg_s = lane_sequence->lane_segment(lane_index).adc_s();
1168 if (!is_bidirection) {
1170 lane_seg_s = lane_sequence->lane_segment(0).start_s();
1172 std::size_t count_point = 0;
1173 while (lane_index < lane_sequence->lane_segment_size() &&
1174 count_point < max_num_lane_point) {
1176 LaneSegment* lane_segment =
1177 lane_sequence->mutable_lane_segment(lane_index);
1179 if (lane_seg_s > lane_segment->end_s()) {
1182 ADEBUG <<
"Move on to the next lane-segment.";
1183 lane_seg_s = lane_seg_s - lane_segment->end_s();
1188 std::string lane_id = lane_segment->lane_id();
1190 ADEBUG <<
"Currently on " << lane_id;
1192 if (lane_info ==
nullptr) {
1196 ADEBUG <<
"Lane-segment s = " << lane_seg_s;
1197 Eigen::Vector2d lane_point_pos =
1199 double lane_point_heading =
1201 double lane_point_width =
1203 double lane_point_angle_diff =
1206 ADEBUG << lane_point_pos[0] <<
" " << lane_point_pos[1];
1207 LanePoint lane_point;
1209 lane_point.mutable_position()->set_x(lane_point_pos[0]);
1210 lane_point.mutable_position()->set_y(lane_point_pos[1]);
1211 lane_point.set_heading(lane_point_heading);
1212 lane_point.set_width(lane_point_width);
1213 lane_point.set_angle_diff(lane_point_angle_diff);
1215 double lane_l =
feature->
lane().lane_feature().lane_l();
1216 lane_point.set_relative_s(total_s);
1217 lane_point.set_relative_l(0.0 - lane_l);
1219 lane_segment->add_lane_point()->CopyFrom(lane_point);
1221 total_s += lane_point_spacing;
1222 lane_seg_s += lane_point_spacing;
1226 ADEBUG <<
"Obstacle [" << id_ <<
"] has lane segments and points.";
1229void Obstacle::SetLaneSequencePath(LaneGraph*
const lane_graph) {
1231 for (
int i = 0; i < lane_graph->lane_sequence_size(); ++i) {
1232 LaneSequence* lane_sequence = lane_graph->mutable_lane_sequence(i);
1233 double lane_segment_s = 0.0;
1235 for (
const LaneSegment& lane_segment : lane_sequence->lane_segment()) {
1237 for (
const LanePoint& lane_point : lane_segment.lane_point()) {
1238 PathPoint* path_point = lane_sequence->add_path_point();
1239 path_point->set_s(lane_point.relative_s());
1240 path_point->set_theta(lane_point.heading());
1242 lane_segment_s += lane_segment.total_length();
1245 int num_path_point = lane_sequence->path_point_size();
1246 if (num_path_point <= 0) {
1250 int segment_index = 0;
1251 int point_index = 0;
1252 for (
int j = 0; j + 1 < num_path_point; ++j) {
1253 while (segment_index < lane_sequence->lane_segment_size() &&
1255 lane_sequence->lane_segment(segment_index).lane_point_size()) {
1259 PathPoint* first_point = lane_sequence->mutable_path_point(j);
1260 PathPoint* second_point = lane_sequence->mutable_path_point(j + 1);
1262 second_point->theta(), first_point->theta());
1263 double delta_s = second_point->s() - first_point->s();
1264 double kappa = std::abs(delta_theta / (delta_s + FLAGS_double_precision));
1265 lane_sequence->mutable_path_point(j)->set_kappa(kappa);
1266 if (segment_index < lane_sequence->lane_segment_size() &&
1268 lane_sequence->lane_segment(segment_index).lane_point_size()) {
1269 lane_sequence->mutable_lane_segment(segment_index)
1270 ->mutable_lane_point(point_index)
1275 lane_sequence->mutable_path_point(num_path_point - 1)->set_kappa(0.0);
1283 LaneGraph* lane_graph = feature_ptr->mutable_lane()->mutable_lane_graph();
1284 for (
int i = 0; i < lane_graph->lane_sequence_size(); ++i) {
1285 LaneSequence* lane_sequence = lane_graph->mutable_lane_sequence(i);
1286 if (lane_sequence->lane_segment_size() == 0) {
1287 AERROR <<
"Empty lane sequence found.";
1290 double obstacle_s = lane_sequence->
lane_s();
1291 double obstacle_l = lane_sequence->
lane_l();
1294 obstacle_l, &forward_obstacle)) {
1295 lane_sequence->add_nearby_obstacle()->CopyFrom(forward_obstacle);
1299 obstacle_l, &backward_obstacle)) {
1300 lane_sequence->add_nearby_obstacle()->CopyFrom(backward_obstacle);
1305void Obstacle::SetMotionStatus() {
1306 int history_size =
static_cast<int>(feature_history_.size());
1308 AERROR <<
"Zero history found";
1311 double pos_std = FLAGS_still_obstacle_position_std;
1312 double speed_threshold = FLAGS_still_obstacle_speed_threshold;
1315 speed_threshold = FLAGS_still_pedestrian_speed_threshold;
1316 pos_std = FLAGS_still_pedestrian_position_std;
1319 speed_threshold = FLAGS_still_unknown_speed_threshold;
1320 pos_std = FLAGS_still_unknown_position_std;
1322 double speed = feature_history_.front().speed();
1325 if (speed < speed_threshold) {
1326 ADEBUG <<
"Obstacle [" << id_ <<
"] has a small speed [" << speed
1327 <<
"] and is considered stationary in the first frame.";
1328 feature_history_.front().set_is_still(
true);
1330 feature_history_.front().set_is_still(
false);
1335 double start_x = 0.0;
1336 double start_y = 0.0;
1337 double avg_drift_x = 0.0;
1338 double avg_drift_y = 0.0;
1339 int len = std::min(
history_size, FLAGS_max_still_obstacle_history_length);
1340 len = std::max(len, FLAGS_min_still_obstacle_history_length);
1343 auto feature_riter = feature_history_.rbegin();
1344 start_x = feature_riter->position().x();
1345 start_y = feature_riter->position().y();
1347 while (feature_riter != feature_history_.rend()) {
1348 avg_drift_x += (feature_riter->position().x() - start_x) / (len - 1);
1349 avg_drift_y += (feature_riter->position().y() - start_y) / (len - 1);
1353 double delta_ts = feature_history_.front().timestamp() -
1354 feature_history_.back().timestamp();
1355 double speed_sensibility = std::sqrt(2 *
history_size) * 4 * pos_std /
1357 if (speed < speed_threshold) {
1358 ADEBUG <<
"Obstacle [" << id_ <<
"] has a small speed [" << speed
1359 <<
"] and is considered stationary.";
1360 feature_history_.front().set_is_still(
true);
1361 }
else if (speed_sensibility < speed_threshold) {
1362 ADEBUG <<
"Obstacle [" << id_ <<
"]"
1363 <<
"] considered moving [sensibility = " << speed_sensibility <<
"]";
1364 feature_history_.front().set_is_still(
false);
1366 double distance = std::hypot(avg_drift_x, avg_drift_y);
1367 double distance_std = std::sqrt(2.0 / len) * pos_std;
1368 if (distance > 2.0 * distance_std) {
1369 ADEBUG <<
"Obstacle [" << id_ <<
"] is moving.";
1370 feature_history_.front().set_is_still(
false);
1372 ADEBUG <<
"Obstacle [" << id_ <<
"] is stationary.";
1373 feature_history_.front().set_is_still(
true);
1378void Obstacle::SetMotionStatusBySpeed() {
1381 ADEBUG <<
"Obstacle [" << id_ <<
"] has no history and "
1382 <<
"is considered moving.";
1384 feature_history_.front().set_is_still(
false);
1389 double speed_threshold = FLAGS_still_obstacle_speed_threshold;
1390 double speed = feature_history_.front().speed();
1392 if (FLAGS_use_navigation_mode) {
1393 if (speed < speed_threshold) {
1394 feature_history_.front().set_is_still(
true);
1396 feature_history_.front().set_is_still(
false);
1401void Obstacle::InsertFeatureToHistory(
const Feature& feature) {
1402 feature_history_.emplace_front(
feature);
1403 ADEBUG <<
"Obstacle [" << id_ <<
"] inserted a frame into the history.";
1409 std::unique_ptr<Obstacle> ptr_obstacle(
new Obstacle());
1410 ptr_obstacle->SetClusters(clusters_ptr);
1411 if (!ptr_obstacle->Insert(perception_obstacle,
timestamp, prediction_id)) {
1414 return ptr_obstacle;
1419 std::unique_ptr<Obstacle> ptr_obstacle(
new Obstacle());
1420 ptr_obstacle->SetClusters(clusters_ptr);
1421 ptr_obstacle->InsertFeatureToHistory(
feature);
1422 return ptr_obstacle;
1426 if (feature_history_.empty()) {
1429 auto last_timestamp_received = feature_history_.front().timestamp();
1430 return timestamp <= last_timestamp_received;
1433void Obstacle::DiscardOutdatedHistory() {
1434 auto num_of_frames = feature_history_.size();
1435 const double latest_ts = feature_history_.front().timestamp();
1436 while (latest_ts - feature_history_.back().timestamp() >=
1437 FLAGS_max_history_time) {
1438 feature_history_.pop_back();
1440 auto num_of_discarded_frames = num_of_frames - feature_history_.size();
1441 if (num_of_discarded_frames > 0) {
1442 ADEBUG <<
"Obstacle [" << id_ <<
"] discards " << num_of_discarded_frames
1443 <<
" historical features";
1448 CHECK_GT(feature_history_.size(), 0U);
1454 if (feature_history_.empty()) {
1462 CHECK_GT(feature_history_.size(), 0U);
1464 feature->mutable_interactive_tag()
1469 CHECK_GT(feature_history_.size(), 0U);
1471 feature->mutable_interactive_tag()
1476 if (feature_history_.empty()) {
1486 obstacle_conf_.set_evaluator_type(evaluator_type);
1491 obstacle_conf_.set_predictor_type(predictor_type);
1497 return prediction_obstacle;
1501 clusters_ptr_ = clusters_ptr;
const std::string & GetJunctionId()
Get junction ID
const JunctionFeature & GetJunctionFeature(const std::string &start_lane_id)
Get junction feature starting from start_lane_id
LaneGraph GetLaneGraph(const double start_s, const double length, const bool consider_lane_split, std::shared_ptr< const apollo::hdmap::LaneInfo > lane_info_ptr)
Obtain a lane graph given a lane info and s
bool ForwardNearbyObstacle(const LaneSequence &lane_sequence, const double s, LaneObstacle *const lane_obstacle)
Get the nearest obstacle on lane sequence at s
void AddObstacle(const int obstacle_id, const std::string &lane_id, const double lane_s, const double lane_l)
Add an obstacle into clusters
StopSign QueryStopSignByLaneId(const std::string &lane_id)
Query stop sign by lane ID
LaneGraph GetLaneGraphWithoutMemorizing(const double start_s, const double length, const bool is_on_lane, std::shared_ptr< const apollo::hdmap::LaneInfo > lane_info_ptr)
Obtain a lane graph given a lane info and s, but don't memorize it.
bool BackwardNearbyObstacle(const LaneSequence &lane_sequence, const int obstacle_id, const double obstacle_s, const double obstacle_l, NearbyObstacle *const nearby_obstacle_ptr)
Get the backward nearest obstacle on lane sequence at s
bool IsInJunction(const std::string &junction_id) const
Check if the obstacle is a junction.
double timestamp() const
Get the obstacle's timestamp.
bool HasJunctionFeatureWithExits() const
Check if the obstacle has junction feature.
bool ReceivedOlderMessage(const double timestamp) const
bool IsNearJunction()
Check if the obstacle is near a junction.
void SetNearbyObstacles()
Set nearby obstacles.
Feature * mutable_feature(const size_t i)
Get a pointer to the ith feature from latest to earliest.
Feature * mutable_latest_feature()
Get a pointer to the latest feature.
void BuildLaneGraphFromLeftToRight()
Build obstacle's lane graph with lanes being ordered.
void BuildLaneGraph()
Build obstacle's lane graph
void ClearOldInformation()
bool IsPedestrian() const
perception::PerceptionObstacle::Type type() const
Get the type of perception obstacle's type.
bool IsCloseToJunctionExit() const
Check if the obstacle is close to a junction exit.
void TrimHistory(const size_t remain_size)
bool IsStill()
Check if the obstacle is still.
bool InsertFeature(const Feature &feature)
Insert a feature proto message.
void SetNonInteractiveTag()
Set the obstacle as noninteractive obstacle.
void SetInteractiveTag()
Set the obstacle as interactive obstacle.
int id() const
Get the obstacle's ID.
bool ToIgnore()
Check if the obstacle can be ignored.
size_t history_size() const
Get the number of historical features.
const Feature & feature(const size_t i) const
Get the ith feature from latest to earliest.
bool IsInteractiveObstacle() const
PredictionObstacle GeneratePredictionObstacle()
bool Insert(const perception::PerceptionObstacle &perception_obstacle, const double timestamp, const int prediction_id)
Insert a perception obstacle with its timestamp.
void BuildJunctionFeature()
Build junction feature.
void SetEvaluatorType(const ObstacleConf::EvaluatorType &evaluator_type)
bool IsOnLane() const
Check if the obstacle is on any lane.
void SetPredictorType(const ObstacleConf::PredictorType &predictor_type)
const Feature & earliest_feature() const
Get the earliest feature.
bool IsSlow()
Check if the obstacle is slow.
void SetCaution()
Set the obstacle as caution level
static std::unique_ptr< Obstacle > Create(const perception::PerceptionObstacle &perception_obstacle, const double timestamp, const int prediction_id, ObstacleClusters *clusters_ptr)
Constructor
const Feature & latest_feature() const
Get the latest feature.
static const int kDumpDataForLearning
static bool InJunction(const Eigen::Vector2d &point, const double radius)
Check if the obstacle is in a junction.
static bool IsPointInJunction(const double x, const double y, const std::shared_ptr< const hdmap::JunctionInfo > junction_info_ptr)
Check if a point with coord x and y is in the junction.
static void OnLane(const std::vector< std::shared_ptr< const hdmap::LaneInfo > > &prev_lanes, const Eigen::Vector2d &point, const double heading, const double radius, const bool on_lane, const int max_num_lane, const double max_lane_angle_diff, std::vector< std::shared_ptr< const hdmap::LaneInfo > > *lanes)
Get the connected lanes from some specified lanes.
static std::shared_ptr< const hdmap::JunctionInfo > JunctionById(const std::string &id)
Get a shared pointer to a junction by junction ID.
static std::vector< std::string > NearbyLaneIds(const Eigen::Vector2d &point, const double radius)
Get nearby lanes by a position.
static double LaneTotalWidth(const std::shared_ptr< const hdmap::LaneInfo > lane_info, const double s)
Get the width on a specified distance on a lane.
static double HeadingOnLane(const std::shared_ptr< const hdmap::LaneInfo > lane_info, const double s)
Get the heading of a point on a specific distance along a lane.
static bool ProjectionFromLane(std::shared_ptr< const hdmap::LaneInfo > lane_info, const double s, hdmap::MapPathPoint *path_point)
Get the nearest path point to a longitudinal coordinate on a lane.
static Eigen::Vector2d PositionOnLane(const std::shared_ptr< const hdmap::LaneInfo > lane_info, const double s)
Get the position of a point on a specific distance along a lane.
static int LaneTurnType(const std::string &lane_id)
Get lane turn type.
static bool NearJunction(const Eigen::Vector2d &point, const double radius)
Check if there are any junctions within the range centered at a certain point with a radius.
static void NearbyLanesByCurrentLanes(const Eigen::Vector2d &point, const double heading, const double radius, const std::vector< std::shared_ptr< const hdmap::LaneInfo > > &lanes, const int max_num_lane, std::vector< std::shared_ptr< const hdmap::LaneInfo > > *nearby_lanes)
Get nearby lanes by a position and current lanes.
static std::shared_ptr< const hdmap::LaneInfo > LaneById(const std::string &id)
Get a shared pointer to a lane by lane ID.
static double PathHeading(std::shared_ptr< const hdmap::LaneInfo > lane_info, const common::PointENU &point)
Get the lane heading on a point.
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.
T Clamp(const T value, T bound1, T bound2)
Clamp a value between two bounds.
double AngleDiff(const double from, const double to)
Calculate the difference between angle from and to
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
uint32_t height
Height of point cloud
uint32_t width
Width of point cloud
Holds all global constants for the prediction module.
optional ObstacleInteractiveTag interactive_tag
optional apollo::perception::PerceptionObstacle::Type type
optional ObstaclePriority priority
optional double timestamp
optional apollo::common::Point3D velocity
optional double velocity_heading
optional JunctionFeature junction_feature
optional apollo::common::Point3D raw_velocity
optional apollo::common::Point3D position
optional LaneFeature enter_lane
repeated JunctionExit junction_exit
repeated LaneSequence lane_sequence
optional int32 lane_sequence_id
repeated LaneSegment lane_segment
optional InteractiveTag interactive_tag
optional Priority priority