dp_road_graph.cc 17.7 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
#include "modules/planning/math/curve1d/quintic_polynomial_curve1d.h"
#include "modules/planning/math/double.h"
39
#include "modules/planning/math/sl_analytic_transformation.h"
Y
Yifei Jiang 已提交
40 41 42 43 44
#include "modules/planning/optimizer/dp_poly_path/trajectory_cost.h"

namespace apollo {
namespace planning {

45 46 47
using apollo::common::ErrorCode;
using apollo::common::Status;

Y
Yajia Zhang 已提交
48
DPRoadGraph::DPRoadGraph(const DpPolyPathConfig &config,
Y
Yajia Zhang 已提交
49
                         const common::TrajectoryPoint &init_point,
50
                         const SpeedData &speed_data)
Z
zhuweicheng 已提交
51
    : config_(config), init_point_(init_point), speed_data_(speed_data) {}
Y
Yifei Jiang 已提交
52

Y
Yajia Zhang 已提交
53
bool DPRoadGraph::FindPathTunnel(const ReferenceLine &reference_line,
D
Dong Li 已提交
54
                                 PathData *const path_data) {
Y
Yifei Jiang 已提交
55
  CHECK_NOTNULL(path_data);
Y
Yajia Zhang 已提交
56
  if (!Init(reference_line)) {
D
Dong Li 已提交
57 58
    AERROR << "Fail to init dp road graph!";
    return false;
Y
Yifei Jiang 已提交
59
  }
Y
Yajia Zhang 已提交
60
  std::vector<DPRoadGraphNode> min_cost_path;
D
Dong Li 已提交
61
  if (!Generate(reference_line, &min_cost_path)) {
D
Dong Li 已提交
62 63
    AERROR << "Fail to generate graph!";
    return false;
Y
Yifei Jiang 已提交
64
  }
D
Dong Li 已提交
65
  std::vector<common::FrenetFramePoint> frenet_path;
Z
zhuweicheng 已提交
66 67
  double accumulated_s = init_sl_point_.s();
  const double path_resolution = config_.path_resolution();
Y
Yajia Zhang 已提交
68 69

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

73
    const double path_length = cur_node.sl_point.s() - prev_node.sl_point.s();
74
    double current_s = 0.0;
75 76 77 78 79
    const auto &curve = cur_node.min_cost_curve;
    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 已提交
80
      common::FrenetFramePoint frenet_frame_point;
Y
Yifei Jiang 已提交
81 82 83 84 85
      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);
      frenet_path.push_back(frenet_frame_point);
86
      current_s += path_resolution;
Y
Yifei Jiang 已提交
87
    }
88
    accumulated_s += path_length;
Y
Yifei Jiang 已提交
89
  }
90
  FrenetFramePath tunnel(frenet_path);
L
liyun 已提交
91

Y
Yifei Jiang 已提交
92
  path_data->set_frenet_path(tunnel);
93
  // convert frenet path to cartesian path by reference line
Y
Yajia Zhang 已提交
94
  std::vector<common::PathPoint> path_points;
95
  for (const common::FrenetFramePoint &frenet_point : frenet_path) {
D
Dong Li 已提交
96
    common::SLPoint sl_point;
97
    common::math::Vec2d cartesian_point;
Y
Yifei Jiang 已提交
98 99
    sl_point.set_s(frenet_point.s());
    sl_point.set_l(frenet_point.l());
100 101
    if (!reference_line.get_point_in_Cartesian_frame(sl_point,
                                                     &cartesian_point)) {
D
Dong Li 已提交
102 103
      AERROR << "Fail to convert sl point to xy point";
      return false;
Y
Yifei Jiang 已提交
104
    }
105 106
    ReferencePoint ref_point =
        reference_line.get_reference_point(frenet_point.s());
Y
Yifei Jiang 已提交
107
    double theta = SLAnalyticTransformation::calculate_theta(
108 109 110 111 112
        ref_point.heading(), ref_point.kappa(), frenet_point.l(),
        frenet_point.dl());
    double kappa = SLAnalyticTransformation::calculate_kappa(
        ref_point.kappa(), ref_point.dkappa(), frenet_point.l(),
        frenet_point.dl(), frenet_point.ddl());
Y
Yajia Zhang 已提交
113 114

    common::PathPoint path_point;
115 116
    path_point.set_x(cartesian_point.x());
    path_point.set_y(cartesian_point.y());
D
Dong Li 已提交
117
    path_point.set_z(0.0);
Y
Yifei Jiang 已提交
118
    path_point.set_theta(theta);
D
Dong Li 已提交
119
    path_point.set_kappa(kappa);
Y
Yifei Jiang 已提交
120 121 122 123 124
    path_point.set_dkappa(0.0);
    path_point.set_ddkappa(0.0);
    path_point.set_s(0.0);

    if (path_points.size() != 0) {
D
Dong Li 已提交
125 126 127
      common::math::Vec2d last(path_points.back().x(), path_points.back().y());
      common::math::Vec2d current(path_point.x(), path_point.y());
      double distance = (last - current).Length();
Y
Yifei Jiang 已提交
128 129 130 131
      path_point.set_s(path_points.back().s() + distance);
    }
    path_points.push_back(std::move(path_point));
  }
