Apollo 11.0
自动驾驶开放平台
lane_follow_path.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2023 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 <memory>
21#include <string>
22#include <utility>
23#include <vector>
24
31namespace apollo {
32namespace planning {
33
36
37bool LaneFollowPath::Init(const std::string& config_dir,
38 const std::string& name,
39 const std::shared_ptr<DependencyInjector>& injector) {
40 if (!Task::Init(config_dir, name, injector)) {
41 return false;
42 }
43 // Load the config this task.
44 return Task::LoadConfig<LaneFollowPathConfig>(&config_);
45}
46
47apollo::common::Status LaneFollowPath::Process(
48 Frame* frame, ReferenceLineInfo* reference_line_info) {
49 if (!reference_line_info->path_data().Empty() ||
50 reference_line_info->path_reusable()) {
51 ADEBUG << "Skip this time path empty:"
52 << reference_line_info->path_data().Empty()
53 << "path reusable: " << reference_line_info->path_reusable();
54 return Status::OK();
55 }
56 std::vector<PathBoundary> candidate_path_boundaries;
57 std::vector<PathData> candidate_path_data;
58
60 if (!DecidePathBounds(&candidate_path_boundaries)) {
61 AERROR << "Decide path bound failed";
62 return Status::OK();
63 }
64 if (!OptimizePath(candidate_path_boundaries, &candidate_path_data)) {
65 AERROR << "Optmize path failed";
66 return Status::OK();
67 }
68 if (!AssessPath(&candidate_path_data,
69 reference_line_info->mutable_path_data())) {
70 AERROR << "Path assessment failed";
71 }
72
73 return Status::OK();
74}
75
76bool LaneFollowPath::DecidePathBounds(std::vector<PathBoundary>* boundary) {
77 boundary->emplace_back();
78 auto& path_bound = boundary->back();
79 std::string blocking_obstacle_id = "";
80 std::string lane_type = "";
81 double path_narrowest_width = 0;
82 // 1. Initialize the path boundaries to be an indefinitely large area.
84 &path_bound, init_sl_state_)) {
85 const std::string msg = "Failed to initialize path boundaries.";
86 AERROR << msg;
87 return false;
88 }
89 std::string borrow_lane_type;
90 bool is_include_adc = config_.is_extend_lane_bounds_to_include_adc() &&
91 !injector_->planning_context()
92 ->planning_status()
93 .path_decider()
94 .is_in_path_lane_borrow_scenario();
95 // 2. Decide a rough boundary based on lane info and ADC's position
97 *reference_line_info_, init_sl_state_, &path_bound)) {
98 AERROR << "Failed to decide a rough boundary based on self lane.";
99 return false;
100 }
101 if (is_include_adc) {
104 &path_bound);
105 }
106 PrintCurves print_curve;
107 auto indexed_obstacles = reference_line_info_->path_decision()->obstacles();
108 for (const auto* obs : indexed_obstacles.Items()) {
109 const auto& sl_bound = obs->PerceptionSLBoundary();
110 for (int i = 0; i < sl_bound.boundary_point_size(); i++) {
111 std::string name = obs->Id() + "_obs_sl_boundary";
112 print_curve.AddPoint(name, sl_bound.boundary_point(i).s(),
113 sl_bound.boundary_point(i).l());
114 }
115 }
116 print_curve.PrintToLog();
117
118 path_bound.set_label(absl::StrCat("regular/", "self"));
119
120 // 3. Fine-tune the boundary based on static obstacles
121 PathBound temp_path_bound = path_bound;
122 obs_sl_polygons_.clear();
127 &blocking_obstacle_id, &path_narrowest_width)) {
128 const std::string msg =
129 "Failed to decide fine tune the boundaries after "
130 "taking into consideration all static obstacles.";
131 AERROR << msg;
132 return false;
133 }
134 // 4. Append some extra path bound points to avoid zero-length path data.
135 int counter = 0;
136 while (!blocking_obstacle_id.empty() &&
137 path_bound.size() < temp_path_bound.size() &&
138 counter < FLAGS_num_extra_tail_bound_point) {
139 path_bound.push_back(temp_path_bound[path_bound.size()]);
140 counter++;
141 }
142
143 // lane_follow_status update
144 auto* lane_follow_status = injector_->planning_context()
145 ->mutable_planning_status()
146 ->mutable_lane_follow();
147 if (!blocking_obstacle_id.empty()) {
148 double current_time = ::apollo::cyber::Clock::NowInSeconds();
149 lane_follow_status->set_block_obstacle_id(blocking_obstacle_id);
150 if (lane_follow_status->lane_follow_block()) {
151 lane_follow_status->set_block_duration(
152 lane_follow_status->block_duration() + current_time -
153 lane_follow_status->last_block_timestamp());
154 } else {
155 lane_follow_status->set_block_duration(0);
156 lane_follow_status->set_lane_follow_block(true);
157 }
158 lane_follow_status->set_last_block_timestamp(current_time);
159 } else {
160 if (lane_follow_status->lane_follow_block()) {
161 lane_follow_status->set_block_duration(0);
162 lane_follow_status->set_lane_follow_block(false);
163 lane_follow_status->set_last_block_timestamp(0);
164 }
165 }
166
167 ADEBUG << "Completed generating path boundaries.";
168 if (init_sl_state_.second[0] > path_bound[0].l_upper.l ||
169 init_sl_state_.second[0] < path_bound[0].l_lower.l) {
170 AINFO << "not in self lane maybe lane borrow or out of road. init l : "
171 << init_sl_state_.second[0] << ", path_bound l: [ "
172 << path_bound[0].l_lower.l << "," << path_bound[0].l_upper.l << " ]";
173 return false;
174 }
175 // std::vector<std::pair<double, double>> regular_path_bound_pair;
176 // for (size_t i = 0; i < path_bound.size(); ++i) {
177 // regular_path_bound_pair.emplace_back(std::get<1>(path_bound[i]),
178 // std::get<2>(path_bound[i]));
179 // }
180
181 path_bound.set_blocking_obstacle_id(blocking_obstacle_id);
182 RecordDebugInfo(path_bound, path_bound.label(), reference_line_info_);
183 return true;
184}
185
186bool LaneFollowPath::OptimizePath(
187 const std::vector<PathBoundary>& path_boundaries,
188 std::vector<PathData>* candidate_path_data) {
189 const auto& config = config_.path_optimizer_config();
190 const ReferenceLine& reference_line = reference_line_info_->reference_line();
191 std::array<double, 3> end_state = {0.0, 0.0, 0.0};
192 for (const auto& path_boundary : path_boundaries) {
193 size_t path_boundary_size = path_boundary.boundary().size();
194 if (path_boundary_size <= 1U) {
195 AERROR << "Get invalid path boundary with size: " << path_boundary_size;
196 return false;
197 }
198 std::vector<double> opt_l, opt_dl, opt_ddl;
199 std::vector<std::pair<double, double>> ddl_bounds;
200 PathOptimizerUtil::CalculateAccBound(path_boundary, reference_line,
201 &ddl_bounds);
202 PrintCurves print_debug;
203 for (size_t i = 0; i < path_boundary_size; ++i) {
204 double s = static_cast<double>(i) * path_boundary.delta_s() +
205 path_boundary.start_s();
206 double kappa = reference_line.GetNearestReferencePoint(s).kappa();
207 print_debug.AddPoint("ref_kappa", s, kappa);
208 }
209 print_debug.PrintToLog();
210 const double jerk_bound = PathOptimizerUtil::EstimateJerkBoundary(
211 std::fmax(init_sl_state_.first[1], 1e-12));
212 std::vector<double> ref_l(path_boundary_size, 0);
213 std::vector<double> weight_ref_l(path_boundary_size, 0);
214
216 path_boundary, config.path_reference_l_weight(), &ref_l, &weight_ref_l);
217 bool res_opt = PathOptimizerUtil::OptimizePath(
218 init_sl_state_, end_state, ref_l, weight_ref_l, path_boundary,
219 ddl_bounds, jerk_bound, config, &opt_l, &opt_dl, &opt_ddl);
220 if (res_opt) {
221 auto frenet_frame_path = PathOptimizerUtil::ToPiecewiseJerkPath(
222 opt_l, opt_dl, opt_ddl, path_boundary.delta_s(),
223 path_boundary.start_s());
224 PathData path_data;
225 path_data.SetReferenceLine(&reference_line);
226 path_data.SetFrenetPath(std::move(frenet_frame_path));
227 if (FLAGS_use_front_axe_center_in_path_planning) {
228 auto discretized_path = DiscretizedPath(
230 path_data));
231 path_data.SetDiscretizedPath(discretized_path);
232 }
233 path_data.set_path_label(path_boundary.label());
234 path_data.set_blocking_obstacle_id(path_boundary.blocking_obstacle_id());
235 candidate_path_data->push_back(std::move(path_data));
236 PrintCurves print_path_kappa;
237 for (const auto& p : candidate_path_data->back().discretized_path()) {
238 print_path_kappa.AddPoint(path_boundary.label() + "_path_kappa",
239 p.s() + init_sl_state_.first[0], p.kappa());
240 }
241 print_path_kappa.PrintToLog();
242 }
243 }
244 if (candidate_path_data->empty()) {
245 return false;
246 }
247 return true;
248}
249
250bool LaneFollowPath::AssessPath(std::vector<PathData>* candidate_path_data,
251 PathData* final_path) {
252 PathData& curr_path_data = candidate_path_data->back();
253 RecordDebugInfo(curr_path_data, curr_path_data.path_label(),
256 curr_path_data)) {
257 AINFO << "Lane follow path is invalid";
258 return false;
259 }
260
261 std::vector<PathPointDecision> path_decision;
263 curr_path_data, PathData::PathPointType::IN_LANE, &path_decision);
264 curr_path_data.SetPathPointDecisionGuide(std::move(path_decision));
265
266 if (curr_path_data.Empty()) {
267 AINFO << "Lane follow path is empty after trimed";
268 return false;
269 }
270 *final_path = curr_path_data;
271 AINFO << final_path->path_label() << final_path->blocking_obstacle_id();
272 reference_line_info_->MutableCandidatePathData()->push_back(*final_path);
274 curr_path_data.blocking_obstacle_id());
275 // move obs_sl_polygon to reference_line_info, it will be empty, do not use it
277 return true;
278}
279
280} // namespace planning
281} // 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
@Brief This is a helper class that can load vehicle configurations.
static double NowInSeconds()
gets the current time in second.
Definition clock.cc:56
Frame holds all data for one planning cycle.
Definition frame.h:62
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
static void InitPathPointDecision(const PathData &path_data, const PathData::PathPointType type, std::vector< PathPointDecision > *const path_point_decision)
Init path_point_decision as type
static bool IsValidRegularPath(const ReferenceLineInfo &reference_line_info, const PathData &path_data)
Check if the generated path is valid
static bool GetBoundaryFromSelfLane(const ReferenceLineInfo &reference_line_info, const SLState &init_sl_state, PathBoundary *const path_bound)
generate path bound by self lane and adc position
static bool ExtendBoundaryByADC(const ReferenceLineInfo &reference_line_info, const SLState &init_sl_state, const double extend_buffer, PathBoundary *const path_bound)
extend boundary to include adc
static bool GetBoundaryFromStaticObstacles(const ReferenceLineInfo &reference_line_info, std::vector< SLPolygon > *const sl_polygons, const SLState &init_sl_state, PathBoundary *const path_boundaries, std::string *const blocking_obstacle_id, double *const narrowest_width)
Refine the boundary based on static obstacles.
static void GetSLPolygons(const ReferenceLineInfo &reference_line_info, std::vector< SLPolygon > *polygons, const SLState &init_sl_state)
static bool InitPathBoundary(const ReferenceLineInfo &reference_line_info, PathBoundary *const path_bound, SLState init_sl_state)
Starting from ADC's current position, increment until the path length, and set lateral bounds to be i...
const IndexedList< std::string, Obstacle > & obstacles() const
void RecordDebugInfo(const PathBound &path_boundaries, const std::string &debug_name, ReferenceLineInfo *const reference_line_info)
add path_boundary debug info for PnC monitor
std::vector< SLPolygon > obs_sl_polygons_
void GetStartPointSLState()
calculate init sl state by planning start point, result will store in init_sl_state_
static std::vector< common::PathPoint > ConvertPathPointRefFromFrontAxeToRearAxe(const PathData &path_data)
static void CalculateAccBound(const PathBoundary &path_boundary, const ReferenceLine &reference_line, std::vector< std::pair< double, double > > *ddl_bounds)
calculate ddl bound by referenceline kappa and adc lat accleration
static FrenetFramePath ToPiecewiseJerkPath(const std::vector< double > &x, const std::vector< double > &dx, const std::vector< double > &ddx, const double delta_s, const double start_s)
Data format tramform from raw data to FrenetFramePath
static double EstimateJerkBoundary(const double vehicle_speed)
Calculation of jerk boundary based on vehicle kinematics model.
static bool OptimizePath(const SLState &init_state, const std::array< double, 3 > &end_state, std::vector< double > l_ref, std::vector< double > l_ref_weight, const PathBoundary &path_boundary, const std::vector< std::pair< double, double > > &ddl_bounds, double dddl_bound, const PiecewiseJerkPathConfig &config, std::vector< double > *x, std::vector< double > *dx, std::vector< double > *ddx)
Piecewise jerk path optimizer.
static void UpdatePathRefWithBound(const PathBoundary &path_boundary, double weight, std::vector< double > *ref_l, std::vector< double > *weight_ref_l)
If ref_l is below or above path boundary, will update its values and weights
ReferenceLineInfo holds all data for one reference line.
void SetBlockingObstacle(const std::string &blocking_obstacle_id)
std::vector< SLPolygon > * mutable_obs_sl_polygons()
const ReferenceLine & reference_line() const
std::vector< PathData > * MutableCandidatePathData()
std::shared_ptr< DependencyInjector > injector_
Definition task.h:59
ReferenceLineInfo * reference_line_info_
Definition task.h:58
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.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
std::vector< PathBoundPoint > PathBound
class register implement
Definition arena_queue.h:37
optional PiecewiseJerkPathConfig path_optimizer_config