23#include "modules/common_msgs/basic_msgs/pnc_point.pb.h"
35 const bool is_change_lane_path,
36 const std::vector<const Obstacle *> &obstacles,
42 reference_line_(&reference_line),
43 is_change_lane_path_(is_change_lane_path),
44 vehicle_param_(vehicle_param),
45 heuristic_speed_data_(heuristic_speed_data),
46 init_sl_point_(init_sl_point),
47 adc_sl_boundary_(adc_sl_boundary) {
48 const double total_time =
49 std::min(heuristic_speed_data_.
TotalTime(), FLAGS_prediction_total_time);
51 num_of_time_stamps_ =
static_cast<uint32_t
>(
52 std::floor(total_time / config.eval_time_interval()));
54 for (
const auto *ptr_obstacle : obstacles) {
55 if (ptr_obstacle->IsIgnore()) {
57 }
else if (ptr_obstacle->LongitudinalDecision().has_stop()) {
60 const auto &sl_boundary = ptr_obstacle->PerceptionSLBoundary();
62 const double adc_left_l =
64 const double adc_right_l =
67 if (adc_left_l + FLAGS_lateral_ignore_buffer < sl_boundary.start_l() ||
68 adc_right_l - FLAGS_lateral_ignore_buffer > sl_boundary.end_l()) {
72 bool is_bycycle_or_pedestrian =
73 (ptr_obstacle->Perception().type() ==
75 ptr_obstacle->Perception().type() ==
78 if (ptr_obstacle->IsVirtual()) {
81 }
else if (ptr_obstacle->IsStatic() || is_bycycle_or_pedestrian) {
82 static_obstacle_sl_boundaries_.push_back(std::move(sl_boundary));
84 std::vector<Box2d> box_by_time;
85 for (uint32_t t = 0; t <= num_of_time_stamps_; ++t) {
87 ptr_obstacle->GetPointAtTime(t * config.eval_time_interval());
89 Box2d obstacle_box = ptr_obstacle->GetBoundingBox(trajectory_point);
90 static constexpr double kBuff = 0.5;
91 Box2d expanded_obstacle_box =
93 obstacle_box.
length() + kBuff, obstacle_box.
width() + kBuff);
94 box_by_time.push_back(expanded_obstacle_box);
96 dynamic_obstacle_boxes_.push_back(std::move(box_by_time));
103 const double end_s,
const uint32_t curr_level,
const uint32_t total_level) {
105 double path_cost = 0.0;
106 std::function<double(
const double)> quasi_softmax = [
this](
const double x) {
107 const double l0 = this->config_.path_l_cost_param_l0();
108 const double b = this->config_.path_l_cost_param_b();
109 const double k = this->config_.path_l_cost_param_k();
110 return (b + std::exp(-k * (x - l0))) / (1.0 + std::exp(-k * (x - l0)));
113 for (
double curve_s = 0.0; curve_s < (end_s - start_s);
114 curve_s += config_.path_resolution()) {
115 const double l = curve.
Evaluate(0, curve_s);
117 path_cost += l * l * config_.path_l_cost() * quasi_softmax(std::fabs(l));
119 const double dl = std::fabs(curve.
Evaluate(1, curve_s));
120 if (IsOffRoad(curve_s + start_s, l, dl, is_change_lane_path_)) {
124 path_cost += dl * dl * config_.path_dl_cost();
126 const double ddl = std::fabs(curve.
Evaluate(2, curve_s));
127 path_cost += ddl * ddl * config_.path_ddl_cost();
129 path_cost *= config_.path_resolution();
131 if (curr_level == total_level) {
132 const double end_l = curve.
Evaluate(0, end_s - start_s);
134 std::sqrt(end_l - init_sl_point_.
l() / 2.0) * config_.path_end_l_cost();
140bool TrajectoryCost::IsOffRoad(
const double ref_s,
const double l,
142 const bool is_change_lane_path) {
143 static constexpr double kIgnoreDistance = 5.0;
144 if (ref_s - init_sl_point_.
s() < kIgnoreDistance) {
147 Vec2d rear_center(0.0, l);
151 (param.front_edge_to_center() - param.back_edge_to_center()) / 2.0,
152 (param.left_edge_to_center() - param.right_edge_to_center()) / 2.0);
154 Vec2d rear_center_to_center = vec_to_center.rotate(std::atan(dl));
155 Vec2d center = rear_center + rear_center_to_center;
156 Vec2d front_center = center + rear_center_to_center;
158 const double buffer = 0.1;
160 (param.left_edge_to_center() + param.right_edge_to_center()) / 2.0;
161 const double r_l = param.back_edge_to_center();
162 const double r = std::sqrt(r_w * r_w + r_l * r_l);
164 double left_width = 0.0;
165 double right_width = 0.0;
166 reference_line_->
GetLaneWidth(ref_s, &left_width, &right_width);
168 double left_bound = std::max(init_sl_point_.
l() + r + buffer, left_width);
169 double right_bound = std::min(init_sl_point_.
l() - r - buffer, -right_width);
170 if (rear_center.y() + r + buffer / 2.0 > left_bound ||
171 rear_center.y() - r - buffer / 2.0 < right_bound) {
174 if (front_center.y() + r + buffer / 2.0 > left_bound ||
175 front_center.y() - r - buffer / 2.0 < right_bound) {
182ComparableCost TrajectoryCost::CalculateStaticObstacleCost(
183 const QuinticPolynomialCurve1d &curve,
const double start_s,
184 const double end_s) {
185 ComparableCost obstacle_cost;
186 for (
double curr_s = start_s; curr_s <= end_s;
187 curr_s += config_.path_resolution()) {
188 const double curr_l = curve.Evaluate(0, curr_s - start_s);
189 for (
const auto &obs_sl_boundary : static_obstacle_sl_boundaries_) {
190 obstacle_cost += GetCostFromObsSL(curr_s, curr_l, obs_sl_boundary);
193 obstacle_cost.safety_cost *= config_.path_resolution();
194 return obstacle_cost;
197ComparableCost TrajectoryCost::CalculateDynamicObstacleCost(
198 const QuinticPolynomialCurve1d &curve,
const double start_s,
199 const double end_s)
const {
200 ComparableCost obstacle_cost;
201 if (dynamic_obstacle_boxes_.empty()) {
202 return obstacle_cost;
205 double time_stamp = 0.0;
206 for (
size_t index = 0; index < num_of_time_stamps_;
207 ++index, time_stamp += config_.eval_time_interval()) {
208 common::SpeedPoint speed_point;
210 double ref_s = speed_point.s() + init_sl_point_.
s();
211 if (ref_s < start_s) {
218 const double s = ref_s - start_s;
219 const double l = curve.Evaluate(0, s);
220 const double dl = curve.Evaluate(1, s);
223 const Box2d ego_box = GetBoxFromSLPoint(sl, dl);
224 for (
const auto &obstacle_trajectory : dynamic_obstacle_boxes_) {
226 GetCostBetweenObsBoxes(ego_box, obstacle_trajectory.at(index));
229 static constexpr double kDynamicObsWeight = 1e-6;
230 obstacle_cost.safety_cost *=
231 (config_.eval_time_interval() * kDynamicObsWeight);
232 return obstacle_cost;
235ComparableCost TrajectoryCost::GetCostFromObsSL(
236 const double adc_s,
const double adc_l,
const SLBoundary &obs_sl_boundary) {
237 const auto &vehicle_param =
238 common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param();
240 ComparableCost obstacle_cost;
241 if (obs_sl_boundary.start_l() * obs_sl_boundary.end_l() <= 0.0) {
242 return obstacle_cost;
245 const double adc_front_s = adc_s + vehicle_param.front_edge_to_center();
246 const double adc_end_s = adc_s - vehicle_param.back_edge_to_center();
247 const double adc_left_l = adc_l + vehicle_param.left_edge_to_center();
248 const double adc_right_l = adc_l - vehicle_param.right_edge_to_center();
250 if (adc_left_l + FLAGS_lateral_ignore_buffer < obs_sl_boundary.start_l() ||
251 adc_right_l - FLAGS_lateral_ignore_buffer > obs_sl_boundary.end_l()) {
252 return obstacle_cost;
255 bool no_overlap = ((adc_front_s < obs_sl_boundary.start_s() ||
256 adc_end_s > obs_sl_boundary.end_s()) ||
257 (adc_left_l + 0.1 < obs_sl_boundary.start_l() ||
258 adc_right_l - 0.1 > obs_sl_boundary.end_l()));
265 if (adc_front_s > obs_sl_boundary.end_s()) {
266 return obstacle_cost;
269 const double delta_l = std::fmax(adc_right_l - obs_sl_boundary.end_l(),
270 obs_sl_boundary.start_l() - adc_left_l);
277 static constexpr double kSafeDistance = 0.6;
278 if (delta_l < kSafeDistance) {
279 obstacle_cost.safety_cost +=
280 config_.obstacle_collision_cost() *
281 Sigmoid(config_.obstacle_collision_distance() - delta_l);
284 return obstacle_cost;
288ComparableCost TrajectoryCost::GetCostBetweenObsBoxes(
289 const Box2d &ego_box,
const Box2d &obstacle_box)
const {
290 ComparableCost obstacle_cost;
292 const double distance = obstacle_box.DistanceTo(ego_box);
293 if (distance > config_.obstacle_ignore_distance()) {
294 return obstacle_cost;
297 obstacle_cost.safety_cost +=
298 config_.obstacle_collision_cost() *
299 Sigmoid(config_.obstacle_collision_distance() - distance);
300 obstacle_cost.safety_cost +=
301 20.0 *
Sigmoid(config_.obstacle_risk_distance() - distance);
302 return obstacle_cost;
305Box2d TrajectoryCost::GetBoxFromSLPoint(
const common::SLPoint &sl,
306 const double dl)
const {
308 reference_line_->
SLToXY(sl, &xy_point);
312 const double one_minus_kappa_r_d = 1 - reference_point.
kappa() * sl.l();
313 const double delta_theta = std::atan2(dl, one_minus_kappa_r_d);
316 return Box2d(xy_point, theta, vehicle_param_.
length(),
317 vehicle_param_.
width());
322 const double start_s,
324 const uint32_t curr_level,
325 const uint32_t total_level) {
329 CalculatePathCost(curve, start_s, end_s, curr_level, total_level);
332 total_cost += CalculateStaticObstacleCost(curve, start_s, end_s);
335 total_cost += CalculateDynamicObstacleCost(curve, start_s, end_s);
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
Rectangular (undirected) bounding box in 2-D.
double width() const
Getter of the width
const Vec2d & center() const
Getter of the center of the box
double length() const
Getter of the length
double heading() const
Getter of the heading
static SLPoint ToSLPoint(const double s, const double l)
static const size_t OUT_OF_BOUNDARY
std::array< bool, 3 > cost_items
static const size_t HAS_COLLISION
double Evaluate(const std::uint32_t order, const double p) const override
ReferencePoint GetReferencePoint(const double s) const
bool SLToXY(const common::SLPoint &sl_point, common::math::Vec2d *const xy_point) const
bool GetLaneWidth(const double s, double *const lane_left_width, double *const lane_right_width) const
bool EvaluateByTime(const double time, common::SpeedPoint *const speed_point) const
ComparableCost Calculate(const QuinticPolynomialCurve1d &curve, const double start_s, const double end_s, const uint32_t curr_level, const uint32_t total_level)
Planning module main class.
double Sigmoid(const double x)
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
optional VehicleParam vehicle_param
optional double left_edge_to_center
optional double right_edge_to_center