132
  path_data->set_discretized_path(path_points);
D
Dong Li 已提交
133
  return true;
Y
Yifei Jiang 已提交
134 135
}

Y
Yajia Zhang 已提交
136
bool DPRoadGraph::Init(const ReferenceLine &reference_line) {
D
Dong Li 已提交
137 138 139
  if (!reference_line.get_point_in_frenet_frame(
          {init_point_.path_point().x(), init_point_.path_point().y()},
          &init_sl_point_)) {
Y
Yajia Zhang 已提交
140
    AERROR << "Fail to map init point from cartesian to sl coordinate!";
D
Dong Li 已提交
141
    return false;
Y
Yifei Jiang 已提交
142 143
  }

144
  ReferencePoint reference_point =
Z
zhuweicheng 已提交
145
      reference_line.get_reference_point(init_sl_point_.s());
Y
Yifei Jiang 已提交
146

D
Dong Li 已提交
147
  double init_dl = SLAnalyticTransformation::calculate_lateral_derivative(
Z
zhuweicheng 已提交
148 149
      reference_point.heading(), init_point_.path_point().theta(),
      init_sl_point_.l(), reference_point.kappa());
Y
Yajia Zhang 已提交
150

151 152
  double init_ddl =
      SLAnalyticTransformation::calculate_second_order_lateral_derivative(
Z
zhuweicheng 已提交
153 154 155
          reference_point.heading(), init_point_.path_point().theta(),
          reference_point.kappa(), init_point_.path_point().kappa(),
          reference_point.dkappa(), init_sl_point_.l());
Y
Yajia Zhang 已提交
156

D
Dong Li 已提交
157
  common::FrenetFramePoint init_frenet_frame_point;
Z
zhuweicheng 已提交
158 159
  init_frenet_frame_point.set_s(init_sl_point_.s());
  init_frenet_frame_point.set_l(init_sl_point_.l());
Y
Yifei Jiang 已提交
160 161 162
  init_frenet_frame_point.set_dl(init_dl);
  init_frenet_frame_point.set_ddl(init_ddl);

D
Dong Li 已提交
163
  return true;
Y
Yifei Jiang 已提交
164 165
}

Y
Yajia Zhang 已提交
166
bool DPRoadGraph::Generate(const ReferenceLine &reference_line,
167
                           std::vector<DPRoadGraphNode> *min_cost_path) {
Y
Yajia Zhang 已提交
168 169
  CHECK(min_cost_path != nullptr);

Y
Yajia Zhang 已提交
170 171
  std::vector<std::vector<common::SLPoint>> path_waypoints;
  if (!SamplePathWaypoints(reference_line, init_point_, &path_waypoints)) {
Y
Yajia Zhang 已提交
172
    AERROR << "Fail to sample path waypoints!";
173
    return false;
Y
Yifei Jiang 已提交
174
  }
D
Dong Li 已提交
175
  path_waypoints.insert(path_waypoints.begin(),
176
                        std::vector<common::SLPoint>{init_sl_point_});
Y
Yajia Zhang 已提交
177

Y
Yajia Zhang 已提交
178
  const auto &vehicle_config =
179
      common::VehicleConfigHelper::instance()->GetConfig();
Y
Yajia Zhang 已提交
180

Z
zhuweicheng 已提交
181
  TrajectoryCost trajectory_cost(config_, reference_line,
Y
Yajia Zhang 已提交
182
                                 vehicle_config.vehicle_param(), speed_data_);
Y
Yajia Zhang 已提交
183 184 185 186 187 188 189

  std::vector<std::vector<DPRoadGraphNode>> graph_nodes(path_waypoints.size());
  graph_nodes[0].push_back(DPRoadGraphNode(init_sl_point_, nullptr, 0.0));

  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];
