Apollo:modules/planning/planner/planner.h学习

源码分析

在 apollo/modules/planning/planner/planner.h 文件中,定义了2个类:Planner类和 PlannerWithReferenceLine类。

Planner

在这里插入图片描述

  • Planner类是所有规划器的基类(纯虚类),重要函数有Init() 和 Plan()。

在这里插入图片描述

最重要的是virtual bool Plan(). 可以使得在运行时可以执行不同的planning算法。

  • 参数1:planning起始点
  • 参数2:当前帧
  • 参数3:路径规划结果集,由一系列离散的轨迹点组成。
  • 目的:根据历史行驶的一系列轨迹节点,并结合Perception模块+Prediction模块+Decision模块+Localization地图定位模块,来进行推算未来一段时间的行驶轨迹。本质是路径规划算法

Planner有三个成员变量: PlanningConfig, ScenarioManager, Scenario.

  • PlanningConfig是定义在planning_config.proto中, 由planning_config.pb.txt文件配置。

在这里插入图片描述

PlannerWithReferenceLine

  • PlannerWithReferenceLine类 也是继承自 Planner类
    在这里插入图片描述

  • 重要函数有PlanOnReferenceLine()。

在这里插入图片描述

继承它的:

class LatticePlanner : public PlannerWithReferenceLine {
    
    };
 
/**
 * @class NaviPlanner
 * @brief NaviPlanner is a planner based on real-time relative maps. It uses the
 * vehicle's FLU (Front-Left-Up) coordinate system to accomplish tasks such as
 * cruising, following, overtaking, nudging, changing lanes and stopping.
 * Note that NaviPlanner is only used in navigation mode (turn on navigation
 * mode by setting "FLAGS_use_navigation_mode" to "true") and do not use it in
 * standard mode.
 */
class NaviPlanner : public PlannerWithReferenceLine {
    
    };
 
 
/**
 * @class PublicRoadPlanner
 * @brief PublicRoadPlanner is an expectation maximization planner.
 */
 
class PublicRoadPlanner : public PlannerWithReferenceLine{
    
    };
 
 
/**
 * @class RTKReplayPlanner
 * @brief RTKReplayPlanner is a derived class of Planner.
 *        It reads a recorded trajectory from a trajectory file and
 *        outputs proper segment of the trajectory according to vehicle
 * position.
 */
class RTKReplayPlanner : public PlannerWithReferenceLine{
    
    };

两大流程

初始化流程

  • launch命令启动,由cyber的Init()触发。简化流程如下:
PlanningComponent::Init() //由Cyber系统初始化调用
OnLanePlanning::OnLanePlanning() //在PlanningComponent::Init()中调用,由use_navigation_mode标志位决定
OnLanePlanning::Init() //在PlanningComponent::Init()中调用
LatticePlanner::LatticePlanner() //在OnLanePlanning::init()中间接调用,由PlannerDispatcher::RegisterPlanners()直接调用
LatticePlanner::Init() //在OnLanePlanning::init()中调用

消息响应流程(运动规划)

由Cyber中的Timer触发,简化流程如下:

PlanningComponent::Proc() //由Cyber系统定时器调用
OnLanePlanning::RunOnce() //由PlanningComponent::Proc()调用
OnLanePlanning::Plan() //由OnLanePlanning::RunOnce()调用
LatticePlanner::Plan() //由OnLanePlanning::Plan()调用
LatticePlanner::PlanOnReferenceLine() //由LatticePlanner::Plan()调用,具体的基于参考线的规划工作

实现

4种规划器

这两个类都是纯虚类,那么谁来实现它们呢?

从上面可以看出,它们是用来生成规划轨迹的。简单来说就是规划轨迹的具体实现。

我们先看下Planner目录结构,一共实现了5种Planner:

 open_space        // open space planner
