Apollo 11.0
自动驾驶开放平台
crosswalk.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
22
23#include <algorithm>
24#include <limits>
25#include <memory>
26#include <unordered_map>
27#include <utility>
28
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"
32#include "cyber/time/clock.h"
41
42namespace apollo {
43namespace planning {
44
54 std::vector<std::pair<const hdmap::PathOverlap*, std::vector<std::string>>>;
56 std::unordered_map<std::string, std::unordered_map<std::string, double>>;
57
58bool Crosswalk::Init(const std::string& name,
59 const std::shared_ptr<DependencyInjector>& injector) {
60 if (!TrafficRule::Init(name, injector)) {
61 return false;
62 }
63 // Load the config this task.
64 return TrafficRule::LoadConfig<CrosswalkConfig>(&config_);
65}
66
68 ReferenceLineInfo* const reference_line_info) {
69 CHECK_NOTNULL(frame);
70 CHECK_NOTNULL(reference_line_info);
71
72 if (!FindCrosswalks(reference_line_info)) {
73 injector_->planning_context()->mutable_planning_status()->clear_crosswalk();
74 return Status::OK();
75 }
76
77 MakeDecisions(frame, reference_line_info);
78 return Status::OK();
79}
80
81void Crosswalk::MakeDecisions(Frame* const frame,
82 ReferenceLineInfo* const reference_line_info) {
83 CHECK_NOTNULL(frame);
84 CHECK_NOTNULL(reference_line_info);
85
86 auto* mutable_crosswalk_status = injector_->planning_context()
87 ->mutable_planning_status()
88 ->mutable_crosswalk();
89
90 auto* path_decision = reference_line_info->path_decision();
91 double adc_front_edge_s = reference_line_info->AdcSlBoundary().end_s();
92
93 CrosswalkToStop crosswalks_to_stop;
94
95 // read crosswalk_stop_timer from saved status
96 CrosswalkStopTimer crosswalk_stop_timer;
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());
100 }
101 crosswalk_stop_timer.emplace(mutable_crosswalk_status->crosswalk_id(),
102 stop_times);
103
104 const auto& finished_crosswalks =
105 mutable_crosswalk_status->finished_crosswalk();
106
107 const auto& reference_line = reference_line_info->reference_line();
108 for (auto crosswalk_overlap : crosswalk_overlaps_) {
109 auto crosswalk_ptr = HDMapUtil::BaseMap().GetCrosswalkById(
110 hdmap::MakeMapId(crosswalk_overlap->object_id));
111 std::string crosswalk_id = crosswalk_ptr->id().id();
112
113 // skip crosswalk if master vehicle body already passes the stop line
114 if (adc_front_edge_s - crosswalk_overlap->end_s >
115 config_.min_pass_s_distance()) {
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();
120 }
121
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.";
126 continue;
127 }
128
129 // check if crosswalk already finished
130 if (finished_crosswalks.end() != std::find(finished_crosswalks.begin(),
131 finished_crosswalks.end(),
132 crosswalk_id)) {
133 ADEBUG << "SKIP: crosswalk_id[" << crosswalk_id << "] crosswalk_end_s["
134 << crosswalk_overlap->end_s << "] finished already";
135 continue;
136 }
137
138 std::vector<std::string> pedestrians;
139 for (const auto* obstacle : path_decision->obstacles().Items()) {
140 const double stop_deceleration = util::GetADCStopDeceleration(
141 injector_->vehicle_state(), adc_front_edge_s,
142 crosswalk_overlap->start_s);
143
144 bool stop = CheckStopForObstacle(reference_line_info, crosswalk_ptr,
145 *obstacle, stop_deceleration);
146
147 const std::string& obstacle_id = obstacle->Id();
148 const PerceptionObstacle& perception_obstacle = obstacle->Perception();
149 PerceptionObstacle::Type obstacle_type = perception_obstacle.type();
150 std::string obstacle_type_name =
151 PerceptionObstacle_Type_Name(obstacle_type);
152
153 // update stop timestamp on static pedestrian for watch timer
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 <=
158 config_.start_watch_timer_distance()) {
159 // check on stop timer for static pedestrians/bicycles
160 // if NOT on_lane ahead of adc
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) {
166 // add timestamp
167 ADEBUG << "add timestamp: obstacle_id[" << obstacle_id
168 << "] timestamp[" << Clock::NowInSeconds() << "]";
169 crosswalk_stop_timer[crosswalk_id].insert(
170 {obstacle_id, Clock::NowInSeconds()});
171 } else {
172 double stop_time = Clock::NowInSeconds() -
173 crosswalk_stop_timer[crosswalk_id][obstacle_id];
174 ADEBUG << "stop_time: obstacle_id[" << obstacle_id << "] stop_time["
175 << stop_time << "]";
176 if (stop_time >= config_.stop_timeout()) {
177 stop = false;
178 }
179 }
180 }
181 }
182
183 if (stop) {
184 pedestrians.push_back(obstacle_id);
185 ADEBUG << "wait for: obstacle_id[" << obstacle_id << "] type["
186 << obstacle_type_name << "] crosswalk_id[" << crosswalk_id
187 << "]";
188 } else {
189 ADEBUG << "skip: obstacle_id[" << obstacle_id << "] type["
190 << obstacle_type_name << "] crosswalk_id[" << crosswalk_id
191 << "]";
192 }
193 }
194
195 if (!pedestrians.empty()) {
196 crosswalks_to_stop.emplace_back(crosswalk_overlap, pedestrians);
197 ADEBUG << "crosswalk_id[" << crosswalk_id << "] STOP";
198 }
199 }
200
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) {
204 // build stop decision
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);
214
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;
219 }
220 }
221
222 if (firsts_crosswalk_to_stop) {
223 // update CrosswalkStatus
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 << "]";
233 }
234
235 // update CrosswalkStatus.finished_crosswalk
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;
242 }
243 }
244 }
245
246 ADEBUG << "crosswalk_status: " << mutable_crosswalk_status->DebugString();
247}
248
249bool Crosswalk::FindCrosswalks(ReferenceLineInfo* const reference_line_info) {
250 CHECK_NOTNULL(reference_line_info);
251
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);
257 }
258 return crosswalk_overlaps_.size() > 0;
259}
260
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);
266
267 std::string crosswalk_id = crosswalk_ptr->id().id();
268
269 const PerceptionObstacle& perception_obstacle = obstacle.Perception();
270 const std::string& obstacle_id = obstacle.Id();
271 PerceptionObstacle::Type obstacle_type = perception_obstacle.type();
272 std::string obstacle_type_name = PerceptionObstacle_Type_Name(obstacle_type);
273 double adc_end_edge_s = reference_line_info->AdcSlBoundary().start_s();
274
275 // check type
276 if (obstacle_type != PerceptionObstacle::PEDESTRIAN &&
277 obstacle_type != PerceptionObstacle::BICYCLE) {
278 ADEBUG << "obstacle_id[" << obstacle_id << "] type[" << obstacle_type_name
279 << "]. skip";
280 return false;
281 }
282
283 // expand crosswalk polygon
284 // note: crosswalk expanded area will include sideway area
285 Vec2d point(perception_obstacle.position().x(),
286 perception_obstacle.position().y());
287 const Polygon2d crosswalk_exp_poly =
288 crosswalk_ptr->polygon().ExpandByDistance(config_.expand_s_distance());
289 bool in_expanded_crosswalk = crosswalk_exp_poly.IsPointIn(point);
290
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";
295 return false;
296 }
297
298 const auto& reference_line = reference_line_info->reference_line();
299
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()));
306
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();
312
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 << "]";
319
320 bool stop = false;
321 if (obstacle_l_distance >= config_.stop_loose_l_distance()) {
322 // (1) when obstacle_l_distance is big enough(>= loose_l_distance),
323 // STOP only if paths crosses
324 if (is_path_cross) {
325 stop = true;
326 ADEBUG << "need_stop(>=l2): obstacle_id[" << obstacle_id << "] type["
327 << obstacle_type_name << "] crosswalk_id[" << crosswalk_id << "]";
328 }
329 } else if (obstacle_l_distance <= config_.stop_strict_l_distance()) {
330 if (is_on_road) {
331 // (2) when l_distance <= strict_l_distance + on_road
332 // always STOP
333 if (obstacle_sl_point.s() > adc_end_edge_s) {
334 stop = true;
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";
339 }
340 } else {
341 // (3) when l_distance <= strict_l_distance
342 // + NOT on_road(i.e. on crosswalk/median etc)
343 // STOP if paths cross
344 if (is_path_cross) {
345 stop = true;
346 ADEBUG << "need_stop(<=l1): obstacle_id[" << obstacle_id << "] type["
347 << obstacle_type_name << "] crosswalk_id[" << crosswalk_id
348 << "] PATH_CRSOSS";
349 } else {
350 // (4) when l_distance <= strict_l_distance
351 // + NOT on_road(i.e. on crosswalk/median etc)
352 // STOP if he pedestrian is moving toward the ego vehicle
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) {
364 stop = true;
365 ADEBUG << "need_stop(<=l1): obstacle_id[" << obstacle_id << "] type["
366 << obstacle_type_name << "] crosswalk_id[" << crosswalk_id
367 << "] MOVING_TOWARD_ADC";
368 }
369 }
370 }
371 } else {
372 // (4) when l_distance is between loose_l and strict_l
373 // use history decision of this crosswalk to smooth unsteadiness
374
375 // TODO(all): replace this temp implementation
376 if (is_path_cross) {
377 stop = true;
378 }
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";
383 }
384
385 // check stop_deceleration
386 if (stop) {
387 if (stop_deceleration >= config_.max_stop_deceleration()) {
388 if (obstacle_l_distance > config_.stop_strict_l_distance()) {
389 // SKIP when stop_deceleration is too big but safe to ignore
390 stop = false;
391 }
392 AWARN << "crosswalk_id[" << crosswalk_id << "] stop_deceleration["
393 << stop_deceleration << "]";
394 }
395 }
396
397 return stop;
398}
399
400} // namespace planning
401} // namespace apollo
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
The class of polygon in 2-D.
Definition polygon2d.h:42
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
a singleton clock that can be used to get the current timestamp.
Definition clock.h:39
static double NowInSeconds()
gets the current time in second.
Definition clock.cc:56
static const HDMap & BaseMap()
CrosswalkInfoConstPtr GetCrosswalkById(const Id &id) const
Definition hdmap.cc:54
common::Status ApplyRule(Frame *const frame, ReferenceLineInfo *const reference_line_info)
Definition crosswalk.cc:67
bool Init(const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
Definition crosswalk.cc:58
Frame holds all data for one planning cycle.
Definition frame.h:62
ReferenceLineInfo holds all data for one reference line.
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.
#define ADEBUG
Definition log.h:41
#define AWARN
Definition log.h:43
Some util functions.
apollo::hdmap::Id MakeMapId(const std::string &id)
create a Map ID given a string.
Definition hdmap_util.h:85
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)
Definition common.cc:28
double GetADCStopDeceleration(apollo::common::VehicleStateProvider *vehicle_state, const double adc_front_edge_s, const double stop_line_s)
Definition util.cc:58
std::vector< std::pair< const hdmap::PathOverlap *, std::vector< std::string > > > CrosswalkToStop
Definition crosswalk.cc:54
std::unordered_map< std::string, std::unordered_map< std::string, double > > CrosswalkStopTimer
Definition crosswalk.cc:56
class register implement
Definition arena_queue.h:37
optional double start_watch_timer_distance