Apollo9.0 Planning2.0决策规划算法代码详细解析 (5): OnLanePlanning::Init()

🌟 面向自动驾驶规划算法工程师的专属指南 🌟

欢迎来到《Apollo9.0 Planning2.0决策规划算法代码详细解析》专栏!本专栏专为自动驾驶规划算法工程师量身打造,旨在通过深入剖析Apollo9.0开源自动驾驶软件栈中的Planning2.0模块,帮助读者掌握自动驾驶决策规划算法的核心原理与实现细节。

🔍 VSCode+GDB:精准调试,洞悉代码逻辑 🔍

在自动驾驶算法的开发过程中,调试是至关重要的一环。本专栏将带你深入掌握VSCode+GDB这一强大的调试工具组合,让你能够逐行分析代码,精准定位问题,从而洞悉算法背后的逻辑与原理。通过实战演练,你将学会如何高效地利用调试工具,提升代码质量与开发效率。

💻 C++语法同步讲解:构建算法基石 💻

C++作为自动驾驶领域的主流编程语言,其重要性不言而喻。本专栏在解析算法代码的同时,将同步介绍C++语法,从基础到进阶,涵盖数据类型、控制结构、面向对象编程等核心知识点。通过系统学习,你将能够熟练运用C++语言编写高效、可维护的自动驾驶规划算法代码。

🚀 掌握自动驾驶PNC工程师从业能力 🚀

完成本专栏的学习后,你将具备自动驾驶PNC(规划、导航与控制)工程师的从业能力。你将能够深入理解自动驾驶决策规划算法的设计思路与实现方法,掌握Apollo9.0 Planning2.0模块的核心技术,为自动驾驶汽车的智能决策提供有力支持。

🚀 Apollo9.0 Planning2.0:探索自动驾驶技术前沿 🚀

Apollo9.0作为百度开源的自动驾驶软件栈,其Planning2.0模块在决策规划算法方面取得了显著进展。本专栏将带你深入探索Apollo9.0 Planning2.0的奥秘,揭秘其背后的算法原理与实现细节。通过系统学习,你将能够站在自动驾驶技术的前沿,为自动驾驶汽车的未来发展贡献力量。

🎉 立即加入,开启自动驾驶规划算法之旅 🎉

无论你是自动驾驶领域的初学者,还是有一定经验的工程师,本专栏都将为你提供宝贵的学习资源与实战机会。立即加入《Apollo9.0 Planning2.0决策规划算法代码详细解析》专栏,与我们一起探索自动驾驶技术的无限可能,共同推动自动驾驶技术的未来发展!

一、OnLanePlanning模块介绍

Apollo的OnLanePlanning是自动驾驶框架中的一个核心模块,它主要负责在有车道线的道路上进行路径规划。以下是对OnLanePlanning的详细介绍:

1、模块位置与继承关系

  • OnLanePlanning的源代码位于modules\planning\on_lane_planning.h
  • 它继承自PlanningBase类,与NaviPlanning类并列,是Apollo规划模块中的两种主要规划方式之一。

2、初始化与运行

  • OnLanePlanning的初始化逻辑主要在Init函数中实现。该函数负责分配具体的Planner(规划器),并启动参考线提供器(ReferenceLineProvider)。
  • 在初始化过程中,会根据配置文件选择默认的规划器,通常为PublicRoadPlanner。

3、核心功能

  • OnLanePlanning的核心功能是在有车道线的道路上进行路径规划。它基于高精地图和车辆当前状态,生成一条安全且舒适的行驶路径。
  • 该模块会考虑实际临时或移动障碍物,以及速度、动力学约束等因素,尽量按照规划路径进行轨迹规划。
  • OnLanePlanning还包含决策功能,能够根据不同的场景(如红绿灯路口、停车场景等)进行决策,并生成相应的规划轨迹。

4、与其他模块的交互

  • OnLanePlanning的上游模块包括Localization(定位模块)、Prediction(预测模块)和Routing(路由模块)。这些模块为OnLanePlanning提供必要的输入信息,如车辆当前位置、障碍物预测信息和全局路线指引等。
  • OnLanePlanning的下游模块是Control(控制模块)。它将生成的规划轨迹传递给Control模块,由Control模块执行具体的车辆控制操作。

5、场景应用

  • OnLanePlanning主要适用于城区和高速公路等具有车道线的道路场景。在这些场景中,它能够有效地进行路径规划和决策,确保车辆的安全行驶。

6、技术特点

  • 基于车道线的规划:OnLanePlanning的规划算法都是基于车道的,即基于参考线的规划。这使得它能够更好地适应具有车道线的道路场景。
  • 实时性强:采用事件触发方式运行,能够根据车辆状态和道路情况实时生成规划轨迹。
  • 安全性高:在规划过程中会考虑实际临时或移动障碍物以及速度、动力学约束等因素,确保生成的规划轨迹是安全的。

综上所述,Apollo的OnLanePlanning是一个功能强大且高效的路径规划模块。它能够在具有车道线的道路场景中为自动驾驶车辆提供安全且舒适的行驶路径。

