speed_profile_generator.cc 6.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file speed_profile_generator.cc
 **/

#include "modules/planning/common/speed_profile_generator.h"

#include <algorithm>
24
#include <limits>
25
#include <memory>
26

G
GoLancer 已提交
27
#include "cyber/common/log.h"
28
#include "modules/planning/common/ego_info.h"
29 30
#include "modules/planning/common/frame.h"
#include "modules/planning/common/planning_gflags.h"
H
Hongyi 已提交
31
#include "modules/planning/math/piecewise_jerk/piecewise_jerk_speed_problem.h"
32 33 34 35

namespace apollo {
namespace planning {

J
jmtao 已提交
36 37 38
using apollo::common::SLPoint;
using apollo::common::SpeedPoint;
using apollo::common::TrajectoryPoint;
39
using apollo::common::math::Vec2d;
40

41 42
SpeedData SpeedProfileGenerator::GenerateFallbackSpeed(
    const double stop_distance) {
43
  AERROR << "Fallback using piecewise jerk speed!";
44 45
  const double init_v = EgoInfo::Instance()->start_point().v();
  const double init_a = EgoInfo::Instance()->start_point().a();
46
  AWARN << "init_v = " << init_v << ", init_a = " << init_a;
47
  const auto& veh_param =
A
Aaron Xiao 已提交
48
      common::VehicleConfigHelper::GetConfig().vehicle_param();
49

50 51 52 53 54 55 56 57 58
  // if already stopped
  if (init_v <= 0.0 && init_a <= 0.0) {
    AWARN << "Already stopped! Nothing to do in GenerateFallbackSpeed()";
    SpeedData speed_data;
    speed_data.AppendSpeedPoint(0.0, 0.0, 0.0, 0.0, 0.0);
    FillEnoughSpeedPoints(&speed_data);
    return speed_data;
  }

59
  std::array<double, 3> init_s = {0.0, init_v, init_a};
60 61

  // TODO(all): dt is too small;
62 63
  double delta_t = FLAGS_fallback_time_unit;
  double total_time = FLAGS_fallback_total_time;
H
Hongyi 已提交
64
  const size_t num_of_knots = static_cast<size_t>(total_time / delta_t) + 1;
65

A
Aaron Xiao 已提交
66 67
  PiecewiseJerkSpeedProblem piecewise_jerk_problem(num_of_knots, delta_t,
                                                   init_s);
68

69
  std::vector<double> end_state_ref(num_of_knots, stop_distance);
70
  piecewise_jerk_problem.set_x_ref(1.0, end_state_ref);
71

72
  piecewise_jerk_problem.set_scale_factor({1.0, 10.0, 100.0});
73

74 75
  piecewise_jerk_problem.set_x_bounds(0.0, std::fmax(stop_distance, 100.0));
  piecewise_jerk_problem.set_dx_bounds(
A
Aaron Xiao 已提交
76
      0.0, std::fmax(FLAGS_planning_upper_speed_limit, init_v));
77
  piecewise_jerk_problem.set_ddx_bounds(veh_param.max_deceleration(),
78
                                        veh_param.max_acceleration());
79 80
  piecewise_jerk_problem.set_dddx_bound(FLAGS_longitudinal_jerk_lower_bound,
                                        FLAGS_longitudinal_jerk_upper_bound);
81 82

  // Solve the problem
83
  if (!piecewise_jerk_problem.Optimize()) {
84
    AERROR << "Piecewise jerk fallback speed optimizer failed!";
H
Hongyi 已提交
85
    return GenerateStopProfile(init_v, init_a);
86 87 88
  }

  // Extract output
89 90 91
  const std::vector<double>& s = piecewise_jerk_problem.opt_x();
  const std::vector<double>& ds = piecewise_jerk_problem.opt_dx();
  const std::vector<double>& dds = piecewise_jerk_problem.opt_ddx();
92

93
  for (size_t i = 0; i < num_of_knots; ++i) {
94 95
    ADEBUG << "For[" << delta_t * static_cast<double>(i) << "], s = " << s[i]
           << ", v = " << ds[i] << ", a = " << dds[i];
96 97
  }

98
  SpeedData speed_data;
99
  speed_data.AppendSpeedPoint(s[0], 0.0, ds[0], dds[0], 0.0);
100
  for (size_t i = 1; i < num_of_knots; ++i) {
H
Hongyi 已提交
101
    // Avoid the very last points when already stopped
A
Aaron Xiao 已提交
102
    if (s[i] - s[i - 1] <= 0.0 || ds[i] <= 0.0) {
H
Hongyi 已提交
103 104
      break;
    }
A
Aaron Xiao 已提交
105 106
    speed_data.AppendSpeedPoint(s[i], delta_t * static_cast<double>(i), ds[i],
                                dds[i], (dds[i] - dds[i - 1]) / delta_t);
107
  }
108
  FillEnoughSpeedPoints(&speed_data);
109 110 111
  return speed_data;
}

112
void SpeedProfileGenerator::FillEnoughSpeedPoints(SpeedData* const speed_data) {
113
  const SpeedPoint& last_point = speed_data->back();
114 115 116 117
  if (last_point.t() >= FLAGS_fallback_total_time) {
    return;
  }
  for (double t = last_point.t() + FLAGS_fallback_time_unit;
A
Aaron Xiao 已提交
118
       t < FLAGS_fallback_total_time; t += FLAGS_fallback_time_unit) {
119 120 121 122
    speed_data->AppendSpeedPoint(last_point.s(), t, 0.0, 0.0, 0.0);
  }
}

123 124 125 126 127 128 129 130 131 132 133 134 135
SpeedData SpeedProfileGenerator::GenerateStopProfile(const double init_speed,
                                                     const double init_acc) {
  AERROR << "Slowing down the car within a constant deceleration with fallback "
            "stopping profile.";
  SpeedData speed_data;

  const double max_t = FLAGS_fallback_total_time;
  const double unit_t = FLAGS_fallback_time_unit;

  double pre_s = 0.0;
  double pre_v = init_speed;
  double acc = FLAGS_slowdown_profile_deceleration;

136 137
  speed_data.AppendSpeedPoint(0.0, 0.0, init_speed, init_acc, 0.0);
  for (double t = unit_t; t < max_t; t += unit_t) {
138 139 140 141 142 143 144 145 146
    double s = 0.0;
    double v = 0.0;
    s = std::fmax(pre_s,
                  pre_s + 0.5 * (pre_v + (pre_v + unit_t * acc)) * unit_t);
    v = std::fmax(0.0, pre_v + unit_t * acc);
    speed_data.AppendSpeedPoint(s, t, v, acc, 0.0);
    pre_s = s;
    pre_v = v;
  }
147
  FillEnoughSpeedPoints(&speed_data);
148 149 150
  return speed_data;
}

151 152
SpeedData SpeedProfileGenerator::GenerateFixedDistanceCreepProfile(
    const double distance, const double max_speed) {
A
Aaron Xiao 已提交
153 154
  static constexpr double kConstDeceleration = -0.8;  // (~3sec to fully stop)
  static constexpr double kProceedingSpeed = 2.23;    // (5mph proceeding speed)
155
  const double proceeding_speed = std::fmin(max_speed, kProceedingSpeed);
156 157 158 159 160 161 162 163 164
  const double distance_to_start_deceleration =
      proceeding_speed * proceeding_speed / kConstDeceleration / 2;
  bool is_const_deceleration_mode = distance < distance_to_start_deceleration;

  double a = kConstDeceleration;
  double t = 0.0;
  double s = 0.0;
  double v = proceeding_speed;

A
Aaron Xiao 已提交
165
  static constexpr double kDeltaT = 0.1;
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

  SpeedData speed_data;
  while (s < distance && v > 0) {
    if (is_const_deceleration_mode) {
      speed_data.AppendSpeedPoint(s, t, v, a, 0.0);
      t += kDeltaT;
      double v_new = std::max(0.0, v + a * t);
      s += kDeltaT * (v + v_new) / 2;
      v = v_new;
    } else {
      speed_data.AppendSpeedPoint(s, t, v, 0.0, 0.0);
      t += kDeltaT;
      s += kDeltaT * v;
      if (distance - s < distance_to_start_deceleration)
        is_const_deceleration_mode = true;
    }
  }

  return speed_data;
}

187 188
}  // namespace planning
}  // namespace apollo