190
    for (std::size_t i = 0; i < level_points.size(); ++i) {
191
      const auto &cur_point = level_points[i];
Y
Yajia Zhang 已提交
192
      graph_nodes[level].push_back(DPRoadGraphNode(cur_point, nullptr));
193
      auto &cur_node = graph_nodes[level].back();
194
      for (std::size_t j = 0; j < prev_dp_nodes.size(); ++j) {
195 196
        const auto &prev_dp_node = prev_dp_nodes[j];
        const auto &prev_sl_point = prev_dp_node.sl_point;
Y
Yajia Zhang 已提交
197 198 199
        QuinticPolynomialCurve1d curve(prev_sl_point.l(), 0.0, 0.0,
                                       cur_point.l(), 0.0, 0.0,
                                       cur_point.s() - prev_sl_point.s());
200 201 202
        const double cost =
            trajectory_cost.calculate(curve, prev_sl_point.s(), cur_point.s()) +
            prev_dp_node.min_cost;
Y
Yajia Zhang 已提交
203
        cur_node.UpdateCost(&prev_dp_node, curve, cost);
D
Dong Li 已提交
204 205 206
      }
    }
  }
Y
Yifei Jiang 已提交
207

208
  // find best path
Y
Yajia Zhang 已提交
209 210
  DPRoadGraphNode fake_head;
  const auto &last_dp_nodes = graph_nodes.back();
211 212
  for (std::size_t i = 0; i < last_dp_nodes.size(); ++i) {
    const auto &cur_dp_node = last_dp_nodes[i];
Y
Yajia Zhang 已提交
213
    fake_head.UpdateCost(&cur_dp_node, cur_dp_node.min_cost_curve,
D
Dong Li 已提交
214
                         cur_dp_node.min_cost);
Y
Yifei Jiang 已提交
215
  }
Y
Yajia Zhang 已提交
216

217 218 219 220 221 222
  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 已提交
223 224 225
  return true;
}