二、OnLanePlanning 类定义分析

class OnLanePlanning : public PlanningBase {
 public:
  explicit OnLanePlanning(const std::shared_ptr<DependencyInjector>& injector)
      : PlanningBase(injector) {}

  virtual ~OnLanePlanning();

  std::string Name() const override;

  common::Status Init(const PlanningConfig& config) override;

  void RunOnce(const LocalView& local_view,
               ADCTrajectory* const ptr_trajectory_pb) override;

  common::Status Plan(
      const double current_time_stamp,
      const std::vector<common::TrajectoryPoint>& stitching_trajectory,
      ADCTrajectory* const trajectory) override;

 private:
  common::Status InitFrame(const uint32_t sequence_num,
                           const common::TrajectoryPoint& planning_start_point,
                           const common::VehicleState& vehicle_state);

  common::VehicleState AlignTimeStamp(const common::VehicleState& vehicle_state,
                                      const double curr_timestamp) const;

  void ExportReferenceLineDebug(planning_internal::Debug* debug);
  bool CheckPlanningConfig(const PlanningConfig& config);
  void GenerateStopTrajectory(ADCTrajectory* ptr_trajectory_pb);
  void ExportFailedLaneChangeSTChart(const planning_internal::Debug& debug_info,
                                     planning_internal::Debug* debug_chart);
  void ExportOnLaneChart(const planning_internal::Debug& debug_info,
                         planning_internal::Debug* debug_chart);
  void ExportOpenSpaceChart(const planning_internal::Debug& debug_info,
                            const ADCTrajectory& trajectory_pb,
                            planning_internal::Debug* debug_chart);
  void AddOpenSpaceOptimizerResult(const planning_internal::Debug& debug_info,
                                   planning_internal::Debug* debug_chart);
  void AddPartitionedTrajectory(const planning_internal::Debug& debug_info,
                                planning_internal::Debug* debug_chart);

  void AddStitchSpeedProfile(planning_internal::Debug* debug_chart);

  void AddPublishedSpeed(const ADCTrajectory& trajectory_pb,
                         planning_internal::Debug* debug_chart);

  void AddPublishedAcceleration(const ADCTrajectory& trajectory_pb,
                                planning_internal::Debug* debug);

  void AddFallbackTrajectory(const planning_internal::Debug& debug_info,
                             planning_internal::Debug* debug_chart);

 private:
  PlanningCommand last_command_;
  std::unique_ptr<ReferenceLineProvider> reference_line_provider_;
  Smoother planning_smoother_;
};

构造函数与析构函数

  • 构造函数explicit OnLanePlanning(const std::shared_ptr<DependencyInjector>& injector)接收一个DependencyInjector的智能指针,用于依赖注入。这是Apollo框架中常用的设计模式,用于解耦模块间的依赖关系。
  • 析构函数virtual ~OnLanePlanning();是一个虚析构函数,确保当通过基类指针删除派生类对象时,能够正确调用派生类的析构函数。

成员函数

  • Name:返回规划模块的名称,即"OnLanePlanning"
  • Init:初始化函数,接收一个PlanningConfig对象作为配置参数,并返回初始化状态。在初始化过程中,会进行一系列的配置检查和资源分配。
  • RunOnce:规划模块的主逻辑函数,由定时器周期触发。它接收一个LocalView对象(包含局部环境信息)和一个ADCTrajectory指针(用于存储生成的规划轨迹)。
  • Plan:根据当前时间戳、拼接轨迹和规划轨迹指针,生成具体的规划轨迹。这个函数可能用于在特定情况下(如重新规划)生成新的轨迹。

私有成员函数

  • InitFrame:初始化规划帧,包括设置序列号、规划起点和车辆状态。
  • AlignTimeStamp:对齐车辆状态的时间戳,确保与当前时间一致。
  • ExportReferenceLineDebug:导出参考线的调试信息。
  • CheckPlanningConfig:检查规划配置的有效性。
  • GenerateStopTrajectory:生成停车轨迹。
  • ExportFailedLaneChangeSTChartExportOnLaneChartExportOpenSpaceChart:导出不同场景下的调试图表,包括车道变换失败、在车道上行驶和开放空间场景。
  • AddOpenSpaceOptimizerResultAddPartitionedTrajectory:向调试图表中添加开放空间优化结果和分区轨迹。
  • AddStitchSpeedProfileAddPublishedSpeedAddPublishedAcceleration:向调试图表中添加拼接速度曲线、发布的速度和加速度信息。
  • AddFallbackTrajectory:向调试图表中添加备用轨迹。

成员变量

  • last_command_:记录上一个规划命令。
  • reference_line_provider_:一个指向ReferenceLineProvider的唯一指针,用于提供参考线信息。
  • planning_smoother_:一个平滑器对象,用于对规划轨迹进行平滑处理。

总结

OnLanePlanning类是一个功能丰富的路径规划模块,它基于车道线进行规划,并考虑了多种场景和约束条件。通过提供的接口和成员函数,它能够生成安全、舒适且符合交通规则的行驶轨迹。此外,该类还提供了丰富的调试信息导出功能,有助于开发者进行问题诊断和性能优化。

