Apollo 10.0
自动驾驶开放平台
piecewise_jerk_speed_optimizer.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
21#include <algorithm>
22
23#include <string>
24#include <utility>
25#include <vector>
26#include "modules/common_msgs/basic_msgs/pnc_point.pb.h"
34
35namespace apollo {
36namespace planning {
37
43
45 const std::string& config_dir, const std::string& name,
46 const std::shared_ptr<DependencyInjector>& injector) {
47 if (!SpeedOptimizer::Init(config_dir, name, injector)) {
48 return false;
49 }
50 // Load the config_ this task.
51 return SpeedOptimizer::LoadConfig<PiecewiseJerkSpeedOptimizerConfig>(
52 &config_);
53}
54
55Status PiecewiseJerkSpeedOptimizer::Process(const PathData& path_data,
56 const TrajectoryPoint& init_point,
57 SpeedData* const speed_data) {
59 return Status::OK();
60 }
61
62 ACHECK(speed_data != nullptr);
63 SpeedData reference_speed_data = *speed_data;
64
65 if (path_data.discretized_path().empty()) {
66 const std::string msg = "Empty path data";
67 AERROR << msg;
68 return Status(ErrorCode::PLANNING_ERROR, msg);
69 }
70 StGraphData& st_graph_data = *reference_line_info_->mutable_st_graph_data();
71 PrintCurves print_debug;
72 const auto& veh_param =
74
75 std::array<double, 3> init_s = {0.0, st_graph_data.init_point().v(),
76 st_graph_data.init_point().a()};
77 const auto& vehicle_state = frame_->vehicle_state();
78 if (vehicle_state.gear() == canbus::Chassis::GEAR_REVERSE) {
79 init_s[1] = std::max(-init_s[1], 0.0);
80 init_s[2] = -init_s[2];
81 AINFO << "transfer reverse speed" << init_s[0] << "," << init_s[1] << ","
82 << init_s[2];
83 }
84 double delta_t = 0.1;
85 double total_length = st_graph_data.path_length();
86 double total_time = st_graph_data.total_time_by_conf();
87 int num_of_knots = static_cast<int>(total_time / delta_t) + 1;
88 print_debug.AddPoint("optimize_st_curve", 0, init_s[0]);
89 print_debug.AddPoint("optimize_vt_curve", 0, init_s[1]);
90 print_debug.AddPoint("optimize_at_curve", 0, init_s[2]);
91 // Update STBoundary
92 const double kEpsilon = 0.01;
93 std::vector<std::pair<double, double>> s_bounds;
94 for (int i = 0; i < num_of_knots; ++i) {
95 double curr_t = i * delta_t;
96 double s_lower_bound = 0.0;
97 double s_upper_bound = total_length;
98 for (const STBoundary* boundary : st_graph_data.st_boundaries()) {
99 double s_lower = 0.0;
100 double s_upper = 0.0;
101 if (!boundary->GetUnblockSRange(curr_t, &s_upper, &s_lower)) {
102 continue;
103 }
104 switch (boundary->boundary_type()) {
107 s_upper_bound = std::fmin(s_upper_bound, s_upper);
108 break;
110 // TODO(Hongyi): unify follow buffer on decision side
111 s_upper_bound = std::fmin(s_upper_bound, s_upper);
112 break;
114 s_lower_bound = std::fmax(s_lower_bound, s_lower);
115 break;
116 default:
117 break;
118 }
119 }
120 s_upper_bound = std::fmax(s_upper_bound, s_lower_bound + kEpsilon);
121 print_debug.AddPoint("st_bounds_lower", curr_t, s_lower_bound);
122 print_debug.AddPoint("st_bounds_upper", curr_t, s_upper_bound);
123 if (s_lower_bound > s_upper_bound) {
124 const std::string msg =
125 "s_lower_bound larger than s_upper_bound on STGraph";
126 AERROR << msg;
127 speed_data->clear();
128 print_debug.PrintToLog();
129 return Status(ErrorCode::PLANNING_ERROR, msg);
130 }
131
132 s_bounds.emplace_back(s_lower_bound, s_upper_bound);
133 }
134
135 // Update SpeedBoundary and ref_s
136 std::vector<double> x_ref(num_of_knots, total_length);
137 std::vector<double> dx_ref(num_of_knots,
139 std::vector<double> dx_ref_weight(num_of_knots, config_.ref_v_weight());
140 std::vector<double> penalty_dx;
141 std::vector<std::pair<double, double>> s_dot_bounds;
142 const SpeedLimit& speed_limit = st_graph_data.speed_limit();
143 for (int i = 0; i < num_of_knots; ++i) {
144 double curr_t = i * delta_t;
145 // get path_s
146 SpeedPoint sp;
147 reference_speed_data.EvaluateByTime(curr_t, &sp);
148 const double path_s = sp.s();
149 x_ref[i] = path_s;
150 // get curvature
151 PathPoint path_point = path_data.GetPathPointWithPathS(path_s);
152 penalty_dx.push_back(std::fabs(path_point.kappa()) *
153 config_.kappa_penalty_weight());
154 // get v_upper_bound
155 const double v_lower_bound = 0.0;
156 double v_upper_bound = FLAGS_planning_upper_speed_limit;
157 v_upper_bound =
158 std::fmin(speed_limit.GetSpeedLimitByS(path_s), v_upper_bound);
159 dx_ref[i] = std::fmin(v_upper_bound, dx_ref[i]);
160 s_dot_bounds.emplace_back(v_lower_bound, std::fmax(v_upper_bound, 0.0));
161 print_debug.AddPoint("st_reference_line", curr_t, x_ref[i]);
162 print_debug.AddPoint("st_penalty_dx", curr_t, penalty_dx.back());
163 print_debug.AddPoint("vt_reference_line", curr_t, dx_ref[i]);
164 print_debug.AddPoint("vt_weighting", curr_t, dx_ref_weight[i]);
165 print_debug.AddPoint("vt_boundary_lower", curr_t, v_lower_bound);
166 print_debug.AddPoint("sv_boundary_lower", path_s, v_lower_bound);
167 print_debug.AddPoint("sk_curve", path_s, path_point.kappa());
168 print_debug.AddPoint("vt_boundary_upper", curr_t, v_upper_bound);
169 print_debug.AddPoint("sv_boundary_upper", path_s, v_upper_bound);
170 }
171 AdjustInitStatus(s_dot_bounds, delta_t, init_s);
172 PiecewiseJerkSpeedProblem piecewise_jerk_problem(num_of_knots, delta_t,
173 init_s);
174 piecewise_jerk_problem.set_weight_ddx(config_.acc_weight());
175 piecewise_jerk_problem.set_weight_dddx(config_.jerk_weight());
176 piecewise_jerk_problem.set_scale_factor({1.0, 10.0, 100.0});
177 piecewise_jerk_problem.set_x_bounds(0.0, total_length);
178 piecewise_jerk_problem.set_ddx_bounds(veh_param.max_deceleration(),
179 veh_param.max_acceleration());
180 piecewise_jerk_problem.set_dddx_bound(FLAGS_longitudinal_jerk_lower_bound,
181 FLAGS_longitudinal_jerk_upper_bound);
182 piecewise_jerk_problem.set_x_bounds(std::move(s_bounds));
183 piecewise_jerk_problem.set_dx_ref(dx_ref_weight, dx_ref);
184 piecewise_jerk_problem.set_x_ref(config_.ref_s_weight(), std::move(x_ref));
185 piecewise_jerk_problem.set_penalty_dx(penalty_dx);
186 piecewise_jerk_problem.set_dx_bounds(std::move(s_dot_bounds));
187
188 // Solve the problem
189 if (!piecewise_jerk_problem.Optimize()) {
190 const std::string msg = "Piecewise jerk speed optimizer failed!";
191 AERROR << msg << ".try to fallback.";
192 piecewise_jerk_problem.set_dx_bounds(
193 0.0, std::fmax(FLAGS_planning_upper_speed_limit,
194 st_graph_data.init_point().v()));
195 if (!FLAGS_speed_optimize_fail_relax_velocity_constraint ||
196 !piecewise_jerk_problem.Optimize()) {
197 speed_data->clear();
198 print_debug.AddPoint("optimize_st_curve", 0, init_s[0]);
199 print_debug.AddPoint("optimize_vt_curve", 0, init_s[1]);
200 print_debug.AddPoint("optimize_at_curve", 0, init_s[2]);
201 AINFO << "jerk_bound: " << FLAGS_longitudinal_jerk_lower_bound << ","
202 << FLAGS_longitudinal_jerk_upper_bound;
203 AINFO << "acc bound: " << veh_param.max_deceleration() << ","
204 << veh_param.max_acceleration();
205 print_debug.PrintToLog();
206 return Status(ErrorCode::PLANNING_ERROR, msg);
207 }
208 }
209
210 // Extract output
211 const std::vector<double>& s = piecewise_jerk_problem.opt_x();
212 const std::vector<double>& ds = piecewise_jerk_problem.opt_dx();
213 const std::vector<double>& dds = piecewise_jerk_problem.opt_ddx();
214 for (int i = 0; i < num_of_knots; ++i) {
215 ADEBUG << "For t[" << i * delta_t << "], s = " << s[i] << ", v = " << ds[i]
216 << ", a = " << dds[i];
217 print_debug.AddPoint("optimize_st_curve", i * delta_t, s[i]);
218 print_debug.AddPoint("optimize_vt_curve", i * delta_t, ds[i]);
219 print_debug.AddPoint("optimize_at_curve", i * delta_t, dds[i]);
220 }
221 speed_data->clear();
222 speed_data->AppendSpeedPoint(s[0], 0.0, ds[0], dds[0], 0.0);
223 for (int i = 1; i < num_of_knots; ++i) {
224 // Avoid the very last points when already stopped
225 if (ds[i] <= 0.0) {
226 break;
227 }
228 speed_data->AppendSpeedPoint(s[i], delta_t * i, ds[i], dds[i],
229 (dds[i] - dds[i - 1]) / delta_t);
230 }
232 RecordDebugInfo(*speed_data, st_graph_data.mutable_st_graph_debug());
233 print_debug.PrintToLog();
234 return Status::OK();
235}
236void PiecewiseJerkSpeedOptimizer::AdjustInitStatus(
237 const std::vector<std::pair<double, double>> s_dot_bound, double delta_t,
238 std::array<double, 3>& init_s) {
239 double v_min = init_s[1];
240 double v_max = init_s[1];
241 double a_min = init_s[2];
242 double a_max = init_s[2];
243 double last_a_min = 0;
244 double last_a_max = 0;
245 for (size_t i = 1; i < s_dot_bound.size(); i++) {
246 last_a_min = a_min;
247 last_a_max = a_max;
248 a_min = a_min + delta_t * FLAGS_longitudinal_jerk_upper_bound;
249 a_max = a_max + delta_t * FLAGS_longitudinal_jerk_lower_bound;
250 v_min = v_min + 0.5 * delta_t * (a_min + last_a_min);
251 v_max = v_max + 0.5 * delta_t * (a_max + last_a_max);
252 if (v_min < s_dot_bound[i].first || v_max > s_dot_bound[i].second) {
253 AWARN << "init state not appropriate in" << i << "," << v_min << ","
254 << v_max << "adjust acc to 0 in init state " << init_s[0] << ","
255 << init_s[1] << "," << init_s[2];
256 init_s[2] = 0;
257 return;
258 }
259 }
260}
261} // namespace planning
262} // 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
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
const common::VehicleState & vehicle_state() const
Definition frame.cc:83
common::PathPoint GetPathPointWithPathS(const double s) const
Definition path_data.cc:112
const DiscretizedPath & discretized_path() const
Definition path_data.cc:90
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
void AppendSpeedPoint(const double s, const double time, const double v, const double a, const double da)
Definition speed_data.cc:48
void RecordDebugInfo(const SpeedData &speed_data)
static void FillEnoughSpeedPoints(SpeedData *const speed_data)
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 ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
class register implement
Definition arena_queue.h:37
: data with map info and obstacle info
optional VehicleParam vehicle_param