st_boundary_mapper.cc 24.0 KB
Newer Older
Z
Zhang Liangliang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/******************************************************************************
 * 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.
 *****************************************************************************/

/**
D
Dong Li 已提交
18
 * @file
Z
Zhang Liangliang 已提交
19 20
 **/

21
#include "modules/planning/optimizer/st_graph/st_boundary_mapper.h"
Z
Zhang Liangliang 已提交
22

D
Dong Li 已提交
23
#include <algorithm>
Z
Zhang Liangliang 已提交
24
#include <limits>
D
Dong Li 已提交
25
#include <string>
Z
Zhang Liangliang 已提交
26

D
Dong Li 已提交
27 28 29 30 31
#include "modules/common/proto/pnc_point.pb.h"
#include "modules/planning/proto/decision.pb.h"

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/log.h"
32
#include "modules/common/math/line_segment2d.h"
33
#include "modules/common/math/vec2d.h"
34
#include "modules/common/util/file.h"
D
Dong Li 已提交
35 36 37 38
#include "modules/common/util/string_util.h"
#include "modules/common/util/util.h"
#include "modules/common/vehicle_state/vehicle_state.h"
#include "modules/planning/common/frame.h"
39 40 41 42
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/double.h"

namespace apollo {
Z
Zhang Liangliang 已提交
43 44
namespace planning {

D
Dong Li 已提交
45 46 47
using ErrorCode = apollo::common::ErrorCode;
using Status = apollo::common::Status;
using PathPoint = apollo::common::PathPoint;
48
using TrajectoryPoint = apollo::common::TrajectoryPoint;
D
Dong Li 已提交
49 50 51 52 53
using SLPoint = apollo::common::SLPoint;
using VehicleParam = apollo::common::VehicleParam;
using Box2d = apollo::common::math::Box2d;
using Vec2d = apollo::common::math::Vec2d;

54 55 56 57 58
StBoundaryMapper::StBoundaryMapper(const StBoundaryConfig& config,
                                   const ReferenceLine& reference_line,
                                   const PathData& path_data,
                                   const double planning_distance,
                                   const double planning_time)
D
Dong Li 已提交
59 60
    : st_boundary_config_(config),
      reference_line_(reference_line),
61 62 63 64
      path_data_(path_data),
      vehicle_param_(
          common::VehicleConfigHelper::instance()->GetConfig().vehicle_param()),
      planning_distance_(planning_distance),
65
      planning_time_(planning_time) {
66
  const auto& path_start_point = path_data_.discretized_path().StartPoint();
67
  common::SLPoint sl_point;
68
  DCHECK(reference_line_.get_point_in_frenet_frame(
69 70 71 72
      {path_start_point.x(), path_start_point.y()}, &sl_point))
      << "Failed to get adc reference line s";
  adc_front_s_ = sl_point.s() + vehicle_param_.front_edge_to_center();
}
D
Dong Li 已提交
73 74

Status StBoundaryMapper::GetGraphBoundary(
75
    const PathDecision& path_decision,
D
Dong Li 已提交
76
    std::vector<StGraphBoundary>* const st_graph_boundaries) const {
77
  const auto& path_obstacles = path_decision.path_obstacles();
D
Dong Li 已提交
78 79 80 81 82 83
  if (st_graph_boundaries == nullptr) {
    const std::string msg = "st_graph_boundaries is NULL.";
    AERROR << msg;
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }

84 85
  if (planning_time_ < 0.0) {
    const std::string msg = "Fail to get params since planning_time_ < 0.";
D
Dong Li 已提交
86 87 88 89
    AERROR << msg;
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }

90
  if (path_data_.discretized_path().NumOfPoints() < 2) {
D
Dong Li 已提交
91 92
    AERROR << "Fail to get params because of too few path points. path points "
              "size: "
93
           << path_data_.discretized_path().NumOfPoints() << ".";
D
Dong Li 已提交
94 95 96 97 98 99 100
    return Status(ErrorCode::PLANNING_ERROR,
                  "Fail to get params because of too few path points");
  }

  st_graph_boundaries->clear();
  Status ret = Status::OK();

101 102 103
  const PathObstacle* stop_obstacle = nullptr;
  ObjectDecisionType stop_decision;
  double min_stop_s = std::numeric_limits<double>::max();
Z
Zhang Liangliang 已提交
104

105
  for (const auto* path_obstacle : path_obstacles.Items()) {
106 107 108
    if (path_obstacle->Decisions().empty()) {
      const auto ret =
          MapObstacleWithoutDecision(*path_obstacle, st_graph_boundaries);
109
      if (ret.code() == ErrorCode::PLANNING_ERROR) {
110 111 112 113 114 115
        std::string msg = common::util::StrCat(
            "Fail to map obstacle ", path_obstacle->Id(), " without decision.");
        AERROR << msg;
        return Status(ErrorCode::PLANNING_ERROR, msg);
      }
    }
116
    for (const auto& decision : path_obstacle->Decisions()) {
117
      StGraphBoundary boundary(path_obstacle);
118
      if (decision.has_follow()) {
119
        const auto ret = MapFollowDecision(*path_obstacle, decision, &boundary);
120
        if (!ret.ok()) {
121 122
          AERROR << "Fail to map obstacle " << path_obstacle->Id()
                 << " with follow decision: " << decision.DebugString();
D
Dong Li 已提交
123
          return Status(ErrorCode::PLANNING_ERROR,
124
                        "Fail to map follow decision");
D
Dong Li 已提交
125
        }
126
      } else if (decision.has_stop()) {
127 128 129 130
        const double stop_s = path_obstacle->sl_boundary().start_s() +
                              decision.stop().distance_s();
        if (stop_s < adc_front_s_) {
          AERROR << "Invalid stop decision. not stop at ahead of current "
Y
Yajia Zhang 已提交
131
                    "position. stop_s : "
132 133 134 135 136 137 138 139 140 141 142 143
                 << stop_s << ", and current adc_s is; " << adc_front_s_;
          return Status(ErrorCode::PLANNING_ERROR, "invalid decision");
        }
        if (!stop_obstacle) {
          stop_obstacle = path_obstacle;
          stop_decision = decision;
          min_stop_s = stop_s;
        } else if (stop_s < min_stop_s) {
          stop_obstacle = path_obstacle;
          min_stop_s = stop_s;
          stop_decision = decision;
        }
144 145
      } else if (decision.has_overtake() || decision.has_yield()) {
        const auto ret = MapObstacleWithPredictionTrajectory(
146
            *path_obstacle, decision, st_graph_boundaries);
D
Dong Li 已提交
147
        if (!ret.ok()) {
148 149 150 151
          AERROR << "Fail to map obstacle " << path_obstacle->Id()
                 << " with decision: " << decision.DebugString();
          return Status(ErrorCode::PLANNING_ERROR,
                        "Fail to map overtake/yield decision");
D
Dong Li 已提交
152
        }
153
      } else {
154 155 156
        std::string msg = common::util::StrCat("No mapping for decision: ",
                                               decision.DebugString());
        return Status(ErrorCode::PLANNING_SKIP, msg);
D
Dong Li 已提交
157
      }
158
      boundary.set_id(path_obstacle->Id());
D
Dong Li 已提交
159 160
    }
  }
Z
Zhang Liangliang 已提交
161

162
  if (stop_obstacle) {
163
    StGraphBoundary stop_boundary(stop_obstacle);
164 165 166 167 168 169
    bool success = MapObstacleWithStopDecision(*stop_obstacle, stop_decision,
                                               &stop_boundary);
    if (!success) {
      std::string msg = "Fail to MapObstacleWithStopDecision.";
      AERROR << msg;
      return Status(ErrorCode::PLANNING_ERROR, msg);
Z
Zhang Liangliang 已提交
170
    }
171
    st_graph_boundaries->push_back(stop_boundary);
Z
Zhang Liangliang 已提交
172 173
  }

D
Dong Li 已提交
174 175 176
  return Status::OK();
}

Z
Zhang Liangliang 已提交
177
bool StBoundaryMapper::MapObstacleWithStopDecision(
178 179 180
    const PathObstacle& stop_obstacle, const ObjectDecisionType& stop_decision,
    StGraphBoundary* const boundary) const {
  CHECK_NOTNULL(boundary);
181
  DCHECK(stop_decision.has_stop()) << "Must have stop decision";
182

183
  PathPoint obstacle_point;
184
  if (!path_data_.GetPathPointWithRefS(stop_obstacle.sl_boundary().start_s(),
185
                                       &obstacle_point)) {
186 187 188 189 190 191
    AERROR << "Fail to get path point from reference s. The sl boundary of "
              "stop obstacle is: "
           << stop_obstacle.sl_boundary().DebugString();
    return false;
  }

192 193 194
  const double st_stop_s =
      obstacle_point.s() + stop_decision.stop().distance_s() -
      vehicle_param_.front_edge_to_center() - FLAGS_decision_valid_stop_range;
195
  if (st_stop_s < 0.0) {
196
    AERROR << "obstacle st stop_s " << st_stop_s << " is less than 0.";
Z
Zhang Liangliang 已提交
197 198 199
    return false;
  }

200
  const double s_min = st_stop_s;
201 202
  const double s_max =
      std::fmax(s_min, std::fmax(planning_distance_, reference_line_.length()));
Z
Zhang Liangliang 已提交
203 204 205 206 207 208 209
  std::vector<STPoint> boundary_points;
  boundary_points.emplace_back(s_min, 0.0);
  boundary_points.emplace_back(s_min, planning_time_);
  boundary_points.emplace_back(s_max + st_boundary_config_.boundary_buffer(),
                               planning_time_);
  boundary_points.emplace_back(s_max, 0.0);

210
  *boundary = StGraphBoundary(&stop_obstacle, boundary_points);
211
  boundary->SetBoundaryType(StGraphBoundary::BoundaryType::STOP);
212
  boundary->SetCharacteristicLength(st_boundary_config_.boundary_buffer());
213
  boundary->set_id(stop_obstacle.Id());
Z
Zhang Liangliang 已提交
214 215 216
  return true;
}

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
Status StBoundaryMapper::MapObstacleWithoutDecision(
    const PathObstacle& path_obstacle,
    std::vector<StGraphBoundary>* const boundary) const {
  std::vector<STPoint> lower_points;
  std::vector<STPoint> upper_points;

  const auto* obstacle = path_obstacle.Obstacle();

  bool skip = true;
  std::vector<STPoint> boundary_points;
  const auto& adc_path_points = path_data_.discretized_path().path_points();
  if (adc_path_points.size() == 0) {
    std::string msg = common::util::StrCat(
        "Too few points in path_data_.discretized_path(); size = ",
        adc_path_points.size());
    AERROR << msg;
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }
  const auto& trajectory = obstacle->Trajectory();
  if (trajectory.trajectory_point_size() == 0) {
237 238 239 240
    std::string msg = common::util::StrCat("Obstacle (id = ", obstacle->Id(),
                                           ") has NO prediction trajectory.");
    AERROR << msg;
    return Status(ErrorCode::PLANNING_ERROR, msg);
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
  }

  for (int j = 0; j < trajectory.trajectory_point_size(); ++j) {
    const auto& trajectory_point = trajectory.trajectory_point(j);
    double trajectory_point_time = trajectory_point.relative_time();
    const Box2d obs_box = obstacle->GetBoundingBox(trajectory_point);
    int64_t low = 0;
    int64_t high = adc_path_points.size() - 1;
    bool find_low = false;
    bool find_high = false;
    while (low < high) {
      if (find_low && find_high) {
        break;
      }
      if (!find_low) {
        if (!CheckOverlap(adc_path_points[low], obs_box,
                          st_boundary_config_.boundary_buffer())) {
          ++low;
        } else {
          find_low = true;
        }
      }
      if (!find_high) {
        if (!CheckOverlap(adc_path_points[high], obs_box,
                          st_boundary_config_.boundary_buffer())) {
          --high;
        } else {
          find_high = true;
        }
      }
    }
    if (find_high && find_low) {
      lower_points.emplace_back(
          adc_path_points[low].s() - st_boundary_config_.point_extension(),
          trajectory_point_time);
      upper_points.emplace_back(
          adc_path_points[high].s() + st_boundary_config_.point_extension(),
          trajectory_point_time);
    }
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
  }
  if (lower_points.size() > 0 && upper_points.size() > 0) {
    boundary_points.clear();
    const double buffer = st_boundary_config_.follow_buffer();
    boundary_points.emplace_back(lower_points.at(0).s() - buffer,
                                 lower_points.at(0).t());
    boundary_points.emplace_back(lower_points.back().s() - buffer,
                                 lower_points.back().t());
    boundary_points.emplace_back(upper_points.back().s() + buffer +
                                     st_boundary_config_.boundary_buffer(),
                                 upper_points.back().t());
    boundary_points.emplace_back(upper_points.at(0).s() + buffer,
                                 upper_points.at(0).t());
    if (lower_points.at(0).t() > lower_points.back().t() ||
        upper_points.at(0).t() > upper_points.back().t()) {
      AWARN << "lower/upper points are reversed.";
    }
297

298 299 300 301 302
    const double area = GetArea(boundary_points);
    if (Double::Compare(area, 0.0) > 0) {
      boundary->emplace_back(&path_obstacle, boundary_points);
      boundary->back().set_id(obstacle->Id());
      skip = false;
303 304 305 306 307 308
    }
  }
  return skip ? Status(ErrorCode::PLANNING_SKIP, "PLANNING_SKIP")
              : Status::OK();
}

309 310 311 312 313 314 315 316 317 318 319
bool StBoundaryMapper::GetOverlapBoundaryPoints(
    const std::vector<PathPoint>& path_points, const Obstacle& obstacle,
    std::vector<STPoint>* upper_points,
    std::vector<STPoint>* lower_points) const {
  DCHECK_NOTNULL(upper_points);
  DCHECK_NOTNULL(lower_points);
  DCHECK(upper_points->empty());
  DCHECK(lower_points->empty());
  DCHECK_GT(path_points.size(), 0);

  if (path_points.size() == 0) {
320 321
    std::string msg = common::util::StrCat(
        "Too few points in path_data_.discretized_path(); size = ",
322
        path_points.size());
323
    AERROR << msg;
324
    return false;
D
Dong Li 已提交
325 326
  }

327
  const auto& trajectory = obstacle.Trajectory();
D
Dong Li 已提交
328 329 330
  for (int j = 0; j < trajectory.trajectory_point_size(); ++j) {
    const auto& trajectory_point = trajectory.trajectory_point(j);
    double trajectory_point_time = trajectory_point.relative_time();
331
    const Box2d obs_box = obstacle.GetBoundingBox(trajectory_point);
D
Dong Li 已提交
332
    int64_t low = 0;
333
    int64_t high = path_points.size() - 1;
D
Dong Li 已提交
334 335 336 337 338 339 340
    bool find_low = false;
    bool find_high = false;
    while (low < high) {
      if (find_low && find_high) {
        break;
      }
      if (!find_low) {
341
        if (!CheckOverlap(path_points[low], obs_box,
D
Dong Li 已提交
342 343 344 345 346 347 348
                          st_boundary_config_.boundary_buffer())) {
          ++low;
        } else {
          find_low = true;
        }
      }
      if (!find_high) {
349
        if (!CheckOverlap(path_points[high], obs_box,
D
Dong Li 已提交
350 351 352 353 354 355 356 357
                          st_boundary_config_.boundary_buffer())) {
          --high;
        } else {
          find_high = true;
        }
      }
    }
    if (find_high && find_low) {
358 359
      lower_points->emplace_back(
          path_points[low].s() - st_boundary_config_.point_extension(),
D
Dong Li 已提交
360
          trajectory_point_time);
361 362
      upper_points->emplace_back(
          path_points[high].s() + st_boundary_config_.point_extension(),
D
Dong Li 已提交
363 364
          trajectory_point_time);
    }
365 366 367 368
  }
  DCHECK_EQ(lower_points->size(), upper_points->size());
  return (lower_points->size() > 0 && upper_points->size() > 0);
}
D
Dong Li 已提交
369

370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
Status StBoundaryMapper::MapObstacleWithPredictionTrajectory(
    const PathObstacle& path_obstacle, const ObjectDecisionType& obj_decision,
    std::vector<StGraphBoundary>* const boundary) const {
  std::vector<STPoint> lower_points;
  std::vector<STPoint> upper_points;

  bool skip = true;
  std::vector<STPoint> boundary_points;
  if (!GetOverlapBoundaryPoints(path_data_.discretized_path().path_points(),
                                *(path_obstacle.Obstacle()), &upper_points,
                                &lower_points)) {
    return skip ? Status(ErrorCode::PLANNING_SKIP, "PLANNING_SKIP")
                : Status::OK();
    ;

    if (lower_points.size() > 0 && upper_points.size() > 0) {
D
Dong Li 已提交
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
      boundary_points.clear();
      const double buffer = st_boundary_config_.follow_buffer();
      boundary_points.emplace_back(lower_points.at(0).s() - buffer,
                                   lower_points.at(0).t());
      boundary_points.emplace_back(lower_points.back().s() - buffer,
                                   lower_points.back().t());
      boundary_points.emplace_back(upper_points.back().s() + buffer +
                                       st_boundary_config_.boundary_buffer(),
                                   upper_points.back().t());
      boundary_points.emplace_back(upper_points.at(0).s() + buffer,
                                   upper_points.at(0).t());
      if (lower_points.at(0).t() > lower_points.back().t() ||
          upper_points.at(0).t() > upper_points.back().t()) {
        AWARN << "lower/upper points are reversed.";
      }

      // change boundary according to obj_decision.
      StGraphBoundary::BoundaryType b_type =
          StGraphBoundary::BoundaryType::UNKNOWN;
405
      double characteristic_length = 0.0;
D
Dong Li 已提交
406
      if (obj_decision.has_follow()) {
407 408 409 410 411 412 413 414 415 416 417
        const auto& speed = obstacle->Perception().velocity();
        const double scalar_speed = std::hypot(speed.x(), speed.y());
        const double minimal_follow_time =
            st_boundary_config_.minimal_follow_time();
        characteristic_length =
            std::fmax(scalar_speed * minimal_follow_time,
                      std::fabs(obj_decision.follow().distance_s())) +
            vehicle_param_.front_edge_to_center();

        boundary_points.at(0).set_s(boundary_points.at(0).s());
        boundary_points.at(1).set_s(boundary_points.at(1).s());
D
Dong Li 已提交
418 419 420 421
        boundary_points.at(3).set_t(-1.0);
        b_type = StGraphBoundary::BoundaryType::FOLLOW;
      } else if (obj_decision.has_yield()) {
        const double dis = std::fabs(obj_decision.yield().distance_s());
422
        characteristic_length = dis;
D
Dong Li 已提交
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
        // TODO(all): remove the arbitrary numbers in this part.
        if (boundary_points.at(0).s() - dis < 0.0) {
          boundary_points.at(0).set_s(
              std::fmax(boundary_points.at(0).s() - 2.0, 0.0));
        } else {
          boundary_points.at(0).set_s(
              std::fmax(boundary_points.at(0).s() - dis, 0.0));
        }
        if (boundary_points.at(1).s() - dis < 0.0) {
          boundary_points.at(1).set_s(
              std::fmax(boundary_points.at(0).s() - 4.0, 0.0));
        } else {
          boundary_points.at(1).set_s(
              std::fmax(boundary_points.at(0).s() - dis, 0.0));
        }
        b_type = StGraphBoundary::BoundaryType::YIELD;
      } else if (obj_decision.has_overtake()) {
        const double dis = std::fabs(obj_decision.overtake().distance_s());
441
        characteristic_length = dis;
D
Dong Li 已提交
442 443 444 445 446
        boundary_points.at(2).set_s(boundary_points.at(2).s() + dis);
        boundary_points.at(3).set_s(boundary_points.at(3).s() + dis);
      }

      const double area = GetArea(boundary_points);
447
      if (Double::Compare(area, 0.0) > 0) {
448
        boundary->emplace_back(&path_obstacle, boundary_points);
D
Dong Li 已提交
449
        boundary->back().SetBoundaryType(b_type);
450
        boundary->back().set_id(obstacle->Id());
451
        boundary->back().SetCharacteristicLength(characteristic_length);
D
Dong Li 已提交
452 453 454
        skip = false;
      }
    }
455 456
    return skip ? Status(ErrorCode::PLANNING_SKIP, "PLANNING_SKIP")
                : Status::OK();
D
Dong Li 已提交
457 458
  }

459 460 461 462 463 464 465 466 467 468 469 470
  Status StBoundaryMapper::MapFollowDecision(
      const PathObstacle& path_obstacle, const ObjectDecisionType& obj_decision,
      StGraphBoundary* const boundary) const {
    if (!obj_decision.has_follow()) {
      std::string msg = common::util::StrCat(
          "Map obstacle without prediction trajectory is ONLY supported when "
          "the "
          "object decision is follow. The current object decision is: \n",
          obj_decision.DebugString());
      AERROR << msg;
      return Status(ErrorCode::PLANNING_ERROR, msg);
    }
D
Dong Li 已提交
471

472
    const auto* obstacle = path_obstacle.Obstacle();
473

474 475
    const auto& speed = obstacle->Perception().velocity();
    const double scalar_speed = std::hypot(speed.x(), speed.y());
D
Dong Li 已提交
476

477 478 479 480 481 482 483 484 485 486
    const auto& perception = obstacle->Perception();
    const PathPoint ref_point = reference_line_.get_reference_point(
        perception.position().x(), perception.position().y());
    const double speed_coeff = std::cos(perception.theta() - ref_point.theta());
    if (speed_coeff < 0.0) {
      AERROR << "Obstacle is moving opposite to the reference line. Obstacle: "
             << perception.DebugString();
      return common::Status(ErrorCode::PLANNING_ERROR,
                            "obstacle is moving opposite the reference line");
    }
D
Dong Li 已提交
487

488 489 490 491 492 493 494 495 496 497 498 499
    const auto& point = path_data_.discretized_path().StartPoint();
    const PathPoint curr_point =
        reference_line_.get_reference_point(point.x(), point.y());
    const double distance_to_obstacle = ref_point.s() - curr_point.s() -
                                        vehicle_param_.front_edge_to_center() -
                                        st_boundary_config_.follow_buffer();

    if (distance_to_obstacle > planning_distance_) {
      std::string msg = "obstacle is out of range.";
      AINFO << msg;
      return Status(ErrorCode::PLANNING_SKIP, msg);
    }
D
Dong Li 已提交
500

501 502 503 504 505 506 507
    double follow_speed = 0.0;
    if (scalar_speed > st_boundary_config_.follow_speed_threshold()) {
      follow_speed = st_boundary_config_.follow_speed_threshold() * speed_coeff;
    } else {
      follow_speed = scalar_speed * speed_coeff *
                     st_boundary_config_.follow_speed_damping_factor();
    }
D
Dong Li 已提交
508

509 510 511 512 513 514
    const double s_min_lower = distance_to_obstacle;
    const double s_min_upper =
        std::max(distance_to_obstacle + 1.0, planning_distance_);
    const double s_max_upper = std::max(
        s_min_upper + planning_time_ * follow_speed, planning_distance_);
    const double s_max_lower = s_min_lower + planning_time_ * follow_speed;
Z
Zhang Liangliang 已提交
515

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
    std::vector<STPoint> boundary_points;
    boundary_points.emplace_back(s_min_lower, 0.0);
    boundary_points.emplace_back(s_max_lower, planning_time_);
    boundary_points.emplace_back(s_max_upper, planning_time_);
    boundary_points.emplace_back(s_min_upper, 0.0);

    const double area = GetArea(boundary_points);
    if (Double::Compare(area, 0.0) <= 0) {
      std::string msg = "Do not need to map because area is zero.";
      AINFO << msg;
      return Status(ErrorCode::PLANNING_SKIP, msg);
    }
    *boundary = StGraphBoundary(&path_obstacle, boundary_points);

    const double characteristic_length =
        std::fmax(scalar_speed * speed_coeff *
                      st_boundary_config_.minimal_follow_time(),
                  std::fabs(obj_decision.follow().distance_s())) +
        vehicle_param_.front_edge_to_center() +
        st_boundary_config_.follow_buffer();

    boundary->SetCharacteristicLength(characteristic_length *
                                      st_boundary_config_.follow_coeff());
    boundary->SetBoundaryType(StGraphBoundary::BoundaryType::FOLLOW);
    boundary->set_id(obstacle->Id());
    return Status::OK();
Z
Zhang Liangliang 已提交
542 543
  }

544 545 546 547 548 549 550 551 552 553
  double StBoundaryMapper::GetArea(const std::vector<STPoint>& boundary_points)
      const {
    if (boundary_points.size() < 3) {
      return 0.0;
    }

    double area = 0.0;
    for (uint32_t i = 2; i < boundary_points.size(); ++i) {
      const double ds1 = boundary_points[i - 1].s() - boundary_points[0].s();
      const double dt1 = boundary_points[i - 1].t() - boundary_points[0].t();
Y
Yajia Zhang 已提交
554

555 556 557 558 559 560
      const double ds2 = boundary_points[i].s() - boundary_points[0].s();
      const double dt2 = boundary_points[i].t() - boundary_points[0].t();
      // cross product
      area += (ds1 * dt2 - ds2 * dt1);
    }
    return fabs(area * 0.5);
Z
Zhang Liangliang 已提交
561 562
  }

563 564 565 566 567 568 569 570 571 572 573 574 575 576
  bool StBoundaryMapper::CheckOverlap(const PathPoint& path_point,
                                      const Box2d& obs_box, const double buffer)
      const {
    const double mid_to_rear_center =
        vehicle_param_.length() / 2.0 - vehicle_param_.front_edge_to_center();
    const double x =
        path_point.x() - mid_to_rear_center * std::cos(path_point.theta());
    const double y =
        path_point.y() - mid_to_rear_center * std::sin(path_point.theta());
    const Box2d adc_box =
        Box2d({x, y}, path_point.theta(), vehicle_param_.length() + 2 * buffer,
              vehicle_param_.width() + 2 * buffer);
    return obs_box.HasOverlap(adc_box);
  }
Z
Zhang Liangliang 已提交
577

578 579 580
  Status StBoundaryMapper::GetSpeedLimits(SpeedLimit * const speed_limit_data)
      const {
    CHECK_NOTNULL(speed_limit_data);
581

582 583 584 585 586 587 588 589 590 591
    std::vector<double> speed_limits;
    for (const auto& path_point : path_data_.discretized_path().path_points()) {
      if (Double::Compare(path_point.s(), reference_line_.length()) > 0) {
        std::string msg = common::util::StrCat(
            "path length [", path_data_.discretized_path().Length(),
            "] is LARGER than reference_line_ length [",
            reference_line_.length(), "]. Please debug before proceeding.");
        AWARN << msg;
        break;
      }
592

593 594
      double speed_limit_on_reference_line =
          reference_line_.GetSpeedLimitFromS(path_point.s());
595

596 597 598 599 600
      // speed limit from path curvature
      double speed_limit_on_path =
          std::sqrt(st_boundary_config_.centric_acceleration_limit() /
                    std::fmax(std::fabs(path_point.kappa()),
                              st_boundary_config_.minimal_kappa()));
601

602 603 604
      const double curr_speed_limit = std::fmax(
          st_boundary_config_.lowest_speed(),
          std::fmin(speed_limit_on_path, speed_limit_on_reference_line));
605

606 607 608
      speed_limit_data->AddSpeedLimit(path_point.s(), curr_speed_limit);
    }
    return Status::OK();
609
  }
610

Z
Zhang Liangliang 已提交
611
}  // namespace planning
612
}  // namespace apollo