三、OnLanePlanning::Init() 介绍

代码解析:

Status OnLanePlanning::Init(const PlanningConfig& config) {
  if (!CheckPlanningConfig(config)) {
    return Status(ErrorCode::PLANNING_ERROR,
                  "planning config error: " + config.DebugString());
  }

  PlanningBase::Init(config);

  // clear planning history
  injector_->history()->Clear();

  // clear planning status
  injector_->planning_context()->mutable_planning_status()->Clear();

  // load map
  hdmap_ = HDMapUtil::BaseMapPtr();
  ACHECK(hdmap_) << "Failed to load map";

  // instantiate reference line provider
  const ReferenceLineConfig* reference_line_config = nullptr;
  if (config_.has_reference_line_config()) {
    reference_line_config = &config_.reference_line_config();
  }
  reference_line_provider_ = std::make_unique<ReferenceLineProvider>(
      injector_->vehicle_state(), reference_line_config);
  reference_line_provider_->Start();

  // dispatch planner
  LoadPlanner();
  if (!planner_) {
    return Status(
        ErrorCode::PLANNING_ERROR,
        "planning is not initialized with config : " + config_.DebugString());
  }

  if (config_.learning_mode() != PlanningConfig::NO_LEARNING) {
    PlanningSemanticMapConfig renderer_config;
    ACHECK(apollo::cyber::common::GetProtoFromFile(
        FLAGS_planning_birdview_img_feature_renderer_config_file,
        &renderer_config))
        << "Failed to load renderer config"
        << FLAGS_planning_birdview_img_feature_renderer_config_file;

    BirdviewImgFeatureRenderer::Instance()->Init(renderer_config);
  }

  traffic_decider_.Init(injector_);

  start_time_ = Clock::NowInSeconds();
  return planner_->Init(injector_, FLAGS_planner_config_path);
}

OnLanePlanning::Init 函数是一个初始化函数,用于设置和准备OnLanePlanning类的实例。这个函数执行了以下关键步骤:

  1. 配置检查
    • 调用CheckPlanningConfig函数来验证传入的PlanningConfig配置对象是否有效。
    • 如果配置无效,则返回一个包含错误代码和错误信息的Status对象。
  2. 基类初始化
    • 调用基类PlanningBaseInit函数,传入相同的配置对象。
  3. 清除历史记录和状态
    • 通过injector_(一个依赖注入器)清除规划历史和规划状态。
  4. 加载地图
    • 使用HDMapUtil::BaseMapPtr()获取高清地图的指针,并存储在hdmap_成员变量中。
    • 使用ACHECK宏来确保地图加载成功;如果失败,则打印错误信息并终止程序。
  5. 实例化参考线提供者
    • 检查配置中是否包含参考线配置。
    • 根据配置(如果有)和车辆状态实例化ReferenceLineProvider
    • 启动参考线提供者。
  6. 加载规划器
    • 调用LoadPlanner函数来加载和设置规划器。
    • 如果规划器未成功加载,则返回一个包含错误代码和错误信息的Status对象。
  7. 学习模式设置(可选):
    • 如果配置中指定了学习模式,则加载渲染器配置并初始化BirdviewImgFeatureRenderer
  8. 交通决策器初始化
    • 调用traffic_decider_Init函数,传入依赖注入器。
  9. 记录开始时间
    • 记录初始化过程的开始时间到start_time_成员变量中。
  10. 规划器初始化
    • 最后,调用规划器的Init函数,传入依赖注入器和规划器配置路径。
    • 返回规划器初始化的结果。

这个函数是OnLanePlanning类的一个重要组成部分,因为它负责设置类的初始状态,包括加载必要的配置、资源和服务,以及确保所有依赖项都已正确初始化。如果初始化过程中的任何步骤失败,函数将返回一个包含错误信息的Status对象,这有助于调用者了解初始化失败的原因。

c++知识,派生来中调用基类函数:

在init函数中,调用了基类的init函数,

  PlanningBase::Init(config);
在C++中,派生类可以通过多种方式调用基类的函数。以下是几种常见的方法:

1. 直接调用基类成员函数(如果它不是虚函数)

如果基类的成员函数不是虚函数,派生类可以直接通过基类名和作用域解析运算符(::)来调用它,或者使用this->指针(虽然在这种情况下通常不是必需的)。但是,更常见的是直接使用成员函数名,因为编译器会根据上下文自动解析为基类的版本(如果派生类没有覆盖它)。

class Base {  
public:  
    void NonVirtualFunction() {  
        // 基类实现  
    }  
};  
 
class Derived : public Base {  
public:  
    void SomeFunction() {  
        // 直接调用基类的非虚函数  
        Base::NonVirtualFunction();  
        // 或者简单地调用(如果Derived没有同名函数)  
        NonVirtualFunction();  
    }  

};
2. 通过基类指针或引用调用虚函数

如果基类的成员函数是虚函数,并且派生类提供了覆盖(override),那么通过基类指针或引用调用该函数时,将调用派生类的版本。但是,有时你可能希望调用基类的版本。这可以通过使用Base::前缀来实现。

