26#include <unordered_map>
29#include "modules/common_msgs/basic_msgs/pnc_point.pb.h"
30#include "modules/common_msgs/perception_msgs/perception_obstacle.pb.h"
31#include "modules/planning/planning_base/proto/planning_status.pb.h"
54 std::vector<std::pair<const hdmap::PathOverlap*, std::vector<std::string>>>;
56 std::unordered_map<std::string, std::unordered_map<std::string, double>>;
59 const std::shared_ptr<DependencyInjector>& injector) {
64 return TrafficRule::LoadConfig<CrosswalkConfig>(&config_);
70 CHECK_NOTNULL(reference_line_info);
72 if (!FindCrosswalks(reference_line_info)) {
73 injector_->planning_context()->mutable_planning_status()->clear_crosswalk();
77 MakeDecisions(frame, reference_line_info);
81void Crosswalk::MakeDecisions(
Frame*
const frame,
84 CHECK_NOTNULL(reference_line_info);
86 auto* mutable_crosswalk_status =
injector_->planning_context()
87 ->mutable_planning_status()
88 ->mutable_crosswalk();
97 std::unordered_map<std::string, double> stop_times;
98 for (
const auto& stop_time : mutable_crosswalk_status->stop_time()) {
99 stop_times.emplace(stop_time.obstacle_id(), stop_time.stop_timestamp_sec());
101 crosswalk_stop_timer.emplace(mutable_crosswalk_status->crosswalk_id(),
104 const auto& finished_crosswalks =
105 mutable_crosswalk_status->finished_crosswalk();
107 const auto& reference_line = reference_line_info->
reference_line();
108 for (
auto crosswalk_overlap : crosswalk_overlaps_) {
111 std::string crosswalk_id = crosswalk_ptr->id().id();
114 if (adc_front_edge_s - crosswalk_overlap->end_s >
116 if (mutable_crosswalk_status->has_crosswalk_id() &&
117 mutable_crosswalk_status->crosswalk_id() == crosswalk_id) {
118 mutable_crosswalk_status->clear_crosswalk_id();
119 mutable_crosswalk_status->clear_stop_time();
122 ADEBUG <<
"SKIP: crosswalk_id[" << crosswalk_id
123 <<
"] crosswalk_overlap_end_s[" << crosswalk_overlap->end_s
124 <<
"] adc_front_edge_s[" << adc_front_edge_s
125 <<
"]. adc_front_edge passes crosswalk_end_s + buffer.";
130 if (finished_crosswalks.end() != std::find(finished_crosswalks.begin(),
131 finished_crosswalks.end(),
133 ADEBUG <<
"SKIP: crosswalk_id[" << crosswalk_id <<
"] crosswalk_end_s["
134 << crosswalk_overlap->end_s <<
"] finished already";
138 std::vector<std::string> pedestrians;
139 for (
const auto* obstacle : path_decision->obstacles().Items()) {
141 injector_->vehicle_state(), adc_front_edge_s,
142 crosswalk_overlap->start_s);
144 bool stop = CheckStopForObstacle(reference_line_info, crosswalk_ptr,
145 *obstacle, stop_deceleration);
147 const std::string& obstacle_id = obstacle->Id();
148 const PerceptionObstacle& perception_obstacle = obstacle->Perception();
150 std::string obstacle_type_name =
151 PerceptionObstacle_Type_Name(obstacle_type);
154 const bool is_on_lane =
155 reference_line.IsOnLane(obstacle->PerceptionSLBoundary());
156 if (stop && !is_on_lane &&
157 crosswalk_overlap->start_s - adc_front_edge_s <=
161 const double kMaxStopSpeed = 0.3;
162 auto obstacle_speed = std::hypot(perception_obstacle.velocity().x(),
163 perception_obstacle.velocity().y());
164 if (obstacle_speed <= kMaxStopSpeed) {
165 if (crosswalk_stop_timer[crosswalk_id].count(obstacle_id) < 1) {
167 ADEBUG <<
"add timestamp: obstacle_id[" << obstacle_id
169 crosswalk_stop_timer[crosswalk_id].insert(
173 crosswalk_stop_timer[crosswalk_id][obstacle_id];
174 ADEBUG <<
"stop_time: obstacle_id[" << obstacle_id <<
"] stop_time["
184 pedestrians.push_back(obstacle_id);
185 ADEBUG <<
"wait for: obstacle_id[" << obstacle_id <<
"] type["
186 << obstacle_type_name <<
"] crosswalk_id[" << crosswalk_id
189 ADEBUG <<
"skip: obstacle_id[" << obstacle_id <<
"] type["
190 << obstacle_type_name <<
"] crosswalk_id[" << crosswalk_id
195 if (!pedestrians.empty()) {
196 crosswalks_to_stop.emplace_back(crosswalk_overlap, pedestrians);
197 ADEBUG <<
"crosswalk_id[" << crosswalk_id <<
"] STOP";
201 double min_s = std::numeric_limits<double>::max();
202 hdmap::PathOverlap* firsts_crosswalk_to_stop =
nullptr;
203 for (
auto crosswalk_to_stop : crosswalks_to_stop) {
205 const auto* crosswalk_overlap = crosswalk_to_stop.first;
206 ADEBUG <<
"BuildStopDecision: crosswalk[" << crosswalk_overlap->object_id
207 <<
"] start_s[" << crosswalk_overlap->start_s <<
"]";
208 std::string virtual_obstacle_id =
209 CROSSWALK_VO_ID_PREFIX + crosswalk_overlap->object_id;
211 virtual_obstacle_id, crosswalk_overlap->start_s,
212 config_.
stop_distance(), StopReasonCode::STOP_REASON_CROSSWALK,
213 crosswalk_to_stop.second,
Getname(), frame, reference_line_info);
215 if (crosswalk_to_stop.first->start_s < min_s) {
216 firsts_crosswalk_to_stop =
217 const_cast<PathOverlap*
>(crosswalk_to_stop.first);
218 min_s = crosswalk_to_stop.first->start_s;
222 if (firsts_crosswalk_to_stop) {
224 std::string crosswalk = firsts_crosswalk_to_stop->object_id;
225 mutable_crosswalk_status->set_crosswalk_id(crosswalk);
226 mutable_crosswalk_status->clear_stop_time();
227 for (
const auto& timer : crosswalk_stop_timer[crosswalk]) {
228 auto* stop_time = mutable_crosswalk_status->add_stop_time();
229 stop_time->set_obstacle_id(timer.first);
230 stop_time->set_stop_timestamp_sec(timer.second);
231 ADEBUG <<
"UPDATE stop_time: id[" << crosswalk <<
"] obstacle_id["
232 << timer.first <<
"] stop_timestamp[" << timer.second <<
"]";
236 mutable_crosswalk_status->clear_finished_crosswalk();
237 for (
auto crosswalk_overlap : crosswalk_overlaps_) {
238 if (crosswalk_overlap->start_s < firsts_crosswalk_to_stop->start_s) {
239 mutable_crosswalk_status->add_finished_crosswalk(
240 crosswalk_overlap->object_id);
241 ADEBUG <<
"UPDATE finished_crosswalk: " << crosswalk_overlap->object_id;
246 ADEBUG <<
"crosswalk_status: " << mutable_crosswalk_status->DebugString();
249bool Crosswalk::FindCrosswalks(ReferenceLineInfo*
const reference_line_info) {
250 CHECK_NOTNULL(reference_line_info);
252 crosswalk_overlaps_.clear();
253 const std::vector<hdmap::PathOverlap>& crosswalk_overlaps =
254 reference_line_info->reference_line().map_path().crosswalk_overlaps();
255 for (
const hdmap::PathOverlap& crosswalk_overlap : crosswalk_overlaps) {
256 crosswalk_overlaps_.push_back(&crosswalk_overlap);
258 return crosswalk_overlaps_.size() > 0;
261bool Crosswalk::CheckStopForObstacle(
262 ReferenceLineInfo*
const reference_line_info,
263 const CrosswalkInfoConstPtr crosswalk_ptr,
const Obstacle& obstacle,
264 const double stop_deceleration) {
265 CHECK_NOTNULL(reference_line_info);
267 std::string crosswalk_id = crosswalk_ptr->id().id();
269 const PerceptionObstacle& perception_obstacle = obstacle.Perception();
270 const std::string& obstacle_id = obstacle.Id();
272 std::string obstacle_type_name = PerceptionObstacle_Type_Name(obstacle_type);
273 double adc_end_edge_s = reference_line_info->AdcSlBoundary().start_s();
278 ADEBUG <<
"obstacle_id[" << obstacle_id <<
"] type[" << obstacle_type_name
285 Vec2d point(perception_obstacle.position().x(),
286 perception_obstacle.position().y());
287 const Polygon2d crosswalk_exp_poly =
289 bool in_expanded_crosswalk = crosswalk_exp_poly.IsPointIn(point);
291 if (!in_expanded_crosswalk) {
292 ADEBUG <<
"skip: obstacle_id[" << obstacle_id <<
"] type["
293 << obstacle_type_name <<
"] crosswalk_id[" << crosswalk_id
294 <<
"]: not in crosswalk expanded area";
298 const auto& reference_line = reference_line_info->reference_line();
300 common::SLPoint obstacle_sl_point;
301 reference_line.XYToSL(perception_obstacle.position(), &obstacle_sl_point);
302 auto& obstacle_sl_boundary = obstacle.PerceptionSLBoundary();
303 const double obstacle_l_distance =
304 std::min(std::fabs(obstacle_sl_boundary.start_l()),
305 std::fabs(obstacle_sl_boundary.end_l()));
307 const bool is_on_lane =
308 reference_line.IsOnLane(obstacle.PerceptionSLBoundary());
309 const bool is_on_road =
310 reference_line.IsOnRoad(obstacle.PerceptionSLBoundary());
311 const bool is_path_cross = !obstacle.reference_line_st_boundary().IsEmpty();
313 ADEBUG <<
"obstacle_id[" << obstacle_id <<
"] type[" << obstacle_type_name
314 <<
"] crosswalk_id[" << crosswalk_id <<
"] obstacle_l["
315 << obstacle_sl_point.l() <<
"] within_expanded_crosswalk_area["
316 << in_expanded_crosswalk <<
"] obstacle_l_distance["
317 << obstacle_l_distance <<
"] on_lane[" << is_on_lane <<
"] is_on_road["
318 << is_on_road <<
"] is_path_cross[" << is_path_cross <<
"]";
326 ADEBUG <<
"need_stop(>=l2): obstacle_id[" << obstacle_id <<
"] type["
327 << obstacle_type_name <<
"] crosswalk_id[" << crosswalk_id <<
"]";
333 if (obstacle_sl_point.s() > adc_end_edge_s) {
335 ADEBUG <<
"need_stop(<=l1): obstacle_id[" << obstacle_id <<
"] type["
336 << obstacle_type_name <<
"] s[" << obstacle_sl_point.s()
337 <<
"] adc_end_edge_s[ " << adc_end_edge_s <<
"] crosswalk_id["
338 << crosswalk_id <<
"] ON_ROAD";
346 ADEBUG <<
"need_stop(<=l1): obstacle_id[" << obstacle_id <<
"] type["
347 << obstacle_type_name <<
"] crosswalk_id[" << crosswalk_id
353 const auto obstacle_v = Vec2d(perception_obstacle.velocity().x(),
354 perception_obstacle.velocity().y());
355 const auto adc_path_point =
356 Vec2d(
injector_->ego_info()->start_point().path_point().x(),
357 injector_->ego_info()->start_point().path_point().y());
358 const auto ovstacle_position =
359 Vec2d(perception_obstacle.position().x(),
360 perception_obstacle.position().y());
361 auto obs_to_adc = adc_path_point - ovstacle_position;
362 const double kEpsilon = 1e-6;
363 if (obstacle_v.InnerProd(obs_to_adc) > kEpsilon) {
365 ADEBUG <<
"need_stop(<=l1): obstacle_id[" << obstacle_id <<
"] type["
366 << obstacle_type_name <<
"] crosswalk_id[" << crosswalk_id
367 <<
"] MOVING_TOWARD_ADC";
379 ADEBUG <<
"need_stop(between l1 & l2): obstacle_id[" << obstacle_id
380 <<
"] type[" << obstacle_type_name <<
"] obstacle_l_distance["
381 << obstacle_l_distance <<
"] crosswalk_id[" << crosswalk_id
382 <<
"] USE_PREVIOUS_DECISION";
392 AWARN <<
"crosswalk_id[" << crosswalk_id <<
"] stop_deceleration["
393 << stop_deceleration <<
"]";
A general class to denote the return status of an API call.
static Status OK()
generate a success status.
The class of polygon in 2-D.
Implements a class of 2-dimensional vectors.
a singleton clock that can be used to get the current timestamp.
static double NowInSeconds()
gets the current time in second.
static const HDMap & BaseMap()
CrosswalkInfoConstPtr GetCrosswalkById(const Id &id) const
common::Status ApplyRule(Frame *const frame, ReferenceLineInfo *const reference_line_info)
bool Init(const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
Frame holds all data for one planning cycle.
ReferenceLineInfo holds all data for one reference line.
PathDecision * path_decision()
const ReferenceLine & reference_line() const
const SLBoundary & AdcSlBoundary() const
virtual bool Init(const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
std::shared_ptr< DependencyInjector > injector_
Planning module main class.
apollo::hdmap::Id MakeMapId(const std::string &id)
create a Map ID given a string.
std::shared_ptr< const CrosswalkInfo > CrosswalkInfoConstPtr
int BuildStopDecision(const std::string &stop_wall_id, const double stop_line_s, const double stop_distance, const StopReasonCode &stop_reason_code, const std::vector< std::string > &wait_for_obstacles, const std::string &decision_tag, Frame *const frame, ReferenceLineInfo *const reference_line_info, double stop_wall_width)
double GetADCStopDeceleration(apollo::common::VehicleStateProvider *vehicle_state, const double adc_front_edge_s, const double stop_line_s)
std::vector< std::pair< const hdmap::PathOverlap *, std::vector< std::string > > > CrosswalkToStop
std::unordered_map< std::string, std::unordered_map< std::string, double > > CrosswalkStopTimer
optional double min_pass_s_distance
optional double stop_loose_l_distance
optional double start_watch_timer_distance
optional double stop_strict_l_distance
optional double max_stop_deceleration
optional double stop_distance
optional double stop_timeout
optional double expand_s_distance