.
├── BUILD
├── navi_planner_dispatcher.cc
├── navi_planner_dispatcher.h
├── navi_planner_dispatcher_test.cc
├── on_lane_planner_dispatcher.cc
├── on_lane_planner_dispatcher.h
├── on_lane_planner_dispatcher_test.cc
├── planner_dispatcher.cc
├── planner_dispatcher.h
├── planner.h
├── lattice           // lattice planner
├── navi              // navi planner
├── public_road       // public road planner
└── rtk               // rtk planner

它们的结构如下图所示:
在这里插入图片描述

这5个Planner的说明如下表所示:每个规划器针对不同的场景和问题。

名称 加入版本 类型 说明
RTKReplayPlanner 1.0 RTK
  • 根据录制的轨迹来规划行车路线。实现了循迹算法
  • 是比较原始的规划器,所以不用多做说明
PublicRoadPlanner 1.5 PUBLIC_ROAD
  • 开放道路的轨迹规划器,实现了EM算法的规划器,这是目前的默认Planner。
LatticePlanner 2.5 LATTICE
  • 基于网格算法的轨迹规划器。主要用于高速公路场景
NaviPlanner 3.0 NAVI
  • 基于实时相对地图的规划器。也叫做导航规划,主要用于高速公路
  • 最新加入的规划器,目前看来还需要更多时间的验证,我们暂时也不会过多讲解
OpenSpacePlanner 3.5 OPEN_SPACE
  • 自主泊车规划器,主要应用于自主泊车和狭窄路段的掉头
  • 算法源于论文:《Optimization-Based Collision Avoidance》。
  • 最新加入的规划器,目前看来还需要更多时间的验证,我们暂时也不会过多讲解

Apollo公开课里对两个较为成熟的Planner:EM Planner和Lattice Planner做了对比,我们可以一起来看一下:

EM Planner Lattice Planner
横向纵向分开求解 横向纵向同时求解
参数较多(DP/QP, Path/Speed) 参数较少且统一
流程复杂 流程简单
单周期解空间受限 简单场景解空间较大
能适应复杂场景 适合简单场景
适合城市道路 适合高速场景

RTKReplayPlanner,PublicRoadPlanner,NaviPlanner,LatticePlanner,都实现了继承自Planner类的Plan()函数和继承自PlannerWithReferenceLine类的PlanOnReferenceLine()函数。在执行具体的规划任务时,都是在Plan()中调用PlanOnReferenceLine(),从而获得规划的轨迹结果。也就是说,最底层的规划方法,是在各规划器的PlanOnReferenceLine()中实现。
在这里插入图片描述
其大致流程如下:

在这里插入图片描述

  • PlanningComponent在cyber中注册
  • 选择Planning
  • 根据不同的Dispatcher,分发Planner

具体类图如下所示:

在这里插入图片描述

补充

在apollo中,规划分为三种模式:

  • OnLanePlanning(车道规划,可用于城区及高速公路各种复杂道路)
  • NaviPlanning(导航规划,主要用于高速公路)
  • OpenSpacePlanning (自主泊车和狭窄路段的掉头)

这三种模式负责调用上面算法

问题是代码中是怎么选择相应的planner呢?

Planner配置

每个Planner都会有一个字符串描述的唯一类型,在配置文件中(见下文)通过这个类型来选择相应的Planner。

Planner的配置文件路径是在/modules/planning/dag/planning.dag中指定的,相关内容如下:

// modules/planning/dag/planning.dag

    config {
    
    
      name: "planning"
      config_file_path:  "/apollo/modules/planning/conf/planning_config.pb.txt"

接下来我们可以看一下planning_config.pb.txt中的内容:

standard_planning_config {
    
    
  planner_type: PUBLIC_ROAD
  planner_public_road_config {
    
    
  }
}

怎么在代码中调用上面配置,具体参见目录【分配器初始化】,可以看到默认使用PUBLIC_ROAD规划器。

要想使用LatticePlanner,需要修改启动配置参数,即将modules/planning/conf/planning_config.pb.txt中的planner_type:PUBLIC_ROAD改为planner_type:LATTICE

猜你喜欢

转载自blog.csdn.net/zhizhengguan/article/details/129365638
今日推荐