class Base {  
public:  
    virtual void VirtualFunction() {  
        // 基类实现  
    }  
};  
 
class Derived : public Base {  
public:  
    void VirtualFunction() override {  
        // 派生类实现  
        // 调用基类的虚函数  
        Base::VirtualFunction();  
    }  

};

在上面的例子中,当Derived的VirtualFunction被调用时,它首先会调用基类的VirtualFunction,然后执行自己的实现。


3. 使用this->指针调用虚函数(显式地调用基类版本)

虽然不常见,但你也可以使用this->指针和Base::前缀来显式地调用基类的虚函数。这通常用于在派生类的覆盖函数中调用基类的实现。

class Derived : public Base {  
public:  
    void VirtualFunction() override {  
        // 使用this指针和Base::前缀调用基类的虚函数  
        this->Base::VirtualFunction();  
        // 或者简单地  
        Base::VirtualFunction();  
        // 派生类自己的实现  
    }  

};
4. 构造函数和析构函数中的调用

在派生类的构造函数中,如果需要调用基类的构造函数,这必须在初始化列表中完成。对于析构函数,当派生类的析构函数被调用时,它会自动调用基类的析构函数(如果基类有析构函数的话)。

class Base {  
public:  
    Base() { /* 基类构造函数实现 */ }  
    virtual ~Base() { /* 基类析构函数实现 */ }  
};  
 
class Derived : public Base {  
public:  
    Derived() : Base() { /* 派生类构造函数实现 */ }  
    ~Derived() override { /* 派生类析构函数实现;基类析构函数会自动调用 */ }  

};

请注意,在析构函数中,你通常不需要(也不应该)显式地调用基类的析构函数,因为C++会自动处理这一点。然而,在构造函数中,你必须通过初始化列表来调用基类的构造函数。

总的来说,调用基类函数的方法取决于函数是否是虚函数、你是否有一个指向基类或派生类对象的指针或引用,以及你是在构造函数、析构函数还是普通成员函数中调用它。

四、reference_line_provider_参考线生成器线程启动

reference_line_provider_使用异步的方式进行参考线的更新与坐标系的计算,

  reference_line_provider_ = std::make_unique<ReferenceLineProvider>(
      injector_->vehicle_state(), reference_line_config);
  reference_line_provider_->Start();
bool ReferenceLineProvider::Start() {
  if (FLAGS_use_navigation_mode) {
    return true;
  }
  if (!is_initialized_) {
    AERROR << "ReferenceLineProvider has NOT been initiated.";
    return false;
  }

  if (FLAGS_enable_reference_line_provider_thread) {
    task_future_ = cyber::Async(&ReferenceLineProvider::GenerateThread, this);
  }
  return true;
}

ReferenceLineProvider::Start 函数是 ReferenceLineProvider 类的一个成员函数,用于启动参考线生成器。下面是对该函数的详细解释:

  1. 检查导航模式
    • 首先,函数检查全局标志 FLAGS_use_navigation_mode 是否被设置。
    • 如果设置了导航模式(即 FLAGS_use_navigation_modetrue),则函数直接返回 true,表示参考线提供者已启动(在导航模式下可能不需要额外的线程或处理)。
  2. 检查初始化状态
    • 接下来,函数检查成员变量 is_initialized_,以确定 ReferenceLineProvider 是否已经被正确初始化。
    • 如果 is_initialized_false,则打印错误日志,并返回 false,表示参考线提供者未能启动。
  3. 启动参考线生成线程
    • 如果全局标志 FLAGS_enable_reference_line_provider_thread 被设置(即允许启动参考线提供者线程),则函数会调用 cyber::Async 方法来异步启动一个线程。
    • cyber::Async 方法接受一个函数指针和对象指针作为参数,这里传递的是 ReferenceLineProvider::GenerateThread 成员函数和 this 指针(指向当前 ReferenceLineProvider 对象)。
    • task_future_ 成员变量被赋值为 cyber::Async 调用返回的 future 对象,这个对象可以用于等待线程完成或获取线程的结果(如果有的话)。不过,在这个特定的代码中,task_future_ 的值似乎没有被进一步使用。
  4. 返回成功
    • 最后,如果所有检查都通过,并且线程(如果需要的话)已经启动,函数返回 true,表示参考线提供者已成功启动。

需要注意的是,这个函数中有几个关键点:

  • 全局标志(如 FLAGS_use_navigation_modeFLAGS_enable_reference_line_provider_thread)用于控制函数的行为。这些标志通常在程序启动时设置,并影响整个程序的运行。
  • 成员变量 is_initialized_ 用于跟踪 ReferenceLineProvider 对象的初始化状态。
  • cyber::Async 是 Apollo 自动驾驶软件框架中用于异步执行任务的函数。它允许程序在不阻塞主线程的情况下执行耗时的操作。

此外,这个函数的实现假设了一些外部条件,比如 is_initialized_ 应该在某处被正确设置,以及 cyber::Async 调用能够成功启动线程。在实际应用中,这些假设需要得到保证,以确保程序的正确性和稳定性。

