当前位置:   article > 正文

Apollo Planning决策规划算法代码详细解析 (3):stage执行_planning决策规划代码详细解析

planning决策规划代码详细解析

通过之前章节的介绍,在经过Scenario的决策与执行之后,Apollo已经可以确定目前处于对应场景下的对应stage,接下来就进入stage类的内部,通过Process() 函数来进行具体的规划过程。本章节将以 LANE_FOLLOW 场景的 LANE_FOLLOW_DEFAULT_STAGE 为例,讲解stage的执行流程。

Apollo Planning决策规划系列文章:

Apollo Planning决策规划代码详细解析 (1):Scenario选择

Apollo Planning决策规划代码详细解析 (2):Scenario执行

Apollo Planning决策规划代码详细解析 (4):Stage逻辑详解

Apollo Planning决策规划代码详细解析 (5):规划算法流程介绍

Apollo Planning决策规划代码详细解析 (6):LaneChangeDecider

Apollo Planning决策规划代码详细解析 (7): PathReuseDecider

Apollo Planning决策规划代码详细解析 (8): PathLaneBorrowDecider

Apollo Planning决策规划代码详细解析 (9): PathBoundsDecider

Apollo Planning决策规划代码详细解析 (10):PiecewiseJerkPathOptimizer

Apollo Planning决策规划代码详细解析 (11): PathAssessmentDecider

Apollo Planning决策规划代码详细解析 (12): PathDecider

Apollo Planning决策规划代码详细解析 (13): RuleBasedStopDecider

算法详细介绍系列文章: 

Apollo决策规划算法Planning : Piecewise Jerk Path Optimizer

仿真技术介绍:

prescan联合simulink进行FCW的仿真_自动驾驶 Player的博客-CSDN博客

通过之前章节的介绍,在经过Scenario的决策与执行之后,Apollo已经可以确定目前处于对应场景下的对应stage,接下来就进入stage类的内部,通过Process() 函数来进行具体的规划过程。本章节将以 LANE_FOLLOW 场景的 LANE_FOLLOW_DEFAULT_STAGE 为例,讲解stage的执行流程。

码字不易,喜欢的朋友们麻烦点个关注与赞。

在本文你将学到下面这些内容:

  1. stage模块的注册与管理机制;
  2. stage模块调用的接口与顺序;
  3. NOP功能最常用stage:LANE_FOLLOW_DEFAULT_STAGE;
  4. LANE_FOLLOW_DEFAULT_STAGE中对变道场景的处理;
  5. LANE_FOLLOW_DEFAULT_STAGE的执行过程;
  6. LANE_FOLLOW_DEFAULT_STAGE的规划逻辑。

代码具体过程如下:

1、前文提到在planning模块执行的过程中,会根据配置来依次实例化每个Scenario当前所处的stage,LANE_FOLLOW这个Scenario只有LANE_FOLLOW_DEFAULT_STAGE一个stage,所以它的 CreateStage() 函数如下:

  1. std::unique_ptr<Stage> LaneFollowScenario::CreateStage(
  2. const ScenarioConfig::StageConfig& stage_config,
  3. const std::shared_ptr<DependencyInjector>& injector) {
  4. if (stage_config.stage_type() != ScenarioConfig::LANE_FOLLOW_DEFAULT_STAGE) {
  5. AERROR << "Follow lane does not support stage type: "
  6. << ScenarioConfig::StageType_Name(stage_config.stage_type());
  7. return nullptr;
  8. }
  9. return std::unique_ptr<Stage>(new LaneFollowStage(stage_config, injector));
  10. }

