Apollo 11.0
自动驾驶开放平台
rule_based_stop_decider.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2019 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 <string>
20#include <tuple>
21#include <vector>
22
23#include "modules/common_msgs/basic_msgs/pnc_point.pb.h"
24
30
31namespace apollo {
32namespace planning {
33
37
38namespace {
39// TODO(ALL): temporarily copy the value from lane_follow_stage.cc, will extract
40// as a common value for planning later
41constexpr double kStraightForwardLineCost = 10.0;
42} // namespace
43
45 const std::string &config_dir, const std::string &name,
46 const std::shared_ptr<DependencyInjector> &injector) {
47 if (!Decider::Init(config_dir, name, injector)) {
48 return false;
49 }
50 // Load the config this task.
51 return Decider::LoadConfig<RuleBasedStopDeciderConfig>(&config_);
52}
53
54apollo::common::Status RuleBasedStopDecider::Process(
55 Frame *const frame, ReferenceLineInfo *const reference_line_info) {
56 // 1. Rule_based stop for side pass onto reverse lane
57 if (config_.enable_stop_on_side_pass()) {
58 StopOnSidePass(frame, reference_line_info);
59 }
60
61 // 2. Rule_based stop for urgent lane change
63 CheckLaneChangeUrgency(frame);
64 }
65
66 // 3. Rule_based stop at path end position
67 AddPathEndStop(frame, reference_line_info);
68
69 return Status::OK();
70}
71
72void RuleBasedStopDecider::CheckLaneChangeUrgency(Frame *const frame) {
73 for (auto &reference_line_info : *frame->mutable_reference_line_info()) {
74 // Check if the target lane is blocked or not
75 if (reference_line_info.IsChangeLanePath()) {
76 is_clear_to_change_lane_ = IsClearToChangeLane(&reference_line_info);
77 is_change_lane_planning_succeed_ =
78 reference_line_info.Cost() < kStraightForwardLineCost;
79 continue;
80 }
81 // If it's not in lane-change scenario || (target lane is not blocked &&
82 // change lane planning succeed), skip
83 if (frame->reference_line_info().size() <= 1 ||
84 (is_clear_to_change_lane_ && is_change_lane_planning_succeed_)) {
85 continue;
86 }
87 // When the target lane is blocked in change-lane case, check the urgency
88 // Get the end point of current routing
89 const auto &route_end_waypoint =
90 reference_line_info.Lanes().RouteEndWaypoint();
91 // If can't get lane from the route's end waypoint, then skip
92 if (!route_end_waypoint.lane) {
93 continue;
94 }
95 auto point = route_end_waypoint.lane->GetSmoothPoint(route_end_waypoint.s);
96 auto *reference_line = reference_line_info.mutable_reference_line();
97 common::SLPoint sl_point;
98 // Project the end point to sl_point on current reference lane
99 if (reference_line->XYToSL(point, &sl_point) &&
100 reference_line->IsOnLane(sl_point)) {
101 // Check the distance from ADC to the end point of current routing
102 double distance_to_passage_end =
103 sl_point.s() - reference_line_info.AdcSlBoundary().end_s();
104 // If ADC is still far from the end of routing, no need to stop, skip
105 if (distance_to_passage_end >
107 continue;
108 }
109 // In urgent case, set a temporary stop fence and wait to change lane
110 // TODO(Jiaxuan Xu): replace the stop fence to more intelligent actions
111 const std::string stop_wall_id = "lane_change_stop";
112 std::vector<std::string> wait_for_obstacles;
114 stop_wall_id, sl_point.s(), config_.urgent_distance_for_lane_change(),
115 StopReasonCode::STOP_REASON_LANE_CHANGE_URGENCY, wait_for_obstacles,
116 "RuleBasedStopDecider", frame, &reference_line_info);
117 }
118 }
119}
120
121void RuleBasedStopDecider::AddPathEndStop(
122 Frame *const frame, ReferenceLineInfo *const reference_line_info) {
123 if (!reference_line_info->path_data().path_label().empty() &&
124 reference_line_info->path_data().frenet_frame_path().back().s() -
125 reference_line_info->path_data().frenet_frame_path().front().s() <
126 config_.short_path_length_threshold()) {
127 const std::string stop_wall_id =
128 PATH_END_VO_ID_PREFIX + reference_line_info->path_data().path_label();
129 std::vector<std::string> wait_for_obstacles;
131 stop_wall_id,
132 reference_line_info->path_data().frenet_frame_path().back().s() - 0.1,
133 0.0, StopReasonCode::STOP_REASON_REFERENCE_END, wait_for_obstacles,
134 "RuleBasedStopDecider", frame, reference_line_info);
135 }
136}
137
138void RuleBasedStopDecider::StopOnSidePass(
139 Frame *const frame, ReferenceLineInfo *const reference_line_info) {
140 static bool check_clear;
141 static common::PathPoint change_lane_stop_path_point;
142
143 const PathData &path_data = reference_line_info->path_data();
144 double stop_s_on_pathdata = 0.0;
145
146 if (path_data.path_label().find("self") != std::string::npos) {
147 check_clear = false;
148 change_lane_stop_path_point.Clear();
149 return;
150 }
151
152 if (check_clear &&
153 CheckClearDone(*reference_line_info, change_lane_stop_path_point)) {
154 check_clear = false;
155 }
156
157 if (!check_clear &&
158 CheckSidePassStop(path_data, *reference_line_info, &stop_s_on_pathdata)) {
159 if (!IsPerceptionBlocked(*reference_line_info, config_.search_beam_length(),
161 config_.search_range(),
162 config_.is_block_angle_threshold()) &&
163 IsClearToChangeLane(reference_line_info)) {
164 return;
165 }
166 if (!CheckADCStop(path_data, *reference_line_info, stop_s_on_pathdata)) {
167 if (!BuildSidePassStopFence(path_data, stop_s_on_pathdata,
168 &change_lane_stop_path_point, frame,
169 reference_line_info)) {
170 AERROR << "Set side pass stop fail";
171 }
172 } else {
173 if (IsClearToChangeLane(reference_line_info)) {
174 check_clear = true;
175 }
176 }
177 }
178}
179
180// @brief Check if necessary to set stop fence used for nonscenario side pass
181bool RuleBasedStopDecider::CheckSidePassStop(
182 const PathData &path_data, const ReferenceLineInfo &reference_line_info,
183 double *stop_s_on_pathdata) {
184 const std::vector<std::tuple<double, PathData::PathPointType, double>>
185 &path_point_decision_guide = path_data.path_point_decision_guide();
186 PathData::PathPointType last_path_point_type =
188 for (const auto &point_guide : path_point_decision_guide) {
189 if (last_path_point_type == PathData::PathPointType::IN_LANE &&
190 std::get<1>(point_guide) ==
192 *stop_s_on_pathdata = std::get<0>(point_guide);
193 // Approximate the stop fence s based on the vehicle position
194 const auto &vehicle_config =
195 common::VehicleConfigHelper::Instance()->GetConfig();
196 const double ego_front_to_center =
197 vehicle_config.vehicle_param().front_edge_to_center();
198 common::PathPoint stop_pathpoint;
199 if (!path_data.GetPathPointWithRefS(*stop_s_on_pathdata,
200 &stop_pathpoint)) {
201 AERROR << "Can't get stop point on path data";
202 return false;
203 }
204 const double ego_theta = stop_pathpoint.theta();
205 Vec2d shift_vec{ego_front_to_center * std::cos(ego_theta),
206 ego_front_to_center * std::sin(ego_theta)};
207 const Vec2d stop_fence_pose =
208 shift_vec + Vec2d(stop_pathpoint.x(), stop_pathpoint.y());
209 double stop_l_on_pathdata = 0.0;
210 const auto &nearby_path = reference_line_info.reference_line().map_path();
211 nearby_path.GetNearestPoint(stop_fence_pose, stop_s_on_pathdata,
212 &stop_l_on_pathdata);
213 return true;
214 }
215 last_path_point_type = std::get<1>(point_guide);
216 }
217 return false;
218}
219
220// @brief Set stop fence for side pass
221bool RuleBasedStopDecider::BuildSidePassStopFence(
222 const PathData &path_data, const double stop_s_on_pathdata,
223 common::PathPoint *stop_point, Frame *const frame,
224 ReferenceLineInfo *const reference_line_info) {
225 CHECK_NOTNULL(frame);
226 CHECK_NOTNULL(reference_line_info);
227
228 if (!path_data.GetPathPointWithRefS(stop_s_on_pathdata, stop_point)) {
229 AERROR << "Can't get stop point on path data";
230 return false;
231 }
232
233 const std::string stop_wall_id = "Side_Pass_Stop";
234 std::vector<std::string> wait_for_obstacles;
235
236 const auto &nearby_path = reference_line_info->reference_line().map_path();
237 double stop_point_s = 0.0;
238 double stop_point_l = 0.0;
239 nearby_path.GetNearestPoint({stop_point->x(), stop_point->y()}, &stop_point_s,
240 &stop_point_l);
241
242 util::BuildStopDecision(stop_wall_id, stop_point_s, 0.0,
243 StopReasonCode::STOP_REASON_SIDEPASS_SAFETY,
244 wait_for_obstacles, "RuleBasedStopDecider", frame,
245 reference_line_info);
246 return true;
247}
248
249// @brief Check if ADV stop at a stop fence
250bool RuleBasedStopDecider::CheckADCStop(
251 const PathData &path_data, const ReferenceLineInfo &reference_line_info,
252 const double stop_s_on_pathdata) {
253 common::PathPoint stop_point;
254 if (!path_data.GetPathPointWithRefS(stop_s_on_pathdata, &stop_point)) {
255 AERROR << "Can't get stop point on path data";
256 return false;
257 }
258
259 const double adc_speed = injector_->vehicle_state()->linear_velocity();
260 if (adc_speed > config_.max_adc_stop_speed()) {
261 ADEBUG << "ADC not stopped: speed[" << adc_speed << "]";
262 return false;
263 }
264
265 // check stop close enough to stop line of the stop_sign
266 const double adc_front_edge_s = reference_line_info.AdcSlBoundary().end_s();
267 const auto &nearby_path = reference_line_info.reference_line().map_path();
268 double stop_point_s = 0.0;
269 double stop_point_l = 0.0;
270 nearby_path.GetNearestPoint({stop_point.x(), stop_point.y()}, &stop_point_s,
271 &stop_point_l);
272
273 const double distance_stop_line_to_adc_front_edge =
274 stop_point_s - adc_front_edge_s;
275
276 if (distance_stop_line_to_adc_front_edge >
277 config_.max_valid_stop_distance()) {
278 ADEBUG << "not a valid stop. too far from stop line.";
279 return false;
280 }
281
282 return true;
283}
284
285bool RuleBasedStopDecider::CheckClearDone(
286 const ReferenceLineInfo &reference_line_info,
287 const common::PathPoint &stop_point) {
288 const double adc_front_edge_s = reference_line_info.AdcSlBoundary().end_s();
289 const double adc_back_edge_s = reference_line_info.AdcSlBoundary().start_s();
290 const double adc_start_l = reference_line_info.AdcSlBoundary().start_l();
291 const double adc_end_l = reference_line_info.AdcSlBoundary().end_l();
292 double lane_left_width = 0.0;
293 double lane_right_width = 0.0;
294 reference_line_info.reference_line().GetLaneWidth(
295 (adc_front_edge_s + adc_back_edge_s) / 2.0, &lane_left_width,
296 &lane_right_width);
297 SLPoint stop_sl_point;
298 reference_line_info.reference_line().XYToSL(stop_point, &stop_sl_point);
299 // use distance to last stop point to determine if needed to check clear
300 // again
301 if (adc_back_edge_s > stop_sl_point.s()) {
302 if (adc_start_l > -lane_right_width || adc_end_l < lane_left_width) {
303 return true;
304 }
305 }
306 return false;
307}
308
309} // namespace planning
310} // 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
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
const LaneWaypoint & RouteEndWaypoint() const
Frame holds all data for one planning cycle.
Definition frame.h:62
ReferenceLineInfo holds all data for one reference line.
const hdmap::RouteSegments & Lanes() const
const SLBoundary & AdcSlBoundary() const
bool IsChangeLanePath() const
Check if the current reference line is a change lane reference line, i.e., ADC's current position is ...
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
std::shared_ptr< DependencyInjector > injector_
Definition task.h:59
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
Definition task.cc:40
Planning module main class.
This file contains the static member functions from LaneChangeDecider, which are deleted from the cla...
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
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
bool IsClearToChangeLane(ReferenceLineInfo *reference_line_info)
A static function to check if the ChangeLanePath type of reference line is safe or if current referen...
bool IsPerceptionBlocked(const ReferenceLineInfo &reference_line_info, const double search_beam_length, const double search_beam_radius_intensity, const double search_range, const double is_block_angle_threshold)
A static function to estimate if an obstacle in certain range in front of ADV blocks too much space p...
class register implement
Definition arena_queue.h:37
LaneInfoConstPtr lane
Definition path.h:44