在planning模块运行时,输入条件如下:

五、LoadPlanner(),初始化规划器

void PlanningBase::LoadPlanner() {
  // Use PublicRoadPlanner as default Planner
  std::string planner_name = "apollo::planning::PublicRoadPlanner";
  if ("" != config_.planner()) {
    planner_name = config_.planner();
    planner_name = ConfigUtil::GetFullPlanningClassName(planner_name);
  }
  planner_ =
      cyber::plugin_manager::PluginManager::Instance()->CreateInstance<Planner>(
          planner_name);
}

PlanningBase::LoadPlanner 函数是 PlanningBase 类的一个成员函数,用于加载并初始化规划器(Planner)。这个函数的具体作用如下:

  1. 设置默认规划器
    • 函数开始时,将 planner_name 设置为 "apollo::planning::PublicRoadPlanner",这是默认的规划器名称。
  2. 检查配置
    • 接下来,函数检查成员变量 config_ 中的 planner 配置项是否为空。
    • 如果 config_.planner() 不为空(即用户指定了其他的规划器),则将 planner_name 更新为用户指定的规划器名称。
    • 然后,使用 ConfigUtil::GetFullPlanningClassName 函数来获取规划器的完整类名。这个函数可能会添加一些前缀或后缀,以确保类名与实际的规划器类匹配。
  3. 创建规划器实例
    • 最后,函数使用 cyber::plugin_manager::PluginManager::Instance()->CreateInstance<Planner> 方法来创建规划器实例。
    • 这里,planner_name 被用作模板参数,告诉插件管理器要创建哪个类的实例。
    • planner_ 成员变量被赋值为新创建的规划器实例。

需要注意的是:

  • config_ 成员变量应该是一个包含规划器配置信息的对象。它可能在 PlanningBase 类的构造函数或其他成员函数中被初始化。
  • cyber::plugin_manager::PluginManager 是 Apollo 自动驾驶软件框架中用于管理插件(如规划器)的类。CreateInstance 方法根据提供的类名动态地创建类的实例。
  • Planner 是一个抽象基类或接口,定义了规划器应该实现的方法。具体的规划器类(如 PublicRoadPlanner)将继承自 Planner 并实现其方法。
  • 如果 CreateInstance 方法无法找到或创建指定的规划器类实例,它可能会返回一个空指针或抛出异常。在实际应用中,应该检查 planner_ 是否为 nullptr,并相应地处理错误情况。

此外,这个函数的实现假设了 cyber::plugin_manager::PluginManager 和相关的配置系统已经正确设置,并且能够找到并创建用户指定的规划器类实例。在实际应用中,这些假设需要得到保证,以确保程序的正确性和稳定性。

六、TrafficDecider::Init()

bool TrafficDecider::Init(const std::shared_ptr<DependencyInjector> &injector) {
  if (init_) return true;
  // Load the pipeline config.
  AINFO << "Load config path:" << FLAGS_traffic_rule_config_filename;
  // Load the pipeline of scenario.
  if (!apollo::cyber::common::LoadConfig(FLAGS_traffic_rule_config_filename,
                                         &rule_pipeline_)) {
    AERROR << "Load pipeline of Traffic decider"
           << " failed!";
    return false;
  }
  //-----------------------------------------------
  for (int i = 0; i < rule_pipeline_.rule_size(); i++) {
    auto rule =
        apollo::cyber::plugin_manager::PluginManager::Instance()
            ->CreateInstance<TrafficRule>(ConfigUtil::GetFullPlanningClassName(
                rule_pipeline_.rule(i).type()));
    if (!rule) {
      AERROR << "Init of Traffic rule" << rule_pipeline_.rule(i).name()
             << " failed!";
      return false;
    }
    rule->Init(rule_pipeline_.rule(i).name(), injector);
    rule_list_.push_back(rule);
  }

  init_ = true;
  return true;
}

该函数的主要目的是初始化交通决策器,具体步骤和逻辑如下:

  1. 检查是否已经初始化:首先,函数通过检查init_成员变量的值来判断TrafficDecider是否已经初始化。如果init_true,表示已经初始化过,直接返回true

  2. 加载管道配置:接着,函数通过打印日志信息表明它正在加载配置文件的路径,这个路径是通过宏FLAGS_traffic_rule_config_filename指定的。然后,使用apollo::cyber::common::LoadConfig函数尝试加载该配置文件到rule_pipeline_成员变量中。如果加载失败,则打印错误信息并返回false

  3. 初始化规则列表:配置文件加载成功后,函数遍历rule_pipeline_中定义的每一条规则。对于每一条规则,它使用apollo::cyber::plugin_manager::PluginManagerCreateInstance方法来创建一个TrafficRule的实例。CreateInstance方法需要一个类名字符串作为参数,这个字符串通过ConfigUtil::GetFullPlanningClassName函数从规则配置中获取。

    • 如果CreateInstance无法创建TrafficRule实例(返回nullptr),则打印错误信息(包含规则的名字),并返回false
    • 如果实例创建成功,则调用该实例的Init方法,传入规则的名字和injector(一个依赖注入器)。
    • 将成功初始化的规则实例添加到rule_list_成员变量中,以便后续使用。
  4. 标记为已初始化:所有规则都成功初始化后,将init_成员变量设置为true,表示TrafficDecider已经初始化完成。

  5. 返回成功:最后,函数返回true,表示初始化成功。