其它的场景可能有多个stage,就需要先注册所有stage,然后再根据type创建当前stage:

  1. void ParkAndGoScenario::RegisterStages() {
  2. if (!s_stage_factory_.Empty()) {
  3. s_stage_factory_.Clear();
  4. }
  5. s_stage_factory_.Register(
  6. ScenarioConfig::PARK_AND_GO_CHECK,
  7. [](const ScenarioConfig::StageConfig& config,
  8. const std::shared_ptr<DependencyInjector>& injector) -> Stage* {
  9. return new ParkAndGoStageCheck(config, injector);
  10. });
  11. s_stage_factory_.Register(
  12. ScenarioConfig::PARK_AND_GO_ADJUST,
  13. [](const ScenarioConfig::StageConfig& config,
  14. const std::shared_ptr<DependencyInjector>& injector) -> Stage* {
  15. return new ParkAndGoStageAdjust(config, injector);
  16. });
  17. s_stage_factory_.Register(
  18. ScenarioConfig::PARK_AND_GO_PRE_CRUISE,
  19. [](const ScenarioConfig::StageConfig& config,
  20. const std::shared_ptr<DependencyInjector>& injector) -> Stage* {
  21. return new ParkAndGoStagePreCruise(config, injector);
  22. });
  23. s_stage_factory_.Register(
  24. ScenarioConfig::PARK_AND_GO_CRUISE,
  25. [](const ScenarioConfig::StageConfig& config,
  26. const std::shared_ptr<DependencyInjector>& injector) -> Stage* {
  27. return new ParkAndGoStageCruise(config, injector);
  28. });
  29. }
  30. std::unique_ptr<Stage> ParkAndGoScenario::CreateStage(
  31. const ScenarioConfig::StageConfig& stage_config,
  32. const std::shared_ptr<DependencyInjector>& injector) {
  33. if (s_stage_factory_.Empty()) {
  34. RegisterStages();
  35. }
  36. auto ptr = s_stage_factory_.CreateObjectOrNull(stage_config.stage_type(),
  37. stage_config, injector);
  38. if (ptr) {
  39. ptr->SetContext(&context_);
  40. }
  41. return ptr;
  42. }

2、当前stage创建好之后,在Scenario的Process()函数处会调用当前stage的Process()函数,完成当前stage具体的规划任务。

  1. Scenario::ScenarioStatus Scenario::Process(
  2. const common::TrajectoryPoint& planning_init_point, Frame* frame) {
  3. // stage类型unknow
  4. if (current_stage_ == nullptr) {
  5. AWARN << "Current stage is a null pointer.";
  6. return STATUS_UNKNOWN;
  7. }
  8. // stage全部执行完成
  9. if (current_stage_->stage_type() == ScenarioConfig::NO_STAGE) {
  10. scenario_status_ = STATUS_DONE;
  11. return scenario_status_;
  12. }
  13. // 当前处于某一stage,调用这个stage的Process()函数,处理具体规划逻辑
  14. auto ret = current_stage_->Process(planning_init_point, frame);
  15. // 读取当前stage完成的状态,并进行处理
  16. switch (ret) {
  17. case Stage::ERROR: {
  18. AERROR << "Stage '" << current_stage_->Name() << "' returns error";
  19. scenario_status_ = STATUS_UNKNOWN;
  20. break;
  21. }
  22. case Stage::RUNNING: {
  23. scenario_status_ = STATUS_PROCESSING;
  24. break;
  25. }
  26. case Stage::FINISHED: {
  27. auto next_stage = current_stage_->NextStage();
  28. if (next_stage != current_stage_->stage_type()) {
  29. AINFO << "switch stage from " << current_stage_->Name() << " to "
  30. << ScenarioConfig::StageType_Name(next_stage);
  31. if (next_stage == ScenarioConfig::NO_STAGE) {
  32. scenario_status_ = STATUS_DONE;
  33. return scenario_status_;
  34. }
  35. if (stage_config_map_.find(next_stage) == stage_config_map_.end()) {
  36. AERROR << "Failed to find config for stage: " << next_stage;
  37. scenario_status_ = STATUS_UNKNOWN;
  38. return scenario_status_;
  39. }
  40. current_stage_ = CreateStage(*stage_config_map_[next_stage], injector_);
  41. if (current_stage_ == nullptr) {
  42. AWARN << "Current stage is a null pointer.";
  43. return STATUS_UNKNOWN;
  44. }
  45. }
  46. if (current_stage_ != nullptr &&
  47. current_stage_->stage_type() != ScenarioConfig::NO_STAGE) {
  48. scenario_status_ = STATUS_PROCESSING;
  49. } else {
  50. scenario_status_ = STATUS_DONE;
  51. }
  52. break;
  53. }
  54. default: {
  55. AWARN << "Unexpected Stage return value: " << ret;
  56. scenario_status_ = STATUS_UNKNOWN;
  57. }
  58. }
  59. return scenario_status_;
  60. }

