dp_road_graph.cc 16.0 KB
Newer Older
Y
Yifei Jiang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/******************************************************************************
 * Copyright 2017 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 dp_road_graph.h
 **/

21 22 23
#include "modules/planning/optimizer/dp_poly_path/dp_road_graph.h"

#include <algorithm>
J
jiangyifei 已提交
24
#include <limits>
A
Aaron Xiao 已提交
25
#include <string>
26
#include <unordered_map>
J
jiangyifei 已提交
27
#include <utility>
Y
Yifei Jiang 已提交
28

29
#include "modules/common/proto/error_code.pb.h"
30
#include "modules/common/proto/pnc_point.pb.h"
31 32 33 34

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/log.h"
#include "modules/common/util/util.h"
Y
Yifei Jiang 已提交
35
#include "modules/planning/common/path/frenet_frame_path.h"
D
Dong Li 已提交
36
#include "modules/planning/common/planning_gflags.h"
Y
Yifei Jiang 已提交
37 38 39 40 41 42 43
#include "modules/planning/math/curve1d/quintic_polynomial_curve1d.h"
#include "modules/planning/math/double.h"
#include "modules/planning/optimizer/dp_poly_path/trajectory_cost.h"

namespace apollo {
namespace planning {

44 45
using apollo::common::ErrorCode;
using apollo::common::Status;
46
using IdDecisionList = std::vector<std::pair<std::string, ObjectDecisionType>>;
47
using ConstPathObstacleList = std::vector<const PathObstacle *>;
48

Y
Yajia Zhang 已提交
49
DPRoadGraph::DPRoadGraph(const DpPolyPathConfig &config,
50
                         const ReferenceLine &reference_line,
51
                         const SpeedData &speed_data)
52 53 54
    : config_(config),
      reference_line_(reference_line),
      speed_data_(speed_data) {}
Y
Yifei Jiang 已提交
55

56
bool DPRoadGraph::FindPathTunnel(const common::TrajectoryPoint &init_point,
D
Dong Li 已提交
57
                                 PathData *const path_data) {
Y
Yifei Jiang 已提交
58
  CHECK_NOTNULL(path_data);
59 60 61 62
  init_point_ = init_point;
  if (!reference_line_.get_point_in_frenet_frame(
          {init_point_.path_point().x(), init_point_.path_point().y()},
          &init_sl_point_)) {
63 64
    AERROR << "Fail to create init_sl_point from : "
           << init_point.DebugString();
D
Dong Li 已提交
65
    return false;
Y
Yifei Jiang 已提交
66
  }
Y
Yajia Zhang 已提交
67
  std::vector<DPRoadGraphNode> min_cost_path;
68
  if (!GenerateMinCostPath(&min_cost_path)) {
D
Dong Li 已提交
69 70
    AERROR << "Fail to generate graph!";
    return false;
Y
Yifei Jiang 已提交
71
  }
D
Dong Li 已提交
72
  std::vector<common::FrenetFramePoint> frenet_path;
Z
zhuweicheng 已提交
73 74
  double accumulated_s = init_sl_point_.s();
  const double path_resolution = config_.path_resolution();
Y
Yajia Zhang 已提交
75 76

  for (std::size_t i = 1; i < min_cost_path.size(); ++i) {
77 78
    const auto &prev_node = min_cost_path[i - 1];
    const auto &cur_node = min_cost_path[i];
Y
Yajia Zhang 已提交
79

80
    const double path_length = cur_node.sl_point.s() - prev_node.sl_point.s();
81
    double current_s = 0.0;
82
    const auto &curve = cur_node.min_cost_curve;
83 84 85 86
    while (Double::Compare(current_s, path_length) < 0.0) {
      const double l = curve.Evaluate(0, current_s);
      const double dl = curve.Evaluate(1, current_s);
      const double ddl = curve.Evaluate(2, current_s);
D
Dong Li 已提交
87
      common::FrenetFramePoint frenet_frame_point;
Y
Yifei Jiang 已提交
88 89 90 91
      frenet_frame_point.set_s(accumulated_s + current_s);
      frenet_frame_point.set_l(l);
      frenet_frame_point.set_dl(dl);
      frenet_frame_point.set_ddl(ddl);
92
      frenet_path.push_back(std::move(frenet_frame_point));
93
      current_s += path_resolution;
Y
Yifei Jiang 已提交
94
    }
95
    accumulated_s += path_length;
Y
Yifei Jiang 已提交
96
  }
97
  FrenetFramePath tunnel(frenet_path);
L
liyun 已提交
98

99
  path_data->set_reference_line(&reference_line_);
Y
Yifei Jiang 已提交
100
  path_data->set_frenet_path(tunnel);
D
Dong Li 已提交
101
  return true;
Y
Yifei Jiang 已提交
102 103
}

104 105
bool DPRoadGraph::GenerateMinCostPath(
    std::vector<DPRoadGraphNode> *min_cost_path) {
Y
Yajia Zhang 已提交
106 107
  CHECK(min_cost_path != nullptr);

Y
Yajia Zhang 已提交
108
  std::vector<std::vector<common::SLPoint>> path_waypoints;
109
  if (!SamplePathWaypoints(init_point_, &path_waypoints)) {
Y
Yajia Zhang 已提交
110
    AERROR << "Fail to sample path waypoints!";
111
    return false;
Y
Yifei Jiang 已提交
112
  }
D
Dong Li 已提交
113
  path_waypoints.insert(path_waypoints.begin(),
114
                        std::vector<common::SLPoint>{init_sl_point_});
Y
Yajia Zhang 已提交
115

Y
Yajia Zhang 已提交
116
  const auto &vehicle_config =
117
      common::VehicleConfigHelper::instance()->GetConfig();
Y
Yajia Zhang 已提交
118

119
  TrajectoryCost trajectory_cost(config_, reference_line_,
Y
Yajia Zhang 已提交
120
                                 vehicle_config.vehicle_param(), speed_data_);
Y
Yajia Zhang 已提交
121 122

  std::vector<std::vector<DPRoadGraphNode>> graph_nodes(path_waypoints.size());
123
  graph_nodes[0].emplace_back(init_sl_point_, nullptr, 0.0);
Y
Yajia Zhang 已提交
124 125 126 127

  for (std::size_t level = 1; level < path_waypoints.size(); ++level) {
    const auto &prev_dp_nodes = graph_nodes[level - 1];
    const auto &level_points = path_waypoints[level];
128
    for (std::size_t i = 0; i < level_points.size(); ++i) {
129
      const auto &cur_point = level_points[i];
130
      graph_nodes[level].emplace_back(cur_point, nullptr);
131
      auto &cur_node = graph_nodes[level].back();
132
      for (std::size_t j = 0; j < prev_dp_nodes.size(); ++j) {
133 134
        const auto &prev_dp_node = prev_dp_nodes[j];
        const auto &prev_sl_point = prev_dp_node.sl_point;
Y
Yajia Zhang 已提交
135 136 137
        QuinticPolynomialCurve1d curve(prev_sl_point.l(), 0.0, 0.0,
                                       cur_point.l(), 0.0, 0.0,
                                       cur_point.s() - prev_sl_point.s());
138 139 140
        const double cost =
            trajectory_cost.calculate(curve, prev_sl_point.s(), cur_point.s()) +
            prev_dp_node.min_cost;
Y
Yajia Zhang 已提交
141
        cur_node.UpdateCost(&prev_dp_node, curve, cost);
D
Dong Li 已提交
142 143 144
      }
    }
  }
Y
Yifei Jiang 已提交
145

146
  // find best path
Y
Yajia Zhang 已提交
147 148
  DPRoadGraphNode fake_head;
  const auto &last_dp_nodes = graph_nodes.back();
149 150
  for (std::size_t i = 0; i < last_dp_nodes.size(); ++i) {
    const auto &cur_dp_node = last_dp_nodes[i];
Y
Yajia Zhang 已提交
151
    fake_head.UpdateCost(&cur_dp_node, cur_dp_node.min_cost_curve,
D
Dong Li 已提交
152
                         cur_dp_node.min_cost);
Y
Yifei Jiang 已提交
153
  }
Y
Yajia Zhang 已提交
154

155 156 157 158 159 160
  const auto *min_cost_node = &fake_head;
  while (min_cost_node->min_cost_prev_node) {
    min_cost_node = min_cost_node->min_cost_prev_node;
    min_cost_path->push_back(*min_cost_node);
  }
  std::reverse(min_cost_path->begin(), min_cost_path->end());
Y
Yifei Jiang 已提交
161 162 163
  return true;
}

164
bool DPRoadGraph::ComputeObjectDecision(
165
    const PathData &path_data, const ConstPathObstacleList &path_obstacles,
166
    IdDecisionList *const decisions) {
167 168 169 170 171
  DCHECK_NOTNULL(decisions);
  if (!MakeStaticObstacleDecision(path_data, path_obstacles, decisions)) {
    AERROR << "Failed to make decisions for static obstacles";
    return false;
  }
172 173 174 175 176 177
  // TODO(all) enable this function call when nudge dynamic obstacle is
  // implemented.
  // if (!MakeDynamicObstcleDecision(path_data, path_obstacles, decisions)) {
  //   AERROR << "Failed to make decisions for dynamic obstacles";
  //   return false;
  // }
178 179
  return true;
}
L
liyun 已提交
180

181 182 183 184
bool DPRoadGraph::MakeStaticObstacleDecision(
    const PathData &path_data, const ConstPathObstacleList &path_obstacles,
    IdDecisionList *const decisions) {
  DCHECK_NOTNULL(decisions);
185 186
  std::vector<common::SLPoint> adc_sl_points;
  std::vector<common::math::Box2d> adc_bounding_box;
187 188 189 190 191 192 193 194 195
  const auto &vehicle_param =
      common::VehicleConfigHelper::instance()->GetConfig().vehicle_param();
  const double adc_length = vehicle_param.length();
  const double adc_width = vehicle_param.length();
  const double adc_max_edge_to_center_dist =
      std::hypot(std::max(vehicle_param.front_edge_to_center(),
                          vehicle_param.back_edge_to_center()),
                 std::max(vehicle_param.left_edge_to_center(),
                          vehicle_param.right_edge_to_center()));
196

Y
Yajia Zhang 已提交
197
  for (const common::PathPoint &path_point :
D
Dong Li 已提交
198
       path_data.discretized_path().points()) {
199
    adc_bounding_box.emplace_back(
200
        common::math::Vec2d{path_point.x(), path_point.y()}, path_point.theta(),
201 202
        adc_length, adc_width);
    common::SLPoint adc_sl;
203
    if (!reference_line_.get_point_in_frenet_frame(
204
            {path_point.x(), path_point.y()}, &adc_sl)) {
205
      AERROR << "get_point_in_Frenet_frame error for ego vehicle "
D
Dong Li 已提交
206
             << path_point.x() << " " << path_point.y();
207
      return false;
208
    } else {
209
      adc_sl_points.push_back(std::move(adc_sl));
210 211
    }
  }
D
Dong Li 已提交
212

213 214
  for (const auto *path_obstacle : path_obstacles) {
    const auto *obstacle = path_obstacle->Obstacle();
215 216 217
    if (!obstacle->IsStatic()) {
      continue;
    }
218
    bool ignore = true;
219
    const auto &static_obstacle_box = obstacle->PerceptionBoundingBox();
Y
Yajia Zhang 已提交
220

221
    const auto &sl_boundary = path_obstacle->sl_boundary();
222 223
    for (std::size_t j = 0; j < adc_sl_points.size(); ++j) {
      const auto &adc_sl = adc_sl_points[j];
224 225 226 227
      if (adc_sl.s() + adc_max_edge_to_center_dist < sl_boundary.start_s() ||
          adc_sl.s() - adc_max_edge_to_center_dist > sl_boundary.end_s()) {
        // no overlap in s direction
        continue;
228 229
      } else if (adc_sl.l() + adc_max_edge_to_center_dist +
                         FLAGS_static_decision_ignore_range <
230
                     sl_boundary.start_l() ||
231 232
                 adc_sl.l() - adc_max_edge_to_center_dist -
                         FLAGS_static_decision_ignore_range >
233 234
                     sl_boundary.end_l()) {
        // no overlap in l direction
235
        continue;
L
liyun 已提交
236
      } else {
237
        if (static_obstacle_box.HasOverlap(adc_bounding_box[j]) &&
238 239 240
            (sl_boundary.start_l() * sl_boundary.end_l() < 0.0 ||
             std::fabs(std::min(sl_boundary.start_l(), sl_boundary.end_l())) <
                 FLAGS_static_decision_stop_buffer)) {
241 242
          ObjectDecisionType object_stop;
          ObjectStop *object_stop_ptr = object_stop.mutable_stop();
T
Tao Jiaming 已提交
243
          object_stop_ptr->set_distance_s(FLAGS_stop_distance_obstacle);
244
          object_stop_ptr->set_reason_code(
D
Dong Li 已提交
245
              StopReasonCode::STOP_REASON_OBSTACLE);
246

247 248
          auto stop_ref_s =
              sl_boundary.start_s() - FLAGS_stop_distance_obstacle;
249 250 251 252
          auto stop_ref_point = reference_line_.get_reference_point(stop_ref_s);
          object_stop_ptr->mutable_stop_point()->set_x(stop_ref_point.x());
          object_stop_ptr->mutable_stop_point()->set_y(stop_ref_point.y());
          object_stop_ptr->set_stop_heading(stop_ref_point.heading());
253

254
          decisions->emplace_back(obstacle->Id(), object_stop);
255 256 257
          ignore = false;
          break;
        } else {
258 259 260
          if (sl_boundary.start_l() > adc_sl.l() &&
              sl_boundary.start_l() - adc_sl.l() <
                  FLAGS_static_decision_ignore_range) {
D
Dong Li 已提交
261
            // GO_RIGHT
262
            ObjectDecisionType object_nudge;
D
Dong Li 已提交
263
            ObjectNudge *object_nudge_ptr = object_nudge.mutable_nudge();
T
Tao Jiaming 已提交
264
            object_nudge_ptr->set_distance_l(FLAGS_nudge_distance_obstacle);
265
            object_nudge_ptr->set_type(ObjectNudge::RIGHT_NUDGE);
266
            decisions->emplace_back(obstacle->Id(), object_nudge);
267 268
            ignore = false;
            break;
269 270 271
          } else if (sl_boundary.end_l() < adc_sl.l() &&
                     adc_sl.l() - sl_boundary.end_l() <
                         FLAGS_static_decision_ignore_range) {
D
Dong Li 已提交
272
            // GO_LEFT
273
            ObjectDecisionType object_nudge;
D
Dong Li 已提交
274
            ObjectNudge *object_nudge_ptr = object_nudge.mutable_nudge();
T
Tao Jiaming 已提交
275
            object_nudge_ptr->set_distance_l(FLAGS_nudge_distance_obstacle);
276
            object_nudge_ptr->set_type(ObjectNudge::LEFT_NUDGE);
277
            decisions->emplace_back(obstacle->Id(), object_nudge);
278 279 280 281
            ignore = false;
            break;
          }
        }
L
liyun 已提交
282
      }
283 284
    }
    if (ignore) {
D
Dong Li 已提交
285
      // IGNORE
D
Dong Li 已提交
286
      ObjectDecisionType object_ignore;
287
      object_ignore.mutable_ignore();
288
      decisions->emplace_back(obstacle->Id(), object_ignore);
L
liyun 已提交
289 290
    }
  }
291 292
  return true;
}
L
liyun 已提交
293

294 295 296
bool DPRoadGraph::MakeDynamicObstcleDecision(
    const PathData &path_data, const ConstPathObstacleList &path_obstacles,
    IdDecisionList *decisions) {
L
liyun 已提交
297
  // Compute dynamic obstacle decision
298
  const double interval = config_.eval_time_interval();
L
liyun 已提交
299
  const double total_time =
300 301 302 303 304 305 306
      std::min(speed_data_.total_time(), FLAGS_prediction_total_time);
  std::size_t evaluate_time_slots =
      static_cast<std::size_t>(std::floor(total_time / interval));
  // list of Box2d for adc given speed profile
  std::vector<common::math::Box2d> adc_by_time;
  if (!ComputeBoundingBoxesForAdc(path_data.frenet_frame_path(),
                                  evaluate_time_slots, &adc_by_time)) {
307
    AERROR << "fill adc_by_time error";
308
    return false;
309 310
  }

311 312
  for (const auto *path_obstacle : path_obstacles) {
    const auto *obstacle = path_obstacle->Obstacle();
313 314 315
    if (obstacle->IsStatic()) {
      continue;
    }
316 317 318
    double timestamp = 0.0;
    for (std::size_t k = 0; k < evaluate_time_slots;
         ++k, timestamp += interval) {
319 320 321
      // TODO(all) make nudge decision for dynamic obstacles.
      // const auto obstacle_by_time =
      //     obstacle->GetBoundingBox(obstacle->GetPointAtTime(timestamp));
322 323 324 325 326
    }
  }
  return true;
}

327
bool DPRoadGraph::ComputeBoundingBoxesForAdc(
328 329
    const FrenetFramePath &frenet_frame_path,
    const std::size_t evaluate_time_slots,
330 331
    std::vector<common::math::Box2d> *adc_boxes) {
  CHECK(adc_boxes != nullptr);
Y
Yajia Zhang 已提交
332

333
  const auto &vehicle_config =
D
Dong Li 已提交
334
      common::VehicleConfigHelper::instance()->GetConfig();
335 336
  double adc_length = vehicle_config.vehicle_param().length();
  double adc_width = vehicle_config.vehicle_param().length();
337

338 339 340 341
  double time_stamp = 0.0;
  const double interval = config_.eval_time_interval();
  for (std::size_t i = 0; i < evaluate_time_slots;
       ++i, time_stamp += interval) {
342
    common::SpeedPoint speed_point;
343
    if (!speed_data_.get_speed_point_with_time(time_stamp, &speed_point)) {
D
Dong Li 已提交
344
      AINFO << "get_speed_point_with_time for time_stamp[" << time_stamp << "]";
345
      return false;
L
liyun 已提交
346
    }
347

D
Dong Li 已提交
348 349
    const common::FrenetFramePoint &interpolated_frenet_point =
        frenet_frame_path.interpolate(speed_point.s());
350 351 352 353
    double s = interpolated_frenet_point.s();
    double l = interpolated_frenet_point.l();
    double dl = interpolated_frenet_point.dl();

354
    common::math::Vec2d adc_position_cartesian;
355 356 357
    common::SLPoint sl_point;
    sl_point.set_s(s);
    sl_point.set_l(l);
358
    reference_line_.get_point_in_cartesian_frame(sl_point,
359
                                                 &adc_position_cartesian);
360

361
    ReferencePoint reference_point = reference_line_.get_reference_point(s);
362 363 364 365

    double one_minus_kappa_r_d = 1 - reference_point.kappa() * l;
    double delta_theta = std::atan2(dl, one_minus_kappa_r_d);
    double theta = ::apollo::common::math::NormalizeAngle(
D
Dong Li 已提交
366
        delta_theta + reference_point.heading());
367

368 369
    adc_boxes->emplace_back(adc_position_cartesian, theta, adc_length,
                            adc_width);
L
liyun 已提交
370 371 372 373
  }
  return true;
}

Y
Yajia Zhang 已提交
374
bool DPRoadGraph::SamplePathWaypoints(
375 376
    const common::TrajectoryPoint &init_point,
    std::vector<std::vector<common::SLPoint>> *const points) {
Y
Yajia Zhang 已提交
377 378 379
  CHECK(points != nullptr);

  common::math::Vec2d init_cartesian_point(init_point.path_point().x(),
D
Dong Li 已提交
380
                                           init_point.path_point().y());
Y
Yajia Zhang 已提交
381
  common::SLPoint init_sl_point;
382 383
  if (!reference_line_.get_point_in_frenet_frame(init_cartesian_point,
                                                 &init_sl_point)) {
384
    AERROR << "Failed to get sl point from point "
Y
Yajia Zhang 已提交
385
           << init_cartesian_point.DebugString();
386 387
    return false;
  }
Y
Yajia Zhang 已提交
388

389
  const double reference_line_length =
390
      reference_line_.map_path().accumulated_s().back();
Y
Yajia Zhang 已提交
391

392 393 394 395 396
  double level_distance =
      std::fmax(config_.step_length_min(),
                std::fmin(init_point.v(), config_.step_length_max()));

  double accumulated_s = init_sl_point.s();
Y
Yajia Zhang 已提交
397
  for (std::size_t i = 0;
398 399 400 401 402 403 404 405
       i < config_.sample_level() && accumulated_s < reference_line_length;
       ++i) {
    std::vector<common::SLPoint> level_points;
    accumulated_s += level_distance;
    double s = std::fmin(accumulated_s, reference_line_length);

    int32_t num =
        static_cast<int32_t>(config_.sample_points_num_each_level() / 2);
Y
Yajia Zhang 已提交
406

407 408 409
    for (int32_t j = -num; j < num + 1; ++j) {
      double l = config_.lateral_sample_offset() * j;
      auto sl = common::util::MakeSLPoint(s, l);
410
      if (reference_line_.is_on_road(sl)) {
411 412 413 414 415 416 417 418 419 420
        level_points.push_back(sl);
      }
    }
    if (!level_points.empty()) {
      points->push_back(level_points);
    }
  }
  return true;
}

Y
Yifei Jiang 已提交
421 422
}  // namespace planning
}  // namespace apollo