总结来说,这个Init函数负责加载交通决策器的配置,并根据配置创建和初始化一系列的交通规则(TrafficRule)实例。如果在任何步骤中遇到错误(如配置文件加载失败、规则实例创建失败等),函数将提前返回false

 七、PublicRoadPlanner::Init()

Status PublicRoadPlanner::Init(
    const std::shared_ptr<DependencyInjector>& injector,
    const std::string& config_path) {
  Planner::Init(injector, config_path);
  LoadConfig<PlannerPublicRoadConfig>(config_path, &config_);
  scenario_manager_.Init(injector, config_);
  return Status::OK();
}

PublicRoadPlannerPlanner类的一个子类,专门用于处理公共道路场景的规划任务。下面是对这段代码的详细解读:

  1. 函数签名
    • Status PublicRoadPlanner::Init(const std::shared_ptr<DependencyInjector>& injector, const std::string& config_path)
    • 这个函数接收两个参数:一个是依赖注入器DependencyInjector的智能指针,另一个是配置文件的路径。
    • 函数返回一个Status对象,这通常用于表示操作的成功或失败状态。
  2. 调用基类初始化方法
    • Planner::Init(injector, config_path);
    • PublicRoadPlannerInit函数中,首先调用了基类PlannerInit方法,传入了相同的参数。
    • 这表明PublicRoadPlanner的初始化过程需要首先完成基类Planner的初始化。
  3. 加载配置
    • LoadConfig<PlannerPublicRoadConfig>(config_path, &config_);
    • 接下来,使用LoadConfig模板函数从指定的配置文件路径加载配置。
    • LoadConfig函数接受两个参数:配置文件的路径和一个指向配置对象(在这里是PlannerPublicRoadConfig类型的对象)的指针。
    • PlannerPublicRoadConfig是专门为PublicRoadPlanner设计的配置类,用于存储与公共道路规划相关的配置信息。
    • 加载的配置信息被存储在config_成员变量中,供后续使用。
  4. 初始化场景管理器
    • scenario_manager_.Init(injector, config_);
    • 然后,调用scenario_manager_成员变量的Init方法,同样传入了依赖注入器和配置信息。
    • scenario_manager_是负责管理和处理不同交通场景的对象。
    • 通过初始化scenario_manager_PublicRoadPlanner能够根据不同的交通场景做出相应的规划决策。
  5. 返回成功状态
    • return Status::OK();
    • 最后,函数返回一个表示操作成功的状态对象。
    • Status::OK()通常是一个静态方法,用于创建一个表示成功状态的Status对象。

总结来说,PublicRoadPlannerInit函数首先完成了基类的初始化,然后加载了专门的配置信息,并初始化了场景管理器。这个过程确保了PublicRoadPlanner在开始执行规划任务之前已经做好了充分的准备。

八、ScenarioManager::Init()

bool ScenarioManager::Init(const std::shared_ptr<DependencyInjector>& injector,
                           const PlannerPublicRoadConfig& planner_config) {
  if (init_) {
    return true;
  }
  injector_ = injector;
  for (int i = 0; i < planner_config.scenario_size(); i++) {
    auto scenario = PluginManager::Instance()->CreateInstance<Scenario>(
        ConfigUtil::GetFullPlanningClassName(
            planner_config.scenario(i).type()));
    ACHECK(scenario->Init(injector_, planner_config.scenario(i).name()))
        << "Can not init scenario" << planner_config.scenario(i).name();
    scenario_list_.push_back(scenario);
    if (planner_config.scenario(i).name() == "LANE_FOLLOW") {
      default_scenario_type_ = scenario;
    }
  }
  AINFO << "Load scenario list:" << planner_config.DebugString();
  current_scenario_ = default_scenario_type_;
  init_ = true;
  return true;
}