3、在当前stage,即LANE_FOLLOW_DEFAULT_STAGE中,调用Process()函数,执行具体的固化任务。该函数的定义如下,关键步骤加了备注,稍后会详细讲解这部分代码。

  1. Stage::StageStatus LaneFollowStage::Process(
  2. const TrajectoryPoint& planning_start_point, Frame* frame) {
  3. bool has_drivable_reference_line = false;
  4. ADEBUG << "Number of reference lines:\t"
  5. << frame->mutable_reference_line_info()->size();
  6. unsigned int count = 0;
  7. // 遍历所有的参考线,直到找到可用来规划的参考线后退出
  8. for (auto& reference_line_info : *frame->mutable_reference_line_info()) {
  9. // TODO(SHU): need refactor
  10. if (count++ == frame->mutable_reference_line_info()->size()) {
  11. break;
  12. }
  13. ADEBUG << "No: [" << count << "] Reference Line.";
  14. ADEBUG << "IsChangeLanePath: " << reference_line_info.IsChangeLanePath();
  15. // 找到可用来规划的参考线,退出循环
  16. if (has_drivable_reference_line) {
  17. reference_line_info.SetDrivable(false);
  18. break;
  19. }
  20. // 执行具体规划任务
  21. auto cur_status =
  22. PlanOnReferenceLine(planning_start_point, frame, &reference_line_info);
  23. // 判断规划结果是否OK
  24. if (cur_status.ok()) {
  25. // 如果发生lanechange,判断reference_line的cost
  26. if (reference_line_info.IsChangeLanePath()) {
  27. ADEBUG << "reference line is lane change ref.";
  28. ADEBUG << "FLAGS_enable_smarter_lane_change: "
  29. << FLAGS_enable_smarter_lane_change;
  30. if (reference_line_info.Cost() < kStraightForwardLineCost &&
  31. (LaneChangeDecider::IsClearToChangeLane(&reference_line_info) ||
  32. FLAGS_enable_smarter_lane_change)) {
  33. // If the path and speed optimization succeed on target lane while
  34. // under smart lane-change or IsClearToChangeLane under older version
  35. has_drivable_reference_line = true;
  36. reference_line_info.SetDrivable(true);
  37. LaneChangeDecider::UpdatePreparationDistance(
  38. true, frame, &reference_line_info, injector_->planning_context());
  39. ADEBUG << "\tclear for lane change";
  40. } else {
  41. LaneChangeDecider::UpdatePreparationDistance(
  42. false, frame, &reference_line_info,
  43. injector_->planning_context());
  44. reference_line_info.SetDrivable(false);
  45. ADEBUG << "\tlane change failed";
  46. }
  47. }
  48. // 如果没有lanechange,stage执行结果为OK,则has_drivable_reference_line置位true
  49. else {
  50. ADEBUG << "reference line is NOT lane change ref.";
  51. has_drivable_reference_line = true;
  52. }
  53. } else {
  54. reference_line_info.SetDrivable(false);
  55. }
  56. }
  57. // 根据has_drivable_reference_line这个标志位的结果,返回stage执行的结果
  58. return has_drivable_reference_line ? StageStatus::RUNNING
  59. : StageStatus::ERROR;
  60. }

通过以上代码看到,当变道时针对目标车道进行规划,如果规划成功后,还需要判断目标车道的变道cost,如果cost太高,那么就会舍弃掉这条目标车道的reference_line, 此时放弃变道的规划,继续循环使用原车道的reference_line进行规划。

