26#include "modules/common_msgs/perception_msgs/perception_obstacle.pb.h"
27#include "modules/common_msgs/planning_msgs/decision.pb.h"
48 const std::shared_ptr<DependencyInjector>& injector) {
53 if (!Task::LoadConfig<SpeedDeciderConfig>(&config_)) {
56 for (
const auto& follow_function :
58 follow_distance_function_.emplace_back(
59 std::make_pair(follow_function.speed(), follow_function.slope()));
61 std::sort(follow_distance_function_.begin(), follow_distance_function_.end());
62 for (
const auto& iter : follow_distance_function_) {
63 AINFO <<
"speed: " << iter.first <<
", slope: " << iter.second;
74 if (!MakeObjectDecision(reference_line_info->
speed_data(),
77 const std::string msg =
"Get object decision by speed profile failed.";
79 return Status(ErrorCode::PLANNING_ERROR, msg);
84SpeedDecider::STLocation SpeedDecider::GetSTLocation(
91 STLocation st_location = BELOW;
92 bool st_position_set =
false;
93 const double start_t = st_boundary.
min_t();
94 const double end_t = st_boundary.
max_t();
95 for (
size_t i = 0; i + 1 < speed_profile.size(); ++i) {
96 const STPoint curr_st(speed_profile[i].s(), speed_profile[i].t());
97 const STPoint next_st(speed_profile[i + 1].s(), speed_profile[i + 1].t());
98 if (curr_st.t() < start_t && next_st.t() < start_t) {
101 if (curr_st.t() > end_t) {
105 if (!FLAGS_use_st_drivable_boundary) {
106 common::math::LineSegment2d speed_line(curr_st, next_st);
108 ADEBUG <<
"speed profile cross st_boundaries.";
111 if (!FLAGS_use_st_drivable_boundary) {
114 if (!CheckKeepClearCrossable(path_decision, speed_profile,
126 if (!st_position_set) {
127 if (start_t < next_st.t() && curr_st.t() < end_t) {
128 STPoint bd_point_front = st_boundary.
upper_points().front();
130 st_location = side < 0.0 ? ABOVE : BELOW;
131 st_position_set =
true;
138bool SpeedDecider::CheckKeepClearCrossable(
139 const PathDecision*
const path_decision,
const SpeedData& speed_profile,
140 const STBoundary& keep_clear_st_boundary)
const {
141 bool keep_clear_crossable =
true;
143 const auto& last_speed_point = speed_profile.back();
144 double last_speed_point_v = 0.0;
145 if (last_speed_point.has_v()) {
146 last_speed_point_v = last_speed_point.v();
148 const size_t len = speed_profile.size();
150 const auto& last_2nd_speed_point = speed_profile[len - 2];
151 last_speed_point_v = (last_speed_point.s() - last_2nd_speed_point.s()) /
152 (last_speed_point.t() - last_2nd_speed_point.t());
155 ADEBUG <<
"last_speed_point_s[" << last_speed_point.s()
156 <<
"] st_boundary.max_s[" << keep_clear_st_boundary.max_s()
157 <<
"] last_speed_point_v[" << last_speed_point_v <<
"]";
158 if (last_speed_point.s() <= keep_clear_st_boundary.max_s() &&
160 keep_clear_crossable =
false;
162 return keep_clear_crossable;
165bool SpeedDecider::CheckKeepClearBlocked(
166 const PathDecision*
const path_decision,
167 const Obstacle& keep_clear_obstacle)
const {
168 bool keep_clear_blocked =
false;
171 for (
const auto* obstacle : path_decision->obstacles().Items()) {
172 if (obstacle->Id() == keep_clear_obstacle.Id()) {
175 const double obstacle_start_s = obstacle->PerceptionSLBoundary().start_s();
176 const double adc_length =
178 const double distance =
179 obstacle_start_s - keep_clear_obstacle.PerceptionSLBoundary().end_s();
181 if (obstacle->IsBlockingObstacle() && distance > 0 &&
182 distance < (adc_length / 2)) {
183 keep_clear_blocked =
true;
187 return keep_clear_blocked;
190bool SpeedDecider::IsFollowTooClose(
const Obstacle& obstacle)
const {
191 if (!obstacle.IsBlockingObstacle()) {
195 if (obstacle.path_st_boundary().min_t() > 0.0) {
198 const double obs_speed = obstacle.speed();
199 const double ego_speed = init_point_.
v();
200 if (obs_speed > ego_speed) {
203 const double distance =
204 obstacle.path_st_boundary().min_s() - FLAGS_min_stop_distance_obstacle;
205 static constexpr double lane_follow_max_decel = 3.0;
206 static constexpr double lane_change_max_decel = 3.0;
207 auto* planning_status =
injector_->planning_context()
208 ->mutable_planning_status()
209 ->mutable_change_lane();
210 double distance_numerator = std::pow((ego_speed - obs_speed), 2) * 0.5;
211 double distance_denominator = lane_follow_max_decel;
212 if (planning_status->has_status() &&
214 distance_denominator = lane_change_max_decel;
216 return distance < distance_numerator / distance_denominator;
219Status SpeedDecider::MakeObjectDecision(
220 const SpeedData& speed_profile, PathDecision*
const path_decision)
const {
221 if (speed_profile.size() < 2) {
222 const std::string msg =
"dp_st_graph failed to get speed profile.";
224 return Status(ErrorCode::PLANNING_ERROR, msg);
227 for (
const auto* obstacle : path_decision->obstacles().Items()) {
228 auto* mutable_obstacle = path_decision->Find(obstacle->Id());
229 const auto& boundary = mutable_obstacle->path_st_boundary();
231 if (boundary.IsEmpty() || boundary.max_s() < 0.0 ||
232 boundary.max_t() < 0.0 ||
233 boundary.min_t() >= speed_profile.back().t()) {
234 AppendIgnoreDecision(mutable_obstacle);
237 if (obstacle->HasLongitudinalDecision()) {
238 AppendIgnoreDecision(mutable_obstacle);
243 if (obstacle->IsVirtual()) {
244 const auto& obstacle_box = obstacle->PerceptionBoundingBox();
245 if (!reference_line_->
IsOnLane(obstacle_box.center())) {
252 CheckStopForPedestrian(*mutable_obstacle)) {
253 ObjectDecisionType stop_decision;
254 if (CreateStopDecision(*mutable_obstacle, &stop_decision,
255 -FLAGS_min_stop_distance_obstacle)) {
256 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph/pedestrian",
262 auto location = GetSTLocation(path_decision, speed_profile, boundary);
264 if (!FLAGS_use_st_drivable_boundary) {
266 if (CheckKeepClearBlocked(path_decision, *obstacle)) {
275 ObjectDecisionType stop_decision;
276 if (CreateStopDecision(*mutable_obstacle, &stop_decision, 0.0)) {
277 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph/keep_clear",
280 }
else if (obstacle->IsStatic()) {
282 ObjectDecisionType stop_decision;
283 if (CreateStopDecision(*mutable_obstacle, &stop_decision,
284 -FLAGS_min_stop_distance_obstacle)) {
285 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph",
288 }
else if (CheckIsFollow(*obstacle, boundary)) {
290 if (IsFollowTooClose(*mutable_obstacle)) {
291 ObjectDecisionType stop_decision;
292 if (CreateStopDecision(*mutable_obstacle, &stop_decision,
293 -FLAGS_min_stop_distance_obstacle)) {
294 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph/too_close",
299 ObjectDecisionType follow_decision;
300 if (CreateFollowDecision(*mutable_obstacle, &follow_decision)) {
301 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph",
307 ObjectDecisionType yield_decision;
308 if (CreateYieldDecision(*mutable_obstacle, &yield_decision)) {
309 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph",
316 ObjectDecisionType ignore;
317 ignore.mutable_ignore();
318 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph", ignore);
321 ObjectDecisionType overtake_decision;
322 if (CreateOvertakeDecision(*mutable_obstacle, &overtake_decision)) {
323 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph/overtake",
329 if (mutable_obstacle->IsBlockingObstacle()) {
330 ObjectDecisionType stop_decision;
331 if (CreateStopDecision(*mutable_obstacle, &stop_decision,
332 -FLAGS_min_stop_distance_obstacle)) {
333 mutable_obstacle->AddLongitudinalDecision(
"dp_st_graph/cross",
336 const std::string msg =
337 absl::StrCat(
"Failed to find a solution for crossing obstacle: ",
338 mutable_obstacle->Id());
340 return Status(ErrorCode::PLANNING_ERROR, msg);
344 AERROR <<
"Unknown position:" << location;
346 AppendIgnoreDecision(mutable_obstacle);
352void SpeedDecider::AppendIgnoreDecision(Obstacle* obstacle)
const {
353 ObjectDecisionType ignore_decision;
354 ignore_decision.mutable_ignore();
355 if (!obstacle->HasLongitudinalDecision()) {
356 obstacle->AddLongitudinalDecision(
"dp_st_graph", ignore_decision);
358 if (!obstacle->HasLateralDecision()) {
359 obstacle->AddLateralDecision(
"dp_st_graph", ignore_decision);
363bool SpeedDecider::CreateStopDecision(
const Obstacle& obstacle,
364 ObjectDecisionType*
const stop_decision,
365 double stop_distance)
const {
366 const auto& boundary = obstacle.path_st_boundary();
371 double fence_s = adc_sl_boundary_.
end_s() + boundary.min_s() + stop_distance;
373 fence_s = obstacle.PerceptionSLBoundary().start_s();
375 const double main_stop_s =
377 if (main_stop_s < fence_s) {
378 ADEBUG <<
"Stop fence is further away, ignore.";
385 auto* stop = stop_decision->mutable_stop();
386 stop->set_distance_s(stop_distance);
387 auto* stop_point = stop->mutable_stop_point();
388 stop_point->
set_x(fence_point.x());
389 stop_point->set_y(fence_point.y());
390 stop_point->set_z(0.0);
391 stop->set_stop_heading(fence_point.heading());
394 stop->set_reason_code(StopReasonCode::STOP_REASON_CLEAR_ZONE);
398 ADEBUG <<
"STOP: obstacle_id[" << obstacle.Id() <<
"] obstacle_type["
399 << PerceptionObstacle_Type_Name(obstacle_type) <<
"]";
404bool SpeedDecider::CreateFollowDecision(
405 const Obstacle& obstacle, ObjectDecisionType*
const follow_decision)
const {
406 const double follow_speed = init_point_.
v();
407 const double follow_distance_s = -EstimateProperFollowGap(follow_speed);
409 const auto& boundary = obstacle.path_st_boundary();
410 const double reference_s =
411 adc_sl_boundary_.
end_s() + boundary.min_s() + follow_distance_s;
412 const double main_stop_s =
414 if (main_stop_s < reference_s) {
415 ADEBUG <<
"Follow reference_s is further away, ignore.";
422 auto* follow = follow_decision->mutable_follow();
423 follow->set_distance_s(follow_distance_s);
424 auto* fence_point = follow->mutable_fence_point();
425 fence_point->
set_x(ref_point.x());
426 fence_point->set_y(ref_point.y());
427 fence_point->set_z(0.0);
428 follow->set_fence_heading(ref_point.heading());
431 ADEBUG <<
"FOLLOW: obstacle_id[" << obstacle.Id() <<
"] obstacle_type["
432 << PerceptionObstacle_Type_Name(obstacle_type) <<
"]";
437bool SpeedDecider::CreateYieldDecision(
438 const Obstacle& obstacle, ObjectDecisionType*
const yield_decision)
const {
442 const auto& obstacle_boundary = obstacle.path_st_boundary();
443 const double yield_distance_s =
444 std::max(-obstacle_boundary.min_s(), -yield_distance);
446 const double reference_line_fence_s =
447 adc_sl_boundary_.
end_s() + obstacle_boundary.min_s() + yield_distance_s;
448 const double main_stop_s =
450 if (main_stop_s < reference_line_fence_s) {
451 ADEBUG <<
"Yield reference_s is further away, ignore.";
458 auto* yield = yield_decision->mutable_yield();
459 yield->set_distance_s(yield_distance_s);
460 yield->mutable_fence_point()->
set_x(ref_point.x());
461 yield->mutable_fence_point()->set_y(ref_point.y());
462 yield->mutable_fence_point()->set_z(0.0);
463 yield->set_fence_heading(ref_point.heading());
465 ADEBUG <<
"YIELD: obstacle_id[" << obstacle.Id() <<
"] obstacle_type["
466 << PerceptionObstacle_Type_Name(obstacle_type) <<
"]";
471bool SpeedDecider::CreateOvertakeDecision(
472 const Obstacle& obstacle,
473 ObjectDecisionType*
const overtake_decision)
const {
474 const auto& velocity = obstacle.Perception().velocity();
475 const double obstacle_speed =
477 .
InnerProd(Vec2d(velocity.x(), velocity.y()));
479 double overtake_distance_s =
480 EstimateProperOvertakingGap(obstacle_speed, init_point_.
v());
482 const auto& boundary = obstacle.path_st_boundary();
483 const double reference_line_fence_s =
484 adc_sl_boundary_.
end_s() + boundary.min_s() + overtake_distance_s;
485 const double main_stop_s =
487 if (main_stop_s < reference_line_fence_s) {
488 ADEBUG <<
"Overtake reference_s is further away, ignore.";
495 auto* overtake = overtake_decision->mutable_overtake();
496 overtake->set_distance_s(overtake_distance_s);
497 overtake->mutable_fence_point()->
set_x(ref_point.x());
498 overtake->mutable_fence_point()->set_y(ref_point.y());
499 overtake->mutable_fence_point()->set_z(0.0);
500 overtake->set_fence_heading(ref_point.heading());
503 ADEBUG <<
"OVERTAKE: obstacle_id[" << obstacle.Id() <<
"] obstacle_type["
504 << PerceptionObstacle_Type_Name(obstacle_type) <<
"]";
509bool SpeedDecider::CheckIsFollow(
const Obstacle& obstacle,
510 const STBoundary& boundary)
const {
511 const double obstacle_l_distance =
512 std::min(std::fabs(obstacle.PerceptionSLBoundary().start_l()),
513 std::fabs(obstacle.PerceptionSLBoundary().end_l()));
519 if (boundary.bottom_left_point().s() > boundary.bottom_right_point().s()) {
523 static constexpr double kFollowTimeEpsilon = 1e-3;
524 static constexpr double kFollowCutOffTime = 0.5;
525 if (boundary.min_t() > kFollowCutOffTime ||
526 boundary.max_t() < kFollowTimeEpsilon) {
538bool SpeedDecider::CheckStopForPedestrian(
const Obstacle& obstacle)
const {
539 const auto& perception_obstacle = obstacle.Perception();
544 const auto& obstacle_sl_boundary = obstacle.PerceptionSLBoundary();
545 if (obstacle_sl_boundary.end_s() < adc_sl_boundary_.
start_s()) {
550 auto* mutable_speed_decider_status =
injector_->planning_context()
551 ->mutable_planning_status()
552 ->mutable_speed_decider();
553 std::unordered_map<std::string, double> stop_time_map;
554 for (
const auto& pedestrian_stop_time :
555 mutable_speed_decider_status->pedestrian_stop_time()) {
556 stop_time_map[pedestrian_stop_time.obstacle_id()] =
557 pedestrian_stop_time.stop_timestamp_sec();
560 const std::string& obstacle_id = obstacle.Id();
564 static constexpr double kSDistanceStartTimer = 10.0;
565 static constexpr double kMaxStopSpeed = 0.3;
566 static constexpr double kPedestrianStopTimeout = 4.0;
569 if (obstacle.path_st_boundary().min_s() < kSDistanceStartTimer) {
570 const auto obstacle_speed = std::hypot(perception_obstacle.velocity().x(),
571 perception_obstacle.velocity().y());
572 if (obstacle_speed > kMaxStopSpeed) {
573 stop_time_map.erase(obstacle_id);
575 if (stop_time_map.count(obstacle_id) == 0) {
578 ADEBUG <<
"add timestamp: obstacle_id[" << obstacle_id <<
"] timestamp["
583 ADEBUG <<
"stop_timer: obstacle_id[" << obstacle_id <<
"] stop_timer["
584 << stop_timer <<
"]";
585 if (stop_timer >= kPedestrianStopTimeout) {
593 mutable_speed_decider_status->mutable_pedestrian_stop_time()->Clear();
594 for (
const auto& stop_time : stop_time_map) {
595 auto pedestrian_stop_time =
596 mutable_speed_decider_status->add_pedestrian_stop_time();
597 pedestrian_stop_time->set_obstacle_id(stop_time.first);
598 pedestrian_stop_time->set_stop_timestamp_sec(stop_time.second);
603double SpeedDecider::EstimateProperOvertakingGap(
const double target_obs_speed,
604 const double adc_speed)
const {
605 const double overtake_distance_s = std::fmax(
608 return overtake_distance_s;
611double SpeedDecider::EstimateProperFollowGap(
const double& adc_speed)
const {
613 for (
int i = 1; i < follow_distance_function_.size(); i++) {
614 if (adc_speed <= follow_distance_function_[i].first) {
615 follow_distance += follow_distance_function_[i - 1].second *
616 (adc_speed - follow_distance_function_[i - 1].first);
619 follow_distance += follow_distance_function_[i - 1].second *
620 (follow_distance_function_[i].first -
621 follow_distance_function_[i - 1].first);
624 if (adc_speed > follow_distance_function_.back().first) {
625 follow_distance += follow_distance_function_.back().second *
626 (adc_speed - follow_distance_function_.back().first);
628 AINFO <<
"follow_distance: " << follow_distance;
629 return follow_distance;
A general class to denote the return status of an API call.
bool ok() const
check whether the return status is OK.
static Status OK()
generate a success status.
@Brief This is a helper class that can load vehicle configurations.
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
bool HasOverlap(const LineSegment2d &line_segment) const
Check if a line segment has overlap with this polygon.
Implements a class of 2-dimensional vectors.
void set_x(const double x)
Setter for x component
static Vec2d CreateUnitVec2d(const double angle)
Creates a unit-vector with a given angle to the positive x semi-axis
double InnerProd(const Vec2d &other) const
Returns the inner product between these two Vec2d.
a singleton clock that can be used to get the current timestamp.
static double NowInSeconds()
gets the current time in second.
Frame holds all data for one planning cycle.
const common::TrajectoryPoint & PlanningStartPoint() const
PathDecision represents all obstacle decisions on one path.
double stop_reference_line_s() const
ReferenceLineInfo holds all data for one reference line.
PathDecision * path_decision()
const SpeedData & speed_data() const
const ReferenceLine & reference_line() const
const SLBoundary & AdcSlBoundary() const
bool IsOnLane(const common::SLPoint &sl_point) const
: check if a box/point is on lane along reference line
ReferencePoint GetReferencePoint(const double s) const
std::vector< STPoint > upper_points() const
BoundaryType boundary_type() const
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info) override
std::shared_ptr< DependencyInjector > injector_
ReferenceLineInfo * reference_line_info_
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
virtual common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info)
Planning module main class.
double CrossProd(const Vec2d &start_point, const Vec2d &end_point_1, const Vec2d &end_point_2)
Cross product between two 2-D vectors from the common start point, and end at two other points.
Defines proper safety distance the ADC should keep from target obstacle considering different informa...
optional PathPoint path_point
optional VehicleParam vehicle_param
repeated FollowDistance follow_distance
optional double follow_min_obs_lateral_distance
optional double follow_min_time_sec
optional double yield_distance_buffer
optional bool is_stop_for_pedestrain
optional double overtake_min_distance
optional double stop_follow_distance
optional double overtake_time_buffer
optional double keep_clear_last_point_speed
optional FollowDistanceSchedulerInfo follow_distance_scheduler