ScenarioManager负责管理不同交通场景规划的对象。下面是对这段代码的详细解读:

  1. 函数签名
    • bool ScenarioManager::Init(const std::shared_ptr<DependencyInjector>& injector, const PlannerPublicRoadConfig& planner_config)
    • 函数接收两个参数:一个是依赖注入器DependencyInjector的智能指针,另一个是PlannerPublicRoadConfig类型的配置对象(通常这种配置对象很大,使用引用传递以避免不必要的复制)。
    • 函数返回一个布尔值,表示初始化是否成功。
  2. 检查是否已经初始化
    • if (init_) { return true; }
    • 如果ScenarioManager已经初始化过(init_true),则直接返回true,避免重复初始化。
  3. 保存依赖注入器
    • injector_ = injector;
    • 将传入的依赖注入器智能指针保存到成员变量injector_中,供后续使用。
  4. 遍历配置中的场景
    • 使用for循环遍历planner_config中定义的场景列表。
    • 对于每个场景,使用PluginManager::Instance()->CreateInstance<Scenario>方法创建一个Scenario的实例。
      • 这个方法需要一个类名字符串作为参数,这个字符串通过ConfigUtil::GetFullPlanningClassName函数从场景配置中获取。
  5. 初始化场景实例
    • 使用ACHECK宏来检查场景实例的Init方法是否成功。
      • ACHECK是一个断言宏,如果条件不满足(即scenario->Init(...)返回false),则打印错误信息并终止程序。
      • 错误信息包括无法初始化的场景名称。
    • 如果初始化成功,将场景实例添加到scenario_list_成员变量中。
  6. 设置默认场景
    • 如果场景的名称是"LANE_FOLLOW",则将该场景设置为默认场景(default_scenario_type_)。
  7. 打印加载的场景列表
    • 使用AINFO宏打印加载的场景列表的调试信息。
    • planner_config.DebugString()方法可能返回一个包含所有场景配置的字符串表示。
  8. 设置当前场景
    • 将当前场景(current_scenario_)设置为默认场景。
  9. 标记为已初始化
    • init_成员变量设置为true,表示ScenarioManager已经初始化完成。
  10. 返回成功
    • 函数返回true,表示初始化成功。

总结来说,ScenarioManagerInit函数负责根据配置信息加载和初始化一系列的场景(Scenario)实例,并设置一个默认场景。如果在任何步骤中遇到错误(如场景实例创建失败、场景初始化失败等),函数将使用ACHECK宏终止程序。成功初始化后,函数将标记ScenarioManager为已初始化状态,并返回true

### 回答1: Apollo Planning决策规划算法在无人驾驶领域中被广泛应用,在自动驾驶车辆中起着至关重要的作用。该算法主要通过对车辆周围环境的感知和分析,实现智能驾驶路线的规划决策,确保车辆安全行驶。 该算法代码主要包含三个部分:感知模块、规划模块和控制模块。其中感知模块主要负责采集车辆周围的环境信息,包括车辆所处的位置、路况、障碍物等。规划模块通过对这些信息的分析,提出一系列可能的驾驶路线,并通过评估这些路线的优劣来选择最佳驾驶路线。控制模块负责实现规划模块中选择的最佳驾驶路线,并控制车辆按照路线行驶。 在Apollo Planning决策规划算法中,规划模块是实现驾驶决策的最重要模块,也是最具技术难度的模块。规划模块通过对车辆当前状态和环境信息的分析,提出一系列汽车驾驶路线。该算法采用在线生成路线方案的方法,路线生成的步骤如下: 1. 动态路径规划:根据车辆的位置和行驶状态,实时选择当前最佳的驾驶路线。 2. 静态路线生成:基于当前车辆所处的环境信息,生成固定的驾驶路线。 3. 组合路径规划:将动态路径规划和静态路线生成相结合,生成最终的驾驶路线。 除此之外,Apollo Planning决策规划算法还包括计算机视觉、机器学习、深度学习和人工智能等技术,这些技术的综合应用使得Apollo Planning决策规划算法成为无人驾驶领域中应用最广泛的决策规划算法。 ### 回答2: Apollo Planning决策规划算法是一种用于自动驾驶系统的规划算法。该算法的主要作用是实时生成安全、有效且符合路况的路径以实现自动驾驶功能。本文将对该算法进行详细解析Apollo Planning决策规划算法主要包括三个步骤:路线规划、运动规划决策规划。具体代码如下: 1. 路线规划 ```c++ bool Planning::PlanOnReferenceLine() { std::vector<const hdmap::HDMap*> hdmap_vec; hdmap_vec.reserve(1); if (!GetHdmapOnRouting(current_routing_, &hdmap_vec)) { AERROR << "Failed to get hdmap on current routing with " << current_routing_.ShortDebugString(); return false; } const auto& reference_line_info = reference_line_infos_.front(); std::vector<ReferencePoint> ref_points; if (!CreateReferenceLineInfo(hdmap_vec.front(), reference_line_info, &ref_points)) { AERROR << "Failed to create reference line from routing"; return false; } // Smooth reference line Spline2d smoothed_ref_line; std::vector<double> s_refs; std::vector<double> l_refs; std::vector<double> headings; std::vector<double> kappas; std::vector<double> dkappas; if (!SmoothReferenceLine(ref_points, &smoothed_ref_line, &s_refs, &l_refs, &headings, &kappas, &dkappas)) { AERROR << "Failed to smooth reference line"; return false; } reference_line_info.SetTrajectory(&smoothed_ref_line); reference_line_info.SetReferenceLine(&ref_points); // set origin point if (!reference_line_info.SLToXY(s_refs.front(), 0.0, &origin_point_)) { AERROR << "Failed to get origin point on reference line"; return false; } return true; } ``` 在路线规划阶段中,Apollo Planning决策规划算法首先获取当前行驶路线和高精度地图数据。然后根据行驶路线和地图数据构建参考线,对参考线进行平滑处理,得到平滑后的参考线。此时我们可以得到平滑后的参考线的位置、方向和曲率等信息,这些信息将作为后面的运动和决策规划的输入。 2. 运动规划 ```c++ bool Planning::PlanOnPrediction() { PredictionObstacles prediction_obstacles; if (!GetPrediction(&prediction_obstacles)) { AERROR << "Prediction failed"; return false; } std::vector<Obstacle> obstacles; if (!BuildObstacle(prediction_obstacles, &obstacles)) { AERROR << "Unable to build obstacle"; return false; } const auto& reference_line_info = reference_line_infos_.front(); const auto& reference_line = reference_line_info.reference_line(); SpeedData speed_data; Cruiser::PlanningTarget planning_target; Status status = cruiser_->Plan(reference_line_info, obstacles, 0.0, reference_line.Length(), &speed_data, &planning_target); if (status != Status::OK()) { AERROR << "Failed to plan path with status: " << status; return false; } RecordDebugInfo(reference_line_info, obstacles, speed_data); return true; } ``` 运动规划主要用于生成车辆在参考线上的运行轨迹。在运动规划阶段,Apollo Planning决策规划算法首先获取预测障碍物信息,将预测的障碍物转化为Obstacle对象。然后根据当前平滑后的参考线、障碍物等信息进行运动规划。运动规划的目标是生成符合规划目标的速度曲线。最后,Apollo Planning决策规划算法记录调试信息,以便后续分析调试。 3. 决策规划 ```c++ bool Planning::MakeDecision() { const auto& reference_line_info = reference_line_infos_.front(); const auto& reference_line = reference_line_info.reference_line(); std::vector<const Obstacle*> obstacles; if (!Obstacle::CreateObstacleRegions(FLAGS_max_distance_obstacle, reference_line_info, &obstacles)) { AERROR << "Failed to create obstacle regions"; return false; } for (auto obstacle_ptr : obstacles) { const auto& obstacle = *obstacle_ptr; if (obstacle.IsVirtual()) { continue; } if (obstacle.IsStatic()) { continue; } if (obstacle.type() == PerceptionObstacle::BICYCLE || obstacle.type() == PerceptionObstacle::PEDESTRIAN) { continue; } const auto& nearest_path_point = obstacle.nearest_point(); const SLPoint obstacle_sl = reference_line_info.xy_to_sl(nearest_path_point); if (obstacle_sl.s() < -FLAGS_max_distance_obstacle || obstacle_sl.s() > reference_line.Length() + FLAGS_max_distance_obstacle) { continue; } ObjectDecisionType decision; decision.mutable_avoid(); decision.mutable_avoid()->set_distance_s(-obstacle_sl.s()); reference_line_info.AddCost(&obstacle, &decision); } std::vector<ObjectDecisionType> decisions; if (!traffic_rule_manager_.ApplyRule(reference_line_info, &decisions)) { AERROR << "Failed to apply traffic rule manager"; return false; } reference_line_info.SetDecision(decisions); return true; } ``` 决策规划是基于当前环境信息和规划的路径等输入信息,实时生成控制命令的过程。在Apollo Planning决策规划算法中,决策规划阶段根据当前参考线、障碍物等信息生成决策。该算法根据不同的规则和策略,生成不同的控制命令,以保证车辆安全、有效地运行。 综上,Apollo Planning决策规划算法自动驾驶系统中重要的规划算法之一,它通过路线规划、运动规划决策规划三个步骤,实现了安全、有效和符合路况的路径规划,为自动驾驶车辆的控制提供了重要的支持。 ### 回答3: Apollo Planning(阿波罗规划)是百度自动驾驶平台Apollo中的一种决策规划算法,主要用于规划车辆的驾驶行为。该算法基于深度强化学习,使用了运动学模型和环境感知技术,可以根据车辆当前位置和目的地,生成一条最优的行驶路径,包括车辆的控制指令和行驶速度等。 该算法的核心技术是深度强化学习,它通过对驾驶过程进行大量的仿真,让计算机通过自我学习得到驾驶规则,使车辆能够根据不同的场景做出最优的决策。具体而言,算法先通过神经网络生成一系列潜在的行动策略,然后通过与环境进行交互、执行行动并接收环境反馈来评估每个策略的优劣,最终选取最优策略进行执行。 在实现上,Apollo Planning算法主要由四个模块构成:感知模块、规划模块、执行模块和控制模块。感知模块主要用于获取车辆周围环境的信息,包括车辆位置、速度、道路情况、交通灯等;规划模块根据感知模块提供的信息和车辆的目的地,生成一条最优的行驶路径;执行模块则根据规划模块生成的路径信息,实现车辆的自主驾驶;控制模块则根据执行模块生成的控制指令,控制车辆的加速、刹车、转向等行为。 在算法实现上,Apollo Planning采用了C++编程语言,结合ROS框架实现各模块之间的数据交互和代码复用,保证了算法的高效性和可维护性。算法代码实现方面还采用了许多优化技术,包括多线程并发执行、高效的数据结构和算法等,以提升算法的运行效率和稳定性。 总之,Apollo Planning是一种基于深度强化学习的决策规划算法,具有高效、自主、可靠等特点,在智能驾驶领域具有广泛应用前景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自动驾驶Player

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值