26#include "modules/common_msgs/basic_msgs/pnc_point.pb.h"
45 const std::string& config_dir,
const std::string& name,
46 const std::shared_ptr<DependencyInjector>& injector) {
51 return SpeedOptimizer::LoadConfig<PiecewiseJerkSpeedOptimizerConfig>(
55Status PiecewiseJerkSpeedOptimizer::Process(
const PathData& path_data,
62 ACHECK(speed_data !=
nullptr);
63 SpeedData reference_speed_data = *speed_data;
66 const std::string msg =
"Empty path data";
68 return Status(ErrorCode::PLANNING_ERROR, msg);
71 PrintCurves print_debug;
72 const auto& veh_param =
75 std::array<double, 3> init_s = {0.0, st_graph_data.init_point().v(),
76 st_graph_data.init_point().a()};
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] <<
","
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]);
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()) {
100 double s_upper = 0.0;
101 if (!boundary->GetUnblockSRange(curr_t, &s_upper, &s_lower)) {
104 switch (boundary->boundary_type()) {
107 s_upper_bound = std::fmin(s_upper_bound, s_upper);
111 s_upper_bound = std::fmin(s_upper_bound, s_upper);
114 s_lower_bound = std::fmax(s_lower_bound, s_lower);
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";
128 print_debug.PrintToLog();
129 return Status(ErrorCode::PLANNING_ERROR, msg);
132 s_bounds.emplace_back(s_lower_bound, s_upper_bound);
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;
147 reference_speed_data.EvaluateByTime(curr_t, &sp);
148 const double path_s = sp.s();
152 penalty_dx.push_back(std::fabs(path_point.kappa()) *
155 const double v_lower_bound = 0.0;
156 double v_upper_bound = FLAGS_planning_upper_speed_limit;
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);
171 AdjustInitStatus(s_dot_bounds, delta_t, init_s);
172 PiecewiseJerkSpeedProblem piecewise_jerk_problem(num_of_knots, delta_t,
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));
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()) {
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);
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]);
223 for (
int i = 1; i < num_of_knots; ++i) {
229 (dds[i] - dds[i - 1]) / delta_t);
233 print_debug.PrintToLog();
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++) {
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];
A general class to denote the return status of an API call.
static Status OK()
generate a success status.
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
const common::VehicleState & vehicle_state() const
common::PathPoint GetPathPointWithPathS(const double s) const
const DiscretizedPath & discretized_path() const
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
StGraphData * mutable_st_graph_data()
double GetCruiseSpeed() const
bool ReachedDestination() const
void AppendSpeedPoint(const double s, const double time, const double v, const double a, const double da)
void RecordDebugInfo(const SpeedData &speed_data)
static void FillEnoughSpeedPoints(SpeedData *const speed_data)
ReferenceLineInfo * reference_line_info_
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
Planning module main class.
: data with map info and obstacle info
optional VehicleParam vehicle_param
optional double ref_v_weight
optional double ref_s_weight
optional double jerk_weight
optional double kappa_penalty_weight
optional double acc_weight