Apollo 10.0
自动驾驶开放平台
obstacle.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <algorithm>
20#include <iomanip>
21#include <limits>
22
29
30namespace apollo {
31namespace prediction {
32namespace {
33
39
40double Damp(const double x, const double sigma) {
41 return 1.0 / (1.0 + std::exp(1.0 / (std::fabs(x) + sigma)));
42}
43
44bool IsClosed(const double x0, const double y0, const double theta0,
45 const double x1, const double y1, const double theta1) {
46 double angle_diff = std::fabs(common::math::AngleDiff(theta0, 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;
50}
51
52} // namespace
53
55
57 return type_ == PerceptionObstacle::PEDESTRIAN;
58}
59
60int Obstacle::id() const { return id_; }
61
62double Obstacle::timestamp() const {
63 ACHECK(!feature_history_.empty());
64 return feature_history_.front().timestamp();
65}
66
67const Feature& Obstacle::feature(const size_t i) const {
68 ACHECK(i < feature_history_.size());
69 return feature_history_[i];
70}
71
73 ACHECK(!feature_history_.empty());
74 ACHECK(i < feature_history_.size());
75 return &feature_history_[i];
76}
77
79 ACHECK(!feature_history_.empty());
80 return feature_history_.front();
81}
82
84 ACHECK(!feature_history_.empty());
85 return feature_history_.back();
86}
87
89 ACHECK(!feature_history_.empty());
90 return &(feature_history_.front());
91}
92
93size_t Obstacle::history_size() const { return feature_history_.size(); }
94
96 if (feature_history_.size() > 0) {
97 return feature_history_.front().is_still();
98 }
99 return true;
100}
101
103 const Feature& feature = latest_feature();
104 return feature.speed() < FLAGS_slow_obstacle_speed_threshold;
105}
106
107bool Obstacle::IsOnLane() const {
108 if (feature_history_.empty() || !latest_feature().has_lane() ||
109 latest_feature().lane().current_lane_feature().empty()) {
110 return false;
111 }
112 for (const auto& curr_lane : latest_feature().lane().current_lane_feature()) {
113 if (curr_lane.lane_type() != hdmap::Lane::CITY_DRIVING &&
114 curr_lane.lane_type() != hdmap::Lane::BIKING) {
115 return false;
116 }
117 }
118
119 ADEBUG << "Obstacle [" << id_ << "] is on lane.";
120 return true;
121}
122
124 if (feature_history_.empty()) {
125 return true;
126 }
128}
129
131 if (feature_history_.empty()) {
132 return false;
133 }
134 double pos_x = latest_feature().position().x();
135 double pos_y = latest_feature().position().y();
136 return PredictionMap::NearJunction({pos_x, pos_y},
137 FLAGS_junction_search_radius);
138}
139
140bool Obstacle::Insert(const PerceptionObstacle& perception_obstacle,
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; "
145 "skip insertion";
146 return false;
147 }
148
150 AERROR << "Obstacle [" << id_ << "] received an older frame ["
151 << std::setprecision(20) << timestamp
152 << "] than the most recent timestamp [ " << this->timestamp()
153 << "].";
154 return false;
155 }
156
157 // Set ID, Type, and Status of the feature.
159 if (!SetId(perception_obstacle, &feature, prediction_obstacle_id)) {
160 return false;
161 }
162
163 SetType(perception_obstacle, &feature);
164
165 SetStatus(perception_obstacle, timestamp, &feature);
166
167 // Set obstacle lane features
168 if (type_ != PerceptionObstacle::PEDESTRIAN) {
169 SetCurrentLanes(&feature);
170 SetNearbyLanes(&feature);
171 }
172
173 if (FLAGS_prediction_offline_mode ==
175 SetSurroundingLaneIds(&feature, FLAGS_surrounding_lane_search_radius);
176 }
177
178 if (FLAGS_adjust_vehicle_heading_by_lane &&
180 AdjustHeadingByLane(&feature);
181 }
182
183 // Insert obstacle feature to history
184 InsertFeatureToHistory(feature);
185
186 // Set obstacle motion status
187 if (FLAGS_use_navigation_mode) {
188 SetMotionStatusBySpeed();
189 } else {
190 SetMotionStatus();
191 }
192
193 // Trim historical features
194 DiscardOutdatedHistory();
195 return true;
196}
197
198bool Obstacle::InsertFeature(const Feature& feature) {
199 InsertFeatureToHistory(feature);
200 type_ = feature.type();
201 id_ = feature.id();
202 return true;
203}
204
206 if (feature_history_.size() <= 1) {
207 return;
208 }
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();
215}
216
217void Obstacle::TrimHistory(const size_t remain_size) {
218 if (feature_history_.size() > remain_size) {
219 feature_history_.resize(remain_size);
220 }
221}
222
223bool Obstacle::IsInJunction(const std::string& junction_id) const {
224 // TODO(all) Consider if need to use vehicle front rather than position
225 if (feature_history_.empty()) {
226 AERROR << "Obstacle [" << id_ << "] has no history";
227 return false;
228 }
229 if (junction_id.empty()) {
230 return false;
231 }
232 std::shared_ptr<const JunctionInfo> junction_info_ptr =
233 PredictionMap::JunctionById(junction_id);
234 if (junction_info_ptr == nullptr) {
235 return false;
236 }
237 const auto& position = latest_feature().position();
238 return PredictionMap::IsPointInJunction(position.x(), position.y(),
239 junction_info_ptr);
240}
241
243 // If obstacle has no history at all, then exit.
244 if (feature_history_.empty()) {
245 AERROR << "Obstacle [" << id_ << "] has no history";
246 return;
247 }
248 // If obstacle is not in the given junction, then exit.
249 const std::string& junction_id = junction_analyzer_->GetJunctionId();
250 if (!IsInJunction(junction_id)) {
251 ADEBUG << "Obstacle [" << id_ << "] is not in junction [" << junction_id
252 << "]";
253 return;
254 }
255
256 // Set the junction features by calling SetJunctionFeatureWithoutEnterLane.
257 Feature* latest_feature_ptr = mutable_latest_feature();
258 if (feature_history_.size() == 1) {
259 SetJunctionFeatureWithoutEnterLane(latest_feature_ptr);
260 return;
261 }
262 const Feature& prev_feature = feature(1);
263 if (prev_feature.junction_feature().has_enter_lane()) {
264 ACHECK(prev_feature.junction_feature().enter_lane().has_lane_id());
265 std::string enter_lane_id =
266 prev_feature.junction_feature().enter_lane().lane_id();
267 // TODO(all) use enter lane when tracking is better
268 SetJunctionFeatureWithoutEnterLane(latest_feature_ptr);
269 } else {
270 SetJunctionFeatureWithoutEnterLane(latest_feature_ptr);
271 }
272}
273
276 AERROR << "No junction feature found";
277 return false;
278 }
279 CHECK_GT(history_size(), 0U);
280 const Feature& latest_feature = feature_history_.front();
281 double position_x = latest_feature.position().x();
282 double position_y = latest_feature.position().y();
283 double raw_velocity_heading = std::atan2(latest_feature.raw_velocity().y(),
285 for (const JunctionExit& junction_exit :
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,
291 exit_heading)) {
292 return true;
293 }
294 }
295 return false;
296}
297
298void Obstacle::SetJunctionFeatureWithEnterLane(const std::string& enter_lane_id,
299 Feature* const feature_ptr) {
300 feature_ptr->mutable_junction_feature()->CopyFrom(
301 junction_analyzer_->GetJunctionFeature(enter_lane_id));
302}
303
304void Obstacle::SetJunctionFeatureWithoutEnterLane(Feature* const feature_ptr) {
305 // Sanity checks.
306 if (!feature_ptr->has_lane()) {
307 ADEBUG << "Obstacle [" << id_ << "] has no lane.";
308 return;
309 }
310
311 // Get the possible lanes that the obstalce is on and their neighbor
312 // lanes and treat them as the starting-lane-segments.
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());
318 }
319 }
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());
323 }
324 }
325 if (start_lane_ids.empty()) {
326 ADEBUG << "Obstacle [" << id_ << "] has no lane in junction";
327 return;
328 }
329 // TODO(kechxu) Maybe output all exits if no start lane found
330 feature_ptr->mutable_junction_feature()->CopyFrom(
331 junction_analyzer_->GetJunctionFeature(start_lane_ids));
332}
333
334void Obstacle::SetStatus(const PerceptionObstacle& perception_obstacle,
335 const double timestamp, Feature* feature) {
336 SetTimestamp(perception_obstacle, timestamp, feature);
337 SetPolygonPoints(perception_obstacle, feature);
338 SetPosition(perception_obstacle, feature);
339 SetVelocity(perception_obstacle, feature);
340 SetAcceleration(feature);
341 SetTheta(perception_obstacle, feature);
342 SetLengthWidthHeight(perception_obstacle, feature);
343 SetIsNearJunction(perception_obstacle, feature);
344}
345
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();
350 if (id_ < 0) {
351 id_ = id;
352 ADEBUG << "Obstacle has id [" << id_ << "].";
353 } else {
354 if (id_ != id) {
355 AERROR << "Obstacle [" << id_ << "] has a mismatched ID [" << id
356 << "] from perception obstacle.";
357 return false;
358 }
359 }
360 feature->set_id(id);
361 return true;
362}
363
364void Obstacle::SetType(const PerceptionObstacle& perception_obstacle,
365 Feature* feature) {
366 type_ = perception_obstacle.type();
367 ADEBUG << "Obstacle [" << id_ << "] has type [" << type_ << "].";
368 feature->set_type(type_);
369}
370
371void Obstacle::SetTimestamp(const PerceptionObstacle& perception_obstacle,
372 const double timestamp, Feature* feature) {
373 double ts = timestamp;
374 feature->set_timestamp(ts);
375
376 ADEBUG << "Obstacle [" << id_ << "] has timestamp [" << std::fixed
377 << std::setprecision(6) << ts << "].";
378}
379
380void Obstacle::SetPolygonPoints(const PerceptionObstacle& perception_obstacle,
381 Feature* feature) {
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();
386 }
387}
388
389void Obstacle::SetPosition(const PerceptionObstacle& perception_obstacle,
390 Feature* feature) {
391 *feature->mutable_position() = perception_obstacle.position();
392 ADEBUG << "Obstacle [" << id_
393 << "] has position:" << perception_obstacle.position().DebugString();
394}
395
396void Obstacle::SetVelocity(const PerceptionObstacle& perception_obstacle,
397 Feature* feature) {
398 double velocity_x = 0.0;
399 double velocity_y = 0.0;
400 double velocity_z = 0.0;
401
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";
407 velocity_x = 0.0;
408 } else if (velocity_x > 50.0 || velocity_x < -50.0) {
409 AERROR << "Found unreasonable velocity_x from perception obstacle";
410 }
411 }
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";
416 velocity_y = 0.0;
417 } else if (velocity_y > 50.0 || velocity_y < -50.0) {
418 AERROR << "Found unreasonable velocity_y from perception obstacle";
419 }
420 }
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";
425 velocity_z = 0.0;
426 } else if (velocity_z > 50.0 || velocity_z < -50.0) {
427 AERROR << "Found unreasonable velocity_z from perception obstacle";
428 }
429 }
430 }
431
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);
435
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();
440 }
441
442 if (!FLAGS_use_navigation_mode && FLAGS_adjust_velocity_by_position_shift &&
443 history_size() > 0) {
444 double diff_x =
445 feature->position().x() - feature_history_.front().position().x();
446 double diff_y =
447 feature->position().y() - feature_history_.front().position().y();
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);
453 double shift_thred =
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);
461 double angle_diff =
462 common::math::NormalizeAngle(shift_heading - velocity_heading);
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;
466 }
467 }
468 velocity_x = speed * std::cos(velocity_heading);
469 velocity_y = speed * std::sin(velocity_heading);
470 }
471
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);
476 feature->set_speed(speed);
477
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 << "].";
486}
487
488void Obstacle::AdjustHeadingByLane(Feature* feature) {
489 if (!feature->has_lane() || !feature->lane().has_lane_feature()) {
490 return;
491 }
492 double velocity_heading = feature->velocity_heading();
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;
497 double speed = feature->speed();
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);
501 }
502}
503
504void Obstacle::UpdateVelocity(const double theta, double* velocity_x,
505 double* velocity_y, double* velocity_heading,
506 double* speed) {
507 *speed = std::hypot(*velocity_x, *velocity_y);
508 double angle_diff = common::math::NormalizeAngle(*velocity_heading - theta);
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);
513 }
514}
515
516void Obstacle::SetAcceleration(Feature* feature) {
517 double acc_x = 0.0;
518 double acc_y = 0.0;
519 double acc_z = 0.0;
520 double acc = 0.0;
521
522 if (feature_history_.size() > 0) {
523 double curr_ts = feature->timestamp();
524 double prev_ts = feature_history_.front().timestamp();
525
526 const Point3D& curr_velocity = feature->velocity();
527 const Point3D& prev_velocity = feature_history_.front().velocity();
528
529 if (curr_ts > prev_ts) {
530 // A damp function is to punish acc calculation for low speed
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);
534
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);
538
539 acc_x *= damping_x;
540 acc_y *= damping_y;
541 acc_z *= damping_z;
542
543 acc_x = common::math::Clamp(acc_x, FLAGS_vehicle_min_linear_acc,
544 FLAGS_vehicle_max_linear_acc);
545 acc_y = common::math::Clamp(acc_y, FLAGS_vehicle_min_linear_acc,
546 FLAGS_vehicle_max_linear_acc);
547 acc_z = common::math::Clamp(acc_z, FLAGS_vehicle_min_linear_acc,
548 FLAGS_vehicle_max_linear_acc);
549
550 double heading = feature->velocity_heading();
551 acc = acc_x * std::cos(heading) + acc_y * std::sin(heading);
552 }
553 }
554
555 feature->mutable_acceleration()->set_x(acc_x);
556 feature->mutable_acceleration()->set_y(acc_y);
557 feature->mutable_acceleration()->set_z(acc_z);
558 feature->set_acc(acc);
559
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 << "].";
566}
567
568void Obstacle::SetTheta(const PerceptionObstacle& perception_obstacle,
569 Feature* feature) {
570 double theta = 0.0;
571 if (perception_obstacle.has_theta()) {
572 theta = perception_obstacle.theta();
573 }
574 feature->set_theta(theta);
575
576 ADEBUG << "Obstacle [" << id_ << "] has theta [" << std::fixed
577 << std::setprecision(6) << theta << "].";
578}
579
580void Obstacle::SetLengthWidthHeight(
581 const PerceptionObstacle& perception_obstacle, Feature* feature) {
582 double length = 0.0;
583 double width = 0.0;
584 double height = 0.0;
585
586 if (perception_obstacle.has_length()) {
587 length = perception_obstacle.length();
588 }
589 if (perception_obstacle.has_width()) {
590 width = perception_obstacle.width();
591 }
592 if (perception_obstacle.has_height()) {
593 height = perception_obstacle.height();
594 }
595
596 feature->set_length(length);
597 feature->set_width(width);
598 feature->set_height(height);
599
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 << "].";
604}
605
606void Obstacle::SetIsNearJunction(const PerceptionObstacle& perception_obstacle,
607 Feature* feature) {
608 if (!perception_obstacle.has_position()) {
609 return;
610 }
611 if (!perception_obstacle.position().has_x() ||
612 !perception_obstacle.position().has_y()) {
613 return;
614 }
615 double x = perception_obstacle.position().x();
616 double y = perception_obstacle.position().y();
617 bool is_near_junction =
618 PredictionMap::NearJunction({x, y}, FLAGS_junction_search_radius);
619 feature->set_is_near_junction(is_near_junction);
620}
621
623 if (history_size() == 0) {
624 return false;
625 }
626 return latest_feature().has_junction_feature() &&
627 latest_feature().junction_feature().junction_exit_size() > 0;
628}
629
630void Obstacle::SetCurrentLanes(Feature* feature) {
631 Eigen::Vector2d point(feature->position().x(), feature->position().y());
632 double heading = feature->velocity_heading();
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;
636 if (PredictionMap::InJunction(point, FLAGS_junction_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;
640 }
641 std::vector<std::shared_ptr<const LaneInfo>> current_lanes;
642 PredictionMap::OnLane(current_lanes_, point, heading, lane_search_radius,
643 true, max_num_lane, max_angle_diff, &current_lanes);
644 current_lanes_ = current_lanes;
645 if (current_lanes_.empty()) {
646 ADEBUG << "Obstacle [" << id_ << "] has no current lanes.";
647 return;
648 }
649 Lane lane;
650 if (feature->has_lane()) {
651 lane = feature->lane();
652 }
653 double min_heading_diff = std::numeric_limits<double>::infinity();
654 clusters_ptr_->ClearObstacle();
655 for (std::shared_ptr<const LaneInfo> current_lane : current_lanes) {
656 if (current_lane == nullptr) {
657 continue;
658 }
659
660 int turn_type = PredictionMap::LaneTurnType(current_lane->id().id());
661 std::string lane_id = current_lane->id().id();
662 double s = 0.0;
663 double l = 0.0;
664 PredictionMap::GetProjection(point, current_lane, &s, &l);
665 if (s < 0.0) {
666 continue;
667 }
668
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 =
674 PredictionMap::PathHeading(current_lane, nearest_point);
675 double angle_diff = common::math::AngleDiff(heading, nearest_point_heading);
676 double left = 0.0;
677 double right = 0.0;
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);
692 }
693 clusters_ptr_->AddObstacle(id_, lane_id, s, l);
694 ADEBUG << "Obstacle [" << id_ << "] has current lanes ["
695 << lane_feature->ShortDebugString() << "].";
696 }
697
698 if (lane.has_lane_feature()) {
699 ADEBUG << "Obstacle [" << id_ << "] has one current lane ["
700 << lane.lane_feature().ShortDebugString() << "].";
701 }
702
703 feature->mutable_lane()->CopyFrom(lane);
704}
705
706void Obstacle::SetNearbyLanes(Feature* feature) {
707 Eigen::Vector2d point(feature->position().x(), feature->position().y());
708 int max_num_lane = FLAGS_max_num_nearby_lane;
709 double lane_search_radius = FLAGS_lane_search_radius;
710 if (PredictionMap::InJunction(point, FLAGS_junction_search_radius)) {
711 max_num_lane = FLAGS_max_num_nearby_lane_in_junction;
712 lane_search_radius = FLAGS_lane_search_radius_in_junction;
713 }
714 double theta = feature->velocity_heading();
715 std::vector<std::shared_ptr<const LaneInfo>> nearby_lanes;
716 PredictionMap::NearbyLanesByCurrentLanes(point, theta, lane_search_radius,
717 current_lanes_, max_num_lane,
718 &nearby_lanes);
719 if (nearby_lanes.empty()) {
720 ADEBUG << "Obstacle [" << id_ << "] has no nearby lanes.";
721 return;
722 }
723
724 for (std::shared_ptr<const LaneInfo> nearby_lane : nearby_lanes) {
725 if (nearby_lane == nullptr) {
726 continue;
727 }
728
729 // Ignore bike and sidewalk lanes for vehicles
730 if (type_ == PerceptionObstacle::VEHICLE &&
731 nearby_lane->lane().has_type() &&
732 (nearby_lane->lane().type() == ::apollo::hdmap::Lane::BIKING ||
733 nearby_lane->lane().type() == ::apollo::hdmap::Lane::SIDEWALK)) {
734 ADEBUG << "Obstacle [" << id_ << "] ignores disqualified lanes.";
735 continue;
736 }
737
738 double s = -1.0;
739 double l = 0.0;
740 PredictionMap::GetProjection(point, nearby_lane, &s, &l);
741 if (s < 0.0 || s >= nearby_lane->total_length()) {
742 continue;
743 }
744 int turn_type = PredictionMap::LaneTurnType(nearby_lane->id().id());
745 double heading = feature->velocity_heading();
746 double angle_diff = 0.0;
747 hdmap::MapPathPoint nearest_point;
748 if (PredictionMap::ProjectionFromLane(nearby_lane, s, &nearest_point)) {
749 angle_diff = common::math::AngleDiff(nearest_point.heading(), heading);
750 }
751
752 double left = 0.0;
753 double right = 0.0;
754 nearby_lane->GetWidth(s, &left, &right);
755
756 LaneFeature* lane_feature =
757 feature->mutable_lane()->add_nearby_lane_feature();
758
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() << "]";
769 }
770}
771
772void Obstacle::SetSurroundingLaneIds(Feature* feature, const double radius) {
773 Eigen::Vector2d point(feature->position().x(), feature->position().y());
774 std::vector<std::string> lane_ids =
775 PredictionMap::NearbyLaneIds(point, radius);
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);
783 }
784 }
785}
786
787bool Obstacle::HasJunctionExitLane(
788 const LaneSequence& lane_sequence,
789 const std::unordered_set<std::string>& exit_lane_id_set) {
790 const Feature& feature = latest_feature();
791 if (!feature.has_junction_feature()) {
792 AERROR << "Obstacle [" << id_ << "] has no junction feature.";
793 return false;
794 }
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()) {
798 return true;
799 }
800 }
801 return false;
802}
803
805 // Sanity checks.
806 if (history_size() == 0) {
807 AERROR << "No feature found.";
808 return;
809 }
810
812 // No need to BuildLaneGraph for those non-moving obstacles.
813 if (feature->is_still() && id_ != FLAGS_ego_vehicle_id) {
814 ADEBUG << "Not build lane graph for still obstacle";
815 return;
816 }
817 if (feature->lane().lane_graph().lane_sequence_size() > 0) {
818 ADEBUG << "Not build lane graph for an old obstacle";
819 return;
820 }
821 double speed = feature->speed();
822 double t_max = FLAGS_prediction_trajectory_time_length;
823 auto estimated_move_distance = speed * t_max;
824
825 double road_graph_search_distance = std::fmax(
826 estimated_move_distance, FLAGS_min_prediction_trajectory_spatial_length);
827
828 bool is_in_junction = HasJunctionFeatureWithExits();
829 std::unordered_set<std::string> exit_lane_id_set;
830 if (is_in_junction) {
831 for (const auto& exit : feature->junction_feature().junction_exit()) {
832 exit_lane_id_set.insert(exit.exit_lane_id());
833 }
834 }
835
836 // BuildLaneGraph for current lanes:
837 // Go through all the LaneSegments in current_lane,
838 // construct up to max_num_current_lane of them.
839 int seq_id = 0;
840 int curr_lane_count = 0;
841 for (auto& lane : feature->lane().current_lane_feature()) {
842 std::shared_ptr<const LaneInfo> lane_info =
843 PredictionMap::LaneById(lane.lane_id());
844 LaneGraph lane_graph = clusters_ptr_->GetLaneGraph(
845 lane.lane_s(), road_graph_search_distance, true, lane_info);
846 if (lane_graph.lane_sequence_size() > 0) {
847 ++curr_lane_count;
848 }
849 for (const auto& lane_seq : lane_graph.lane_sequence()) {
850 if (is_in_junction && !HasJunctionExitLane(lane_seq, exit_lane_id_set)) {
851 continue;
852 }
853 LaneSequence* lane_seq_ptr =
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() << "].";
864 }
865 if (curr_lane_count >= FLAGS_max_num_current_lane) {
866 break;
867 }
868 }
869
870 // BuildLaneGraph for neighbor lanes.
871 int nearby_lane_count = 0;
872 for (auto& lane : feature->lane().nearby_lane_feature()) {
873 std::shared_ptr<const LaneInfo> lane_info =
874 PredictionMap::LaneById(lane.lane_id());
875 LaneGraph lane_graph = clusters_ptr_->GetLaneGraph(
876 lane.lane_s(), road_graph_search_distance, false, lane_info);
877 if (lane_graph.lane_sequence_size() > 0) {
878 ++nearby_lane_count;
879 }
880 for (const auto& lane_seq : lane_graph.lane_sequence()) {
881 if (is_in_junction && !HasJunctionExitLane(lane_seq, exit_lane_id_set)) {
882 continue;
883 }
884 LaneSequence* lane_seq_ptr =
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() << "].";
895 }
896 if (nearby_lane_count >= FLAGS_max_num_nearby_lane) {
897 break;
898 }
899 }
900
901 if (feature->has_lane() && feature->lane().has_lane_graph()) {
902 SetLanePoints(feature);
903 SetLaneSequencePath(feature->mutable_lane()->mutable_lane_graph());
904 }
905 ADEBUG << "Obstacle [" << id_ << "] set lane graph features.";
906}
907
908void Obstacle::SetLaneSequenceStopSign(LaneSequence* lane_sequence_ptr) {
909 // Set the nearest stop sign along the lane sequence
910 if (lane_sequence_ptr->lane_segment().empty()) {
911 return;
912 }
913 double accumulate_s = 0.0;
914 for (const LaneSegment& lane_segment : lane_sequence_ptr->lane_segment()) {
915 const StopSign& stop_sign =
916 clusters_ptr_->QueryStopSignByLaneId(lane_segment.lane_id());
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 ["
923 << lane_sequence_ptr->lane_sequence_id() << "].";
924 break;
925 }
926 accumulate_s += lane_segment.total_length();
927 }
928}
929
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) {
934 // Exit recursion if reached max num of allowed search depth.
935 if (recursion_depth <= 0) {
936 return;
937 }
938 if (is_left) {
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();
944 // If haven't seen this lane id before.
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);
949 }
950 }
951 }
952
953 for (const std::string& lane_id : curr_left_lane_ids) {
954 GetNeighborLaneSegments(PredictionMap::LaneById(lane_id), true,
955 recursion_depth - 1, lane_ids_ordered,
956 existing_lane_ids);
957 }
958 } else {
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();
964 // If haven't seen this lane id before.
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);
969 }
970 }
971 }
972
973 for (const std::string& lane_id : curr_right_lane_ids) {
974 GetNeighborLaneSegments(PredictionMap::LaneById(lane_id), false,
975 recursion_depth - 1, lane_ids_ordered,
976 existing_lane_ids);
977 }
978 }
979}
980
982 // Sanity checks.
983 if (history_size() == 0) {
984 AERROR << "No feature found.";
985 return;
986 }
987
988 // No need to BuildLaneGraph for those non-moving obstacles.
990 if (feature->is_still()) {
991 ADEBUG << "Don't build lane graph for non-moving obstacle.";
992 return;
993 }
994 if (feature->lane().lane_graph_ordered().lane_sequence_size() > 0) {
995 ADEBUG << "Don't build lane graph for an old obstacle.";
996 return;
997 }
998 // double speed = feature->speed();
999 double road_graph_search_distance = 50.0 * 0.95; // (45mph for 3sec)
1000 // std::fmax(speed * FLAGS_prediction_trajectory_time_length +
1001 // 0.5 * FLAGS_vehicle_max_linear_acc *
1002 // FLAGS_prediction_trajectory_time_length *
1003 // FLAGS_prediction_trajectory_time_length,
1004 // FLAGS_min_prediction_trajectory_spatial_length);
1005
1006 // Treat the most probable lane_segment as the center, put its left
1007 // and right neighbors into a vector following the left-to-right order.
1008 if (!feature->has_lane() || !feature->lane().has_lane_feature()) {
1009 return;
1010 }
1011
1012 bool is_in_junction = HasJunctionFeatureWithExits();
1013 std::unordered_set<std::string> exit_lane_id_set;
1014 if (is_in_junction) {
1015 for (const auto& exit : feature->junction_feature().junction_exit()) {
1016 exit_lane_id_set.insert(exit.exit_lane_id());
1017 }
1018 }
1019
1020 std::shared_ptr<const LaneInfo> center_lane_info =
1021 PredictionMap::LaneById(feature->lane().lane_feature().lane_id());
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);
1030
1031 const std::vector<std::string> lane_ids_ordered(lane_ids_ordered_list.begin(),
1032 lane_ids_ordered_list.end());
1033 // TODO(all): sort the lane_segments from left to right (again)
1034 // to double-check and make sure it's well sorted.
1035 // Build lane_graph for every lane_segment and update it into proto.
1036 int seq_id = 0;
1037 for (const std::string& lane_id : lane_ids_ordered) {
1038 // Construct the local lane_graph based on the current lane_segment.
1039 bool vehicle_is_on_lane = (lane_id == center_lane_info->lane().id().id());
1040 std::shared_ptr<const LaneInfo> curr_lane_info =
1041 PredictionMap::LaneById(lane_id);
1042 LaneGraph local_lane_graph = clusters_ptr_->GetLaneGraphWithoutMemorizing(
1043 feature->lane().lane_feature().lane_s(), road_graph_search_distance,
1044 true, curr_lane_info);
1045 // Update it into the Feature proto
1046 for (const auto& lane_seq : local_lane_graph.lane_sequence()) {
1047 if (is_in_junction && !HasJunctionExitLane(lane_seq, exit_lane_id_set)) {
1048 continue;
1049 }
1050 LaneSequence* lane_seq_ptr = feature->mutable_lane()
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() << "].";
1060 }
1061 }
1062
1063 // Build lane_points.
1064 if (feature->lane().has_lane_graph_ordered()) {
1065 SetLanePoints(feature, 0.5, 100, true,
1066 feature->mutable_lane()->mutable_lane_graph_ordered());
1067 SetLaneSequencePath(feature->mutable_lane()->mutable_lane_graph_ordered());
1068 }
1069 ADEBUG << "Obstacle [" << id_ << "] set lane graph features.";
1070}
1071
1072// The default SetLanePoints applies to lane_graph with
1073// FLAGS_target_lane_gap.
1074void Obstacle::SetLanePoints(Feature* feature) {
1075 LaneGraph* lane_graph = feature->mutable_lane()->mutable_lane_graph();
1076 SetLanePoints(feature, FLAGS_target_lane_gap, FLAGS_max_num_lane_point, false,
1077 lane_graph);
1078}
1079
1080// The generic SetLanePoints
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;
1087 // Sanity checks.
1088 if (feature == nullptr || !feature->has_velocity_heading()) {
1089 AERROR << "Null feature or no velocity heading.";
1090 return;
1091 }
1092 double heading = feature->velocity_heading();
1093 double x = feature->position().x();
1094 double y = feature->position().y();
1095 Eigen::Vector2d position(x, y);
1096
1097 // Go through every lane_sequence.
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()) {
1101 continue;
1102 }
1103 // TODO(jiacheng): can refactor the following two parts into one to
1104 // make it more elegant.
1105
1106 // If building bidirectionally, then build backward lane-points as well.
1107 if (is_bidirection) {
1108 int lane_index = 0;
1109 double lane_seg_s = lane_sequence->lane_segment(lane_index).start_s();
1110 while (lane_index < lane_sequence->lane_segment_size()) {
1111 // Go through lane_segment one by one sequentially.
1112 LaneSegment* lane_segment =
1113 lane_sequence->mutable_lane_segment(lane_index);
1114
1115 // End-condition: reached the current ADC's location.
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());
1119 break;
1120 }
1121
1122 if (lane_seg_s > lane_segment->end_s()) {
1123 // If already exceeds the current lane_segment, then go to the
1124 // next following one.
1125 ADEBUG << "Move on to the next lane-segment.";
1126 lane_seg_s = lane_seg_s - lane_segment->end_s();
1127 ++lane_index;
1128 } else {
1129 // Otherwise, update lane_graph:
1130 // 1. Sanity checks.
1131 std::string lane_id = lane_segment->lane_id();
1132 lane_segment->set_lane_turn_type(
1134 ADEBUG << "Currently on " << lane_id;
1135 auto lane_info = PredictionMap::LaneById(lane_id);
1136 if (lane_info == nullptr) {
1137 break;
1138 }
1139 // 2. Get the closeset lane_point
1140 ADEBUG << "Lane-segment s = " << lane_seg_s;
1141 Eigen::Vector2d lane_point_pos =
1142 PredictionMap::PositionOnLane(lane_info, lane_seg_s);
1143 double lane_point_heading =
1144 PredictionMap::HeadingOnLane(lane_info, lane_seg_s);
1145 double lane_point_width =
1146 PredictionMap::LaneTotalWidth(lane_info, lane_seg_s);
1147 double lane_point_angle_diff =
1148 common::math::AngleDiff(lane_point_heading, heading);
1149 // 3. Update it into the lane_graph
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);
1157 // Update into lane_segment.
1158 lane_segment->add_lane_point()->CopyFrom(lane_point);
1159 lane_seg_s += lane_point_spacing;
1160 }
1161 }
1162 }
1163
1164 // Build lane-point in the forward direction.
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) {
1169 lane_index = 0;
1170 lane_seg_s = lane_sequence->lane_segment(0).start_s();
1171 }
1172 std::size_t count_point = 0;
1173 while (lane_index < lane_sequence->lane_segment_size() &&
1174 count_point < max_num_lane_point) {
1175 // Go through lane_segment one by one sequentially.
1176 LaneSegment* lane_segment =
1177 lane_sequence->mutable_lane_segment(lane_index);
1178
1179 if (lane_seg_s > lane_segment->end_s()) {
1180 // If already exceeds the current lane_segment, then go to the
1181 // next following one.
1182 ADEBUG << "Move on to the next lane-segment.";
1183 lane_seg_s = lane_seg_s - lane_segment->end_s();
1184 ++lane_index;
1185 } else {
1186 // Otherwise, update lane_graph:
1187 // 1. Sanity checks.
1188 std::string lane_id = lane_segment->lane_id();
1189 lane_segment->set_lane_turn_type(PredictionMap::LaneTurnType(lane_id));
1190 ADEBUG << "Currently on " << lane_id;
1191 auto lane_info = PredictionMap::LaneById(lane_id);
1192 if (lane_info == nullptr) {
1193 break;
1194 }
1195 // 2. Get the closeset lane_point
1196 ADEBUG << "Lane-segment s = " << lane_seg_s;
1197 Eigen::Vector2d lane_point_pos =
1198 PredictionMap::PositionOnLane(lane_info, lane_seg_s);
1199 double lane_point_heading =
1200 PredictionMap::HeadingOnLane(lane_info, lane_seg_s);
1201 double lane_point_width =
1202 PredictionMap::LaneTotalWidth(lane_info, lane_seg_s);
1203 double lane_point_angle_diff =
1204 common::math::AngleDiff(lane_point_heading, heading);
1205 // 3. Update it into the lane_graph
1206 ADEBUG << lane_point_pos[0] << " " << lane_point_pos[1];
1207 LanePoint lane_point;
1208 // Update direct information.
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);
1214 // Update deducted information.
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);
1218 // Update into lane_segment.
1219 lane_segment->add_lane_point()->CopyFrom(lane_point);
1220 ++count_point;
1221 total_s += lane_point_spacing;
1222 lane_seg_s += lane_point_spacing;
1223 }
1224 }
1225 }
1226 ADEBUG << "Obstacle [" << id_ << "] has lane segments and points.";
1227}
1228
1229void Obstacle::SetLaneSequencePath(LaneGraph* const lane_graph) {
1230 // Go through every lane_sequence.
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;
1234 // Go through every lane_segment.
1235 for (const LaneSegment& lane_segment : lane_sequence->lane_segment()) {
1236 // Go through every lane_point and set the corresponding path_point.
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());
1241 }
1242 lane_segment_s += lane_segment.total_length();
1243 }
1244 // Sanity checks.
1245 int num_path_point = lane_sequence->path_point_size();
1246 if (num_path_point <= 0) {
1247 continue;
1248 }
1249 // Go through every path_point, calculate kappa, and update it.
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() &&
1254 point_index >=
1255 lane_sequence->lane_segment(segment_index).lane_point_size()) {
1256 ++segment_index;
1257 point_index = 0;
1258 }
1259 PathPoint* first_point = lane_sequence->mutable_path_point(j);
1260 PathPoint* second_point = lane_sequence->mutable_path_point(j + 1);
1261 double delta_theta = apollo::common::math::AngleDiff(
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() &&
1267 point_index <
1268 lane_sequence->lane_segment(segment_index).lane_point_size()) {
1269 lane_sequence->mutable_lane_segment(segment_index)
1270 ->mutable_lane_point(point_index)
1271 ->set_kappa(kappa);
1272 ++point_index;
1273 }
1274 }
1275 lane_sequence->mutable_path_point(num_path_point - 1)->set_kappa(0.0);
1276 }
1277}
1278
1280 // This function runs after all basic features have been set up
1281 Feature* feature_ptr = mutable_latest_feature();
1282
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.";
1288 continue;
1289 }
1290 double obstacle_s = lane_sequence->lane_s();
1291 double obstacle_l = lane_sequence->lane_l();
1292 NearbyObstacle forward_obstacle;
1293 if (clusters_ptr_->ForwardNearbyObstacle(*lane_sequence, id_, obstacle_s,
1294 obstacle_l, &forward_obstacle)) {
1295 lane_sequence->add_nearby_obstacle()->CopyFrom(forward_obstacle);
1296 }
1297 NearbyObstacle backward_obstacle;
1298 if (clusters_ptr_->BackwardNearbyObstacle(*lane_sequence, id_, obstacle_s,
1299 obstacle_l, &backward_obstacle)) {
1300 lane_sequence->add_nearby_obstacle()->CopyFrom(backward_obstacle);
1301 }
1302 }
1303}
1304
1305void Obstacle::SetMotionStatus() {
1306 int history_size = static_cast<int>(feature_history_.size());
1307 if (history_size == 0) {
1308 AERROR << "Zero history found";
1309 return;
1310 }
1311 double pos_std = FLAGS_still_obstacle_position_std;
1312 double speed_threshold = FLAGS_still_obstacle_speed_threshold;
1313 if (type_ == PerceptionObstacle::PEDESTRIAN ||
1314 type_ == PerceptionObstacle::BICYCLE) {
1315 speed_threshold = FLAGS_still_pedestrian_speed_threshold;
1316 pos_std = FLAGS_still_pedestrian_position_std;
1317 } else if (type_ == PerceptionObstacle::UNKNOWN ||
1319 speed_threshold = FLAGS_still_unknown_speed_threshold;
1320 pos_std = FLAGS_still_unknown_position_std;
1321 }
1322 double speed = feature_history_.front().speed();
1323
1324 if (history_size == 1) {
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);
1329 } else {
1330 feature_history_.front().set_is_still(false);
1331 }
1332 return;
1333 }
1334
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);
1341 CHECK_GT(len, 1);
1342
1343 auto feature_riter = feature_history_.rbegin();
1344 start_x = feature_riter->position().x();
1345 start_y = feature_riter->position().y();
1346 ++feature_riter;
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);
1350 ++feature_riter;
1351 }
1352
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 /
1356 ((history_size + 1) * delta_ts);
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);
1365 } else {
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);
1371 } else {
1372 ADEBUG << "Obstacle [" << id_ << "] is stationary.";
1373 feature_history_.front().set_is_still(true);
1374 }
1375 }
1376}
1377
1378void Obstacle::SetMotionStatusBySpeed() {
1379 auto history_size = feature_history_.size();
1380 if (history_size < 2) {
1381 ADEBUG << "Obstacle [" << id_ << "] has no history and "
1382 << "is considered moving.";
1383 if (history_size > 0) {
1384 feature_history_.front().set_is_still(false);
1385 }
1386 return;
1387 }
1388
1389 double speed_threshold = FLAGS_still_obstacle_speed_threshold;
1390 double speed = feature_history_.front().speed();
1391
1392 if (FLAGS_use_navigation_mode) {
1393 if (speed < speed_threshold) {
1394 feature_history_.front().set_is_still(true);
1395 } else {
1396 feature_history_.front().set_is_still(false);
1397 }
1398 }
1399}
1400
1401void Obstacle::InsertFeatureToHistory(const Feature& feature) {
1402 feature_history_.emplace_front(feature);
1403 ADEBUG << "Obstacle [" << id_ << "] inserted a frame into the history.";
1404}
1405
1406std::unique_ptr<Obstacle> Obstacle::Create(
1407 const PerceptionObstacle& perception_obstacle, const double timestamp,
1408 const int prediction_id, ObstacleClusters* clusters_ptr) {
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)) {
1412 return nullptr;
1413 }
1414 return ptr_obstacle;
1415}
1416
1417std::unique_ptr<Obstacle> Obstacle::Create(const Feature& feature,
1418 ObstacleClusters* clusters_ptr) {
1419 std::unique_ptr<Obstacle> ptr_obstacle(new Obstacle());
1420 ptr_obstacle->SetClusters(clusters_ptr);
1421 ptr_obstacle->InsertFeatureToHistory(feature);
1422 return ptr_obstacle;
1423}
1424
1425bool Obstacle::ReceivedOlderMessage(const double timestamp) const {
1426 if (feature_history_.empty()) {
1427 return false;
1428 }
1429 auto last_timestamp_received = feature_history_.front().timestamp();
1430 return timestamp <= last_timestamp_received;
1431}
1432
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();
1439 }
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";
1444 }
1445}
1446
1448 CHECK_GT(feature_history_.size(), 0U);
1450 feature->mutable_priority()->set_priority(ObstaclePriority::CAUTION);
1451}
1452
1454 if (feature_history_.empty()) {
1455 return false;
1456 }
1457 const Feature& feature = latest_feature();
1459}
1460
1462 CHECK_GT(feature_history_.size(), 0U);
1464 feature->mutable_interactive_tag()
1465 ->set_interactive_tag(ObstacleInteractiveTag::INTERACTION);
1466}
1467
1469 CHECK_GT(feature_history_.size(), 0U);
1471 feature->mutable_interactive_tag()
1472 ->set_interactive_tag(ObstacleInteractiveTag::NONINTERACTION);
1473}
1474
1476 if (feature_history_.empty()) {
1477 return false;
1478 }
1479 const Feature& feature = latest_feature();
1482}
1483
1485 const ObstacleConf::EvaluatorType& evaluator_type) {
1486 obstacle_conf_.set_evaluator_type(evaluator_type);
1487}
1488
1490 const ObstacleConf::PredictorType& predictor_type) {
1491 obstacle_conf_.set_predictor_type(predictor_type);
1492}
1493
1495 PredictionObstacle prediction_obstacle;
1496 // TODO(kechxu) implement
1497 return prediction_obstacle;
1498}
1499
1500void Obstacle::SetClusters(ObstacleClusters* clusters_ptr) {
1501 clusters_ptr_ = clusters_ptr;
1502}
1503
1504} // namespace prediction
1505} // namespace apollo
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.
Definition obstacle.cc:223
double timestamp() const
Get the obstacle's timestamp.
Definition obstacle.cc:62
bool HasJunctionFeatureWithExits() const
Check if the obstacle has junction feature.
Definition obstacle.cc:622
bool ReceivedOlderMessage(const double timestamp) const
Definition obstacle.cc:1425
bool IsNearJunction()
Check if the obstacle is near a junction.
Definition obstacle.cc:130
void SetNearbyObstacles()
Set nearby obstacles.
Definition obstacle.cc:1279
Feature * mutable_feature(const size_t i)
Get a pointer to the ith feature from latest to earliest.
Definition obstacle.cc:72
Feature * mutable_latest_feature()
Get a pointer to the latest feature.
Definition obstacle.cc:88
void BuildLaneGraphFromLeftToRight()
Build obstacle's lane graph with lanes being ordered.
Definition obstacle.cc:981
void BuildLaneGraph()
Build obstacle's lane graph
Definition obstacle.cc:804
perception::PerceptionObstacle::Type type() const
Get the type of perception obstacle's type.
Definition obstacle.cc:54
bool IsCloseToJunctionExit() const
Check if the obstacle is close to a junction exit.
Definition obstacle.cc:274
void TrimHistory(const size_t remain_size)
Definition obstacle.cc:217
bool IsStill()
Check if the obstacle is still.
Definition obstacle.cc:95
bool InsertFeature(const Feature &feature)
Insert a feature proto message.
Definition obstacle.cc:198
void SetNonInteractiveTag()
Set the obstacle as noninteractive obstacle.
Definition obstacle.cc:1468
void SetInteractiveTag()
Set the obstacle as interactive obstacle.
Definition obstacle.cc:1461
int id() const
Get the obstacle's ID.
Definition obstacle.cc:60
bool ToIgnore()
Check if the obstacle can be ignored.
Definition obstacle.cc:123
size_t history_size() const
Get the number of historical features.
Definition obstacle.cc:93
const Feature & feature(const size_t i) const
Get the ith feature from latest to earliest.
Definition obstacle.cc:67
bool IsInteractiveObstacle() const
Definition obstacle.cc:1475
PredictionObstacle GeneratePredictionObstacle()
Definition obstacle.cc:1494
bool Insert(const perception::PerceptionObstacle &perception_obstacle, const double timestamp, const int prediction_id)
Insert a perception obstacle with its timestamp.
Definition obstacle.cc:140
void BuildJunctionFeature()
Build junction feature.
Definition obstacle.cc:242
void SetEvaluatorType(const ObstacleConf::EvaluatorType &evaluator_type)
Definition obstacle.cc:1484
bool IsOnLane() const
Check if the obstacle is on any lane.
Definition obstacle.cc:107
void SetPredictorType(const ObstacleConf::PredictorType &predictor_type)
Definition obstacle.cc:1489
const Feature & earliest_feature() const
Get the earliest feature.
Definition obstacle.cc:83
bool IsSlow()
Check if the obstacle is slow.
Definition obstacle.cc:102
void SetCaution()
Set the obstacle as caution level
Definition obstacle.cc:1447
static std::unique_ptr< Obstacle > Create(const perception::PerceptionObstacle &perception_obstacle, const double timestamp, const int prediction_id, ObstacleClusters *clusters_ptr)
Constructor
Definition obstacle.cc:1406
const Feature & latest_feature() const
Get the latest feature.
Definition obstacle.cc:78
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.
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
Some util functions.
T Clamp(const T value, T bound1, T bound2)
Clamp a value between two bounds.
Definition math_utils.h:155
double AngleDiff(const double from, const double to)
Calculate the difference between angle from and to
Definition math_utils.cc:61
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
Definition math_utils.cc:53
uint32_t height
Height of point cloud
uint32_t width
Width of point cloud
class register implement
Definition arena_queue.h:37
Obstacle
Holds all global constants for the prediction module.
optional ObstacleInteractiveTag interactive_tag
optional apollo::perception::PerceptionObstacle::Type type
optional ObstaclePriority priority
optional apollo::common::Point3D velocity
Definition feature.proto:90
optional double velocity_heading
Definition feature.proto:93
optional JunctionFeature junction_feature
optional apollo::common::Point3D raw_velocity
Definition feature.proto:91
optional apollo::common::Point3D position
Definition feature.proto:88
optional LaneFeature enter_lane
Definition feature.proto:52
repeated JunctionExit junction_exit
Definition feature.proto:53
repeated LaneSequence lane_sequence
repeated LaneSegment lane_segment
optional InteractiveTag interactive_tag
Definition feature.proto:74