Apollo 11.0
自动驾驶开放平台
reverse_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>
32namespace apollo {
33namespace planning {
34
37
39 const std::string& config_dir,
40 const std::string& name,
41 const std::shared_ptr<DependencyInjector>& injector) {
42 if (!Task::Init(config_dir, name, injector)) {
43 AINFO << "Failed to initialize task";
44 return false;
45 }
46 // Load the config this task.
47 if (!Task::LoadConfig<ReversePathConfig>(&config_)) {
48 AINFO << "Failed to load config";
49 return false;
50 }
51 AINFO << "ReversePath config: " << config_.DebugString();
52 return true;
53}
54
55apollo::common::Status ReversePath::Process(Frame* frame, ReferenceLineInfo* reference_line_info) {
58 && reference_line_info->GetJunction(init_sl_state_.first[0], &junction_overlap_) == 0) {
59 AERROR << "not in square junction";
60 return Status::OK();
61 }
62 PathBoundary path_boundary;
63 PathData path_data;
64 AINFO << init_sl_state_.first[0] << "," << init_sl_state_.first[1] << "," << init_sl_state_.second[0] << ","
65 << init_sl_state_.second[1];
66 double reference_line_backward_s = reference_line_info->reference_line().GetMapPath().accumulated_s().front();
67 static constexpr double kEpsilon = 0.1;
68 double reference_line_backward_length = init_sl_state_.first[0] - reference_line_backward_s - kEpsilon;
69 if (!DecidePathBounds(&path_boundary, reference_line_backward_length)) {
70 AERROR << "Decide path bound failed";
71 return Status::OK();
72 }
73 if (!OptimizePathOsqp(path_boundary, &path_data)) {
74 AERROR << "Optimize path failed";
75 return Status::OK();
76 }
77 *reference_line_info->mutable_path_data() = path_data;
78 // for (const auto& pt : path_data.discretized_path()) {
79 // AINFO << pt.x() << "," << pt.y() << "," << pt.s() << "," << pt.theta();
80 // }
81 // for (const auto& pt : path_data.frenet_frame_path()) {
82 // AINFO << pt.s() << "," << pt.l() << "," << pt.dl() << "," << pt.ddl();
83 // }
84 return Status::OK();
85}
86
87bool ReversePath::DecidePathBounds(PathBoundary* boundary, double& reference_line_backward_length) {
88 if (!InitPathBoundary(boundary, init_sl_state_, reference_line_backward_length)) {
89 const std::string msg = "Failed to initialize path boundaries.";
90 AERROR << msg;
91 return false;
92 }
93 if (config_.is_considered_square_boundary()) {
94 GetBoundaryFromSquare(*reference_line_info_, boundary, init_sl_state_);
95 } else if (config_.is_considered_lane_boundary()) {
97 AERROR << "Get boundary from self lane failed";
98 return false;
99 }
100 }
101
102 if (init_sl_state_.second[0] > boundary->at(0).l_upper.l || init_sl_state_.second[0] < boundary->at(0).l_lower.l) {
103 AINFO << "init l out of range" << init_sl_state_.second[0] << boundary->at(0).l_lower.l << ","
104 << boundary->at(0).l_upper.l;
106 AERROR << "Failed to decide a rough boundary based on adc.";
107 return false;
108 }
109 AINFO << "extend boundary by adc";
110 }
111 boundary->set_label("reverse_path");
112 RecordDebugInfo(*boundary, boundary->label(), reference_line_info_);
113 return true;
114}
115
116bool ReversePath::OptimizePath(PathBoundary* path_boundary, PathData* candidate_path_data) {
117 double delta_s = path_boundary->delta_s();
118 double start_s = path_boundary->at(0).s;
119 size_t path_boundary_size = path_boundary->boundary().size();
120 FrenetFramePath frenet_frame_path;
121 std::vector<double> opt_l, opt_dl, opt_ddl;
122 opt_l.resize(path_boundary_size, 0.0);
123 opt_dl.resize(path_boundary_size, init_sl_state_.second[1]);
124 opt_ddl.resize(path_boundary_size, 0.0);
125 for (size_t i = 0; i < path_boundary_size; i++) {
126 double cur_l = init_sl_state_.second[0] + init_sl_state_.second[1] * delta_s * i;
127 if (cur_l > path_boundary->at(i).l_upper.l || cur_l < path_boundary->at(i).l_lower.l) {
128 AINFO << "trim the path" << cur_l << "," << path_boundary->delta_s() * i;
129 break;
130 }
131 common::FrenetFramePoint frenet_frame_point;
132 frenet_frame_point.set_s(delta_s * i + start_s);
133 frenet_frame_point.set_l(cur_l);
134 frenet_frame_point.set_dl(init_sl_state_.second[1]);
135 frenet_frame_point.set_ddl(0);
136 frenet_frame_path.push_back(std::move(frenet_frame_point));
137 }
138 if (path_boundary_size <= 1U) {
139 AERROR << "Get invalid path boundary with size: " << path_boundary_size;
140 return false;
141 }
142 candidate_path_data->SetReferenceLine(&reference_line_info_->reference_line());
143 candidate_path_data->SetFrenetPath(frenet_frame_path);
144 candidate_path_data->set_is_reverse_path(true);
145 candidate_path_data->set_path_label("reverse_path");
146 return true;
147}
148
149bool ReversePath::OptimizePathOsqp(PathBoundary& path_boundary, PathData* candidate_path_data) {
150 const auto& config = config_.path_optimizer_config();
151 const ReferenceLine& reference_line = reference_line_info_->reference_line();
152 std::array<double, 3> end_state = {0.0, 0.0, 0.0};
153 size_t path_boundary_size = path_boundary.boundary().size();
154 if (path_boundary_size <= 1U) {
155 AERROR << "Get invalid path boundary with size: " << path_boundary_size;
156 return false;
157 }
158 std::vector<double> opt_l, opt_dl, opt_ddl;
159 std::vector<std::pair<double, double>> ddl_bounds;
160 PathOptimizerUtil::CalculateAccBound(path_boundary, reference_line, &ddl_bounds);
161 std::for_each(ddl_bounds.begin(), ddl_bounds.end(),
162 [](std::pair<double, double>& bound) {
163 double temp = bound.first;
164 bound.first = -bound.second;
165 bound.second = -temp;
166 });
167 PrintCurves print_debug;
168 for (size_t i = 0; i < path_boundary_size; ++i) {
169 double s = static_cast<double>(i) * path_boundary.delta_s() + path_boundary.start_s();
170 double kappa = reference_line.GetNearestReferencePoint(s).kappa();
171 print_debug.AddPoint("ref_kappa", s, kappa);
172 }
173 print_debug.PrintToLog();
174 const double jerk_bound = PathOptimizerUtil::EstimateJerkBoundary(std::fmax(init_sl_state_.first[1], 1e-12));
175 std::vector<double> ref_l(path_boundary_size, 0);
176 std::vector<double> weight_ref_l(path_boundary_size, 0);
177 PathOptimizerUtil::UpdatePathRefWithBound(path_boundary, config.path_reference_l_weight(), &ref_l, &weight_ref_l);
178
179 path_boundary.set_delta_s(0.1);
180 SLState reverse_init_sl_state = init_sl_state_;
181 reverse_init_sl_state.second[1] = -reverse_init_sl_state.second[1];
182 reverse_init_sl_state.second[2] = -reverse_init_sl_state.second[2];
183 bool res_opt = PathOptimizerUtil::OptimizePath(
184 reverse_init_sl_state,
185 end_state,
186 ref_l,
187 weight_ref_l,
188 path_boundary,
189 ddl_bounds,
190 jerk_bound,
191 config,
192 &opt_l,
193 &opt_dl,
194 &opt_ddl);
195 if (res_opt) {
196 auto frenet_frame_path = PathOptimizerUtil::ToPiecewiseJerkPath(
197 opt_l, opt_dl, opt_ddl, path_boundary.delta_s(), path_boundary.start_s());
198
199 double frenet_delta_s = 0.0;
200 for (auto& point : frenet_frame_path) {
201 frenet_delta_s = point.s() - path_boundary.start_s();
202 AINFO << point.dl() << "," << point.ddl();
203 point.set_s(path_boundary.start_s() - frenet_delta_s);
204 point.set_dl(-point.dl());
205 point.set_ddl(-point.ddl());
206 AINFO << point.dl() << "," << point.ddl();
207 }
208 PathData path_data;
209 path_data.SetReferenceLine(&reference_line);
210 path_data.SetFrenetPath(std::move(frenet_frame_path));
211 if (FLAGS_use_front_axe_center_in_path_planning) {
212 auto discretized_path
214 path_data.SetDiscretizedPath(discretized_path);
215 }
216 path_data.set_path_label(path_boundary.label());
217 path_data.set_blocking_obstacle_id(path_boundary.blocking_obstacle_id());
218 path_data.set_is_reverse_path(true);
219 *candidate_path_data = std::move(path_data);
220 }
221 path_boundary.set_delta_s(-0.1);
222 return true;
223}
224
225bool ReversePath::GetBoundaryFromSquare(
226 const ReferenceLineInfo& reference_line_info,
227 PathBoundary* const path_boundary,
228 const SLState& init_sl_state) {
229 const auto& hdmap = hdmap::HDMapUtil::BaseMapPtr();
230 const auto& junction = hdmap->GetJunctionById(hdmap::MakeMapId(junction_overlap_.object_id));
231 const auto& junction_polygon = junction->polygon();
232 const auto& reference_line = reference_line_info.reference_line();
233 SLBoundary sl_boundary;
234 reference_line.GetSLBoundary(junction_polygon, &sl_boundary);
235 SLPolygon sl_polygon(sl_boundary, junction_overlap_.object_id);
236
237 for (size_t i = 0; i < path_boundary->size(); i++) {
238 auto& point = path_boundary->at(i);
239 if (point.s < sl_polygon.MinS() || point.s > sl_polygon.MaxS()) {
240 continue;
241 }
242 double l_min = sl_polygon.GetRightBoundaryByS(point.s);
243 double l_max = sl_polygon.GetLeftBoundaryByS(point.s);
244 l_min = std::max<double>(l_min, -config_.max_lateral_distance());
245 l_max = std::min<double>(l_max, config_.max_lateral_distance());
246 if (point.l_lower.l > l_min) {
247 point.l_lower.l = l_min;
248 point.l_lower.type = BoundType::ROAD;
249 }
250 if (point.l_upper.l < l_max) {
251 point.l_upper.l = l_max;
252 point.l_upper.type = BoundType::ROAD;
253 }
254 }
255 return true;
256}
257
258bool ReversePath::InitPathBoundary(
259 PathBoundary* const path_bound,
260 SLState init_sl_state,
261 double& reference_line_backward_length) {
262 // Sanity checks.
263 CHECK_NOTNULL(path_bound);
264 path_bound->clear();
265 path_bound->set_delta_s(-0.1);
266 double delta_s = path_bound->delta_s();
267 double end_s = init_sl_state.first[0] - std::min(config_.max_s_distance(), reference_line_backward_length);
268 for (double curr_s = init_sl_state.first[0]; curr_s > end_s; curr_s += delta_s) {
269 path_bound->emplace_back(curr_s, -config_.max_lateral_distance(), config_.max_lateral_distance());
270 }
271 // Return.
272 if (path_bound->empty()) {
273 AERROR << "Empty path boundary in InitPathBoundary";
274 return false;
275 }
276 return true;
277}
278
279} // namespace planning
280} // 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 const HDMap * BaseMapPtr()
const std::vector< double > & accumulated_s() const
Definition path.h:289
Frame holds all data for one planning cycle.
Definition frame.h:62
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
void RecordDebugInfo(const PathBound &path_boundaries, const std::string &debug_name, ReferenceLineInfo *const reference_line_info)
add path_boundary debug info for PnC monitor
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.
int GetJunction(const double s, hdmap::PathOverlap *junction_overlap) const
const ReferenceLine & reference_line() const
const hdmap::Path & GetMapPath() const
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
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 AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
apollo::hdmap::Id MakeMapId(const std::string &id)
create a Map ID given a string.
Definition hdmap_util.h:85
std::pair< std::array< double, 3 >, std::array< double, 3 > > SLState
class register implement
Definition arena_queue.h:37
std::string object_id
Definition path.h:95
optional PiecewiseJerkPathConfig path_optimizer_config