226
bool DPRoadGraph::ComputeObjectDecision(const PathData &path_data,
D
Dong Li 已提交
227 228
                                        const SpeedData &heuristic_speed_data,
                                        const ReferenceLine &reference_line,
229 230 231
                                        const ConstObstacleList &obstacles,
                                        DecisionList *const decisions) {
  CHECK_NOTNULL(decisions);
L
liyun 已提交
232

233 234
  std::vector<common::SLPoint> adc_sl_points;
  std::vector<common::math::Box2d> adc_bounding_box;
235 236

  const auto &vehicle_config =
D
Dong Li 已提交
237
      common::VehicleConfigHelper::instance()->GetConfig();
238 239
  double adc_length = vehicle_config.vehicle_param().length();
  double adc_width = vehicle_config.vehicle_param().length();
240

Y
Yajia Zhang 已提交
241
  for (const common::PathPoint &path_point :
D
Dong Li 已提交
242
       path_data.discretized_path().points()) {
243
    adc_bounding_box.emplace_back(
244
        common::math::Vec2d{path_point.x(), path_point.y()}, path_point.theta(),
245 246
        adc_length, adc_width);
    common::SLPoint adc_sl;
D
Dong Li 已提交
247
    if (!reference_line.get_point_in_frenet_frame(
248
            {path_point.x(), path_point.y()}, &adc_sl)) {
249
      AERROR << "get_point_in_Frenet_frame error for ego vehicle "
D
Dong Li 已提交
250
             << path_point.x() << " " << path_point.y();
251
    } else {
252
      adc_sl_points.push_back(std::move(adc_sl));
253 254
    }
  }
D
Dong Li 已提交
255

256 257 258 259
  for (const auto obstacle : obstacles) {
    if (!obstacle->IsStatic()) {
      continue;
    }
260
    bool ignore = true;
261
    const auto &static_obstacle_box = obstacle->PerceptionBoundingBox();
Y
Yajia Zhang 已提交
262
    common::SLPoint obs_sl;
263

264
    if (!reference_line.get_point_in_frenet_frame(
D
Dong Li 已提交
265 266
            {static_obstacle_box.center_x(), static_obstacle_box.center_y()},
            &obs_sl)) {
267
      AERROR << "Fail to map obs in frenet frame";
L
liyun 已提交
268
    }
Y
Yajia Zhang 已提交
269

270 271 272 273
    for (std::size_t j = 0; j < adc_sl_points.size(); ++j) {
      const auto &adc_sl = adc_sl_points[j];
      if (adc_sl.s() < obs_sl.s() - static_obstacle_box.half_length() ||
          adc_sl.s() > obs_sl.s() + static_obstacle_box.half_length()) {
274
        continue;
L
liyun 已提交
275
      } else {
276
        if (static_obstacle_box.HasOverlap(adc_bounding_box[j]) &&
D
Dong Li 已提交
277
            std::fabs(obs_sl.l()) < FLAGS_static_decision_stop_buffer) {
278 279 280 281
          ObjectDecisionType object_stop;
          ObjectStop *object_stop_ptr = object_stop.mutable_stop();
          object_stop_ptr->set_distance_s(FLAGS_dp_path_decision_buffer);
          object_stop_ptr->set_reason_code(
D
Dong Li 已提交
282
              StopReasonCode::STOP_REASON_OBSTACLE);
283
          decisions->push_back(std::make_pair(obstacle->Id(), object_stop));
284 285 286
          ignore = false;
          break;
        } else {
287
          double diff_l = obs_sl.l() - adc_sl.l();
288
          if (diff_l > 0 && fabs(diff_l) < FLAGS_static_decision_ignore_range) {
D
Dong Li 已提交
289
            // GO_RIGHT
290
            ObjectDecisionType object_nudge;
D
Dong Li 已提交
291
            ObjectNudge *object_nudge_ptr = object_nudge.mutable_nudge();
292 293
            object_nudge_ptr->set_distance_l(FLAGS_dp_path_decision_buffer);
            object_nudge_ptr->set_type(ObjectNudge::RIGHT_NUDGE);
294
            decisions->push_back(std::make_pair(obstacle->Id(), object_nudge));
295 296
            ignore = false;
            break;
D
Dong Li 已提交
297 298 299
          } else if (diff_l < 0 &&
                     fabs(diff_l) < FLAGS_static_decision_ignore_range) {
            // GO_LEFT
300
            ObjectDecisionType object_nudge;
D
Dong Li 已提交
301
            ObjectNudge *object_nudge_ptr = object_nudge.mutable_nudge();
302 303
            object_nudge_ptr->set_distance_l(FLAGS_dp_path_decision_buffer);
            object_nudge_ptr->set_type(ObjectNudge::LEFT_NUDGE);
304
            decisions->push_back(std::make_pair(obstacle->Id(), object_nudge));
305 306 307 308
            ignore = false;
            break;
          }
        }
L
liyun 已提交
309
      }
310 311
    }
    if (ignore) {
D
Dong Li 已提交
312
      // IGNORE
D
Dong Li 已提交
313
      ObjectDecisionType object_ignore;
314 315
      object_ignore.mutable_ignore();
      decisions->push_back(std::make_pair(obstacle->Id(), object_ignore));
L
liyun 已提交
316 317 318 319 320
    }
  }

  // Compute dynamic obstacle decision
  const double total_time =
D
Dong Li 已提交
321
      std::min(heuristic_speed_data.total_time(), FLAGS_prediction_total_time);
Y
Yajia Zhang 已提交
322
  std::size_t evaluate_times = static_cast<std::size_t>(
D
Dong Li 已提交
323
      std::floor(total_time / config_.eval_time_interval()));
324 325 326 327
  for (const auto obstacle : obstacles) {
    if (obstacle->IsStatic()) {
      continue;
    }
328 329

    // list of Box2d for ego car given heuristic speed profile
330
    std::vector<common::math::Box2d> adc_by_time;
331 332
    if (!ComputeBoundingBoxesForEgoVehicle(path_data.frenet_frame_path(),
                                           reference_line, heuristic_speed_data,
333 334
                                           evaluate_times, &adc_by_time)) {
      AERROR << "fill_adc_by_time error";
335 336
    }

Y
Yajia Zhang 已提交
337 338
    std::vector<common::math::Box2d> obstacle_by_time;
    for (std::size_t time = 0; time <= evaluate_times; ++time) {
339
      auto traj_point =
340 341
          obstacle->GetPointAtTime(time * config_.eval_time_interval());
      obstacle_by_time.push_back(obstacle->GetBoundingBox(traj_point));
342
    }
343

344
    // if two lists of boxes collide
345
    if (obstacle_by_time.size() != adc_by_time.size()) {
346
      AINFO << "dynamic_obstacle_by_time size[" << obstacle_by_time.size()
347
            << "] != adc_by_time[" << adc_by_time.size()
348 349 350
            << "] from heuristic_speed_data";
      continue;
    }
351

352
    // judge for collision
Y
Yajia Zhang 已提交
353
    for (std::size_t k = 0; k < obstacle_by_time.size(); ++k) {
354
      if (adc_by_time[k].DistanceTo(obstacle_by_time[k]) <
355 356 357
          FLAGS_dynamic_decision_follow_range) {
        // Follow
        ObjectDecisionType object_follow;
358 359 360
        ObjectFollow *object_follow_ptr = object_follow.mutable_follow();
        object_follow_ptr->set_distance_s(FLAGS_dp_path_decision_buffer);
        decisions->push_back(std::make_pair(obstacle->Id(), object_follow));
361
        break;
362 363 364 365 366 367
      }
    }
  }
  return true;
}