4、LANE_FOLLOW_DEFAULT_STAGE的规划逻辑在 PlanOnReferenceLine() 函数,这个函数的实现如下,关键步骤加了备注:

  1. Status LaneFollowStage::PlanOnReferenceLine(
  2. const TrajectoryPoint& planning_start_point, Frame* frame,
  3. ReferenceLineInfo* reference_line_info) {
  4. if (!reference_line_info->IsChangeLanePath()) {
  5. reference_line_info->AddCost(kStraightForwardLineCost);
  6. }
  7. ADEBUG << "planning start point:" << planning_start_point.DebugString();
  8. ADEBUG << "Current reference_line_info is IsChangeLanePath: "
  9. << reference_line_info->IsChangeLanePath();
  10. auto ret = Status::OK();
  11. for (auto* task : task_list_) {
  12. const double start_timestamp = Clock::NowInSeconds();
  13. ret = task->Execute(frame, reference_line_info);
  14. const double end_timestamp = Clock::NowInSeconds();
  15. const double time_diff_ms = (end_timestamp - start_timestamp) * 1000;
  16. ADEBUG << "after task[" << task->Name()
  17. << "]:" << reference_line_info->PathSpeedDebugString();
  18. ADEBUG << task->Name() << " time spend: " << time_diff_ms << " ms.";
  19. RecordDebugInfo(reference_line_info, task->Name(), time_diff_ms);
  20. if (!ret.ok()) {
  21. AERROR << "Failed to run tasks[" << task->Name()
  22. << "], Error message: " << ret.error_message();
  23. break;
  24. }
  25. // TODO(SHU): disable reference line order changes for now
  26. // updated reference_line_info, because it is changed in
  27. // lane_change_decider by PrioritizeChangeLane().
  28. // reference_line_info = &frame->mutable_reference_line_info()->front();
  29. // ADEBUG << "Current reference_line_info is IsChangeLanePath: "
  30. // << reference_line_info->IsChangeLanePath();
  31. }
  32. RecordObstacleDebugInfo(reference_line_info);
  33. // check path and speed results for path or speed fallback
  34. reference_line_info->set_trajectory_type(ADCTrajectory::NORMAL);
  35. if (!ret.ok()) {
  36. PlanFallbackTrajectory(planning_start_point, frame, reference_line_info);
  37. }
  38. DiscretizedTrajectory trajectory;
  39. if (!reference_line_info->CombinePathAndSpeedProfile(
  40. planning_start_point.relative_time(),
  41. planning_start_point.path_point().s(), &trajectory)) {
  42. const std::string msg = "Fail to aggregate planning trajectory.";
  43. AERROR << msg;
  44. return Status(ErrorCode::PLANNING_ERROR, msg);
  45. }
  46. // determine if there is a destination on reference line.
  47. double dest_stop_s = -1.0;
  48. for (const auto* obstacle :
  49. reference_line_info->path_decision()->obstacles().Items()) {
  50. if (obstacle->LongitudinalDecision().has_stop() &&
  51. obstacle->LongitudinalDecision().stop().reason_code() ==
  52. STOP_REASON_DESTINATION) {
  53. SLPoint dest_sl = GetStopSL(obstacle->LongitudinalDecision().stop(),
  54. reference_line_info->reference_line());
  55. dest_stop_s = dest_sl.s();
  56. }
  57. }
  58. for (const auto* obstacle :
  59. reference_line_info->path_decision()->obstacles().Items()) {
  60. if (obstacle->IsVirtual()) {
  61. continue;
  62. }
  63. if (!obstacle->IsStatic()) {
  64. continue;
  65. }
  66. if (obstacle->LongitudinalDecision().has_stop()) {
  67. bool add_stop_obstacle_cost = false;
  68. if (dest_stop_s < 0.0) {
  69. add_stop_obstacle_cost = true;
  70. } else {
  71. SLPoint stop_sl = GetStopSL(obstacle->LongitudinalDecision().stop(),
  72. reference_line_info->reference_line());
  73. if (stop_sl.s() < dest_stop_s) {
  74. add_stop_obstacle_cost = true;
  75. }
  76. }
  77. if (add_stop_obstacle_cost) {
  78. static constexpr double kReferenceLineStaticObsCost = 1e3;
  79. reference_line_info->AddCost(kReferenceLineStaticObsCost);
  80. }
  81. }
  82. }
  83. if (FLAGS_enable_trajectory_check) {
  84. if (ConstraintChecker::ValidTrajectory(trajectory) !=
  85. ConstraintChecker::Result::VALID) {
  86. const std::string msg = "Current planning trajectory is not valid.";
  87. AERROR << msg;
  88. return Status(ErrorCode::PLANNING_ERROR, msg);
  89. }
  90. }
  91. reference_line_info->SetTrajectory(trajectory);
  92. reference_line_info->SetDrivable(true);
  93. return Status::OK();
  94. }

5、本章节主要以LANE_FOLLOW_DEFAULT_STAGE为例,介绍了apollo中stage这个模块的运行机制,LANE_FOLLOW_DEFAULT_STAGE是NOP功能下最常用到的一个stage,在下一章节会详细介绍这个stage的逻辑。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/655805
推荐阅读
  

闽ICP备14008679号