Y
Yajia Zhang 已提交
368
bool DPRoadGraph::ComputeBoundingBoxesForEgoVehicle(
D
Dong Li 已提交
369
    const FrenetFramePath &frenet_frame_path,
370
    const ReferenceLine &reference_line, const SpeedData &heuristic_speed_data,
Y
Yajia Zhang 已提交
371
    const std::size_t evaluate_times,
372 373
    std::vector<common::math::Box2d> *adc_boxes) {
  CHECK(adc_boxes != nullptr);
Y
Yajia Zhang 已提交
374

375
  const auto &vehicle_config =
D
Dong Li 已提交
376
      common::VehicleConfigHelper::instance()->GetConfig();
377 378
  double adc_length = vehicle_config.vehicle_param().length();
  double adc_width = vehicle_config.vehicle_param().length();
379

Y
Yajia Zhang 已提交
380
  for (std::size_t i = 0; i < evaluate_times; ++i) {
381 382
    double time_stamp = i * config_.eval_time_interval();
    common::SpeedPoint speed_point;
D
Dong Li 已提交
383 384 385
    if (!heuristic_speed_data.get_speed_point_with_time(time_stamp,
                                                        &speed_point)) {
      AINFO << "get_speed_point_with_time for time_stamp[" << time_stamp << "]";
386
      return false;
L
liyun 已提交
387
    }
388

D
Dong Li 已提交
389 390
    const common::FrenetFramePoint &interpolated_frenet_point =
        frenet_frame_path.interpolate(speed_point.s());
391 392 393 394
    double s = interpolated_frenet_point.s();
    double l = interpolated_frenet_point.l();
    double dl = interpolated_frenet_point.dl();

395
    common::math::Vec2d adc_position_cartesian;
396 397 398
    common::SLPoint sl_point;
    sl_point.set_s(s);
    sl_point.set_l(l);
D
Dong Li 已提交
399
    reference_line.get_point_in_Cartesian_frame(sl_point,
400
                                                &adc_position_cartesian);
401 402 403 404 405 406

    ReferencePoint reference_point = reference_line.get_reference_point(s);

    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 已提交
407
        delta_theta + reference_point.heading());
408

409 410
    adc_boxes->emplace_back(adc_position_cartesian, theta, adc_length,
                            adc_width);
L
liyun 已提交
411 412 413 414
  }
  return true;
}

Y
Yajia Zhang 已提交
415
bool DPRoadGraph::SamplePathWaypoints(
416 417 418
    const ReferenceLine &reference_line,
    const common::TrajectoryPoint &init_point,
    std::vector<std::vector<common::SLPoint>> *const points) {
Y
Yajia Zhang 已提交
419 420 421
  CHECK(points != nullptr);

  common::math::Vec2d init_cartesian_point(init_point.path_point().x(),
D
Dong Li 已提交
422
                                           init_point.path_point().y());
Y
Yajia Zhang 已提交
423 424
  common::SLPoint init_sl_point;
  if (!reference_line.get_point_in_frenet_frame(init_cartesian_point,
425 426
                                                &init_sl_point)) {
    AERROR << "Failed to get sl point from point "
Y
Yajia Zhang 已提交
427
           << init_cartesian_point.DebugString();
428 429
    return false;
  }
Y
Yajia Zhang 已提交
430

431 432
  const double reference_line_length =
      reference_line.map_path().accumulated_s().back();
Y
Yajia Zhang 已提交
433

434 435 436 437 438
  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 已提交
439
  for (std::size_t i = 0;
440 441 442 443 444 445 446 447
       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 已提交
448

449 450 451 452 453 454 455 456 457 458 459 460 461 462
    for (int32_t j = -num; j < num + 1; ++j) {
      double l = config_.lateral_sample_offset() * j;
      auto sl = common::util::MakeSLPoint(s, l);
      if (reference_line.is_on_road(sl)) {
        level_points.push_back(sl);
      }
    }
    if (!level_points.empty()) {
      points->push_back(level_points);
    }
  }
  return true;
}

Y
Yifei Jiang 已提交
463 464
}  // namespace planning
}  // namespace apollo