Apollo开发-apollo介绍之planning模块(四)

Planning模块简介

规划(planning)模块的作用是根据感知预测的结果,当前的车辆信息和路况规划出一条车辆能够行驶的轨迹,这个轨迹会交给控制(control)模块,控制模块通过油门,刹车和方向盘使得车辆按照规划的轨迹运行。

规划模块的轨迹是短期轨迹,即车辆短期内行驶的轨迹,长期的轨迹是routing模块规划出的导航轨迹,即起点到目的地的轨迹,规划模块会先生成导航轨迹,然后根据导航轨迹和路况的情况,沿着短期轨迹行驶,直到目的地。这点也很好理解,我们开车之前先打开导航,然后根据导航行驶,如果前面有车就会减速或者变道,超车,避让行人等,这就是短期轨迹,结合上述方式直到行驶到目的地。

Planning输入输出

我们先看下Apollo的数据流向:

可以看到规划(planning)模块的上游是Localization, Prediction, Routing模块,而下游是Control模块。Routing模块先规划出一条导航线路,然后Planning模块根据这条线路做局部优化,如果Planning模块发现短期规划的线路行不通(比如前面修路,或者错过了路口),会触发Routing模块重新规划线路,因此这两个模块的数据流是双向的。

Planning模块的输入在"planning_component.h"中,接口如下:

 

bool Proc(const std::shared_ptr<prediction::PredictionObstacles>&

prediction_obstacles,

const std::shared_ptr<canbus::Chassis>& chassis,

const std::shared_ptr<localization::LocalizationEstimate>&

localization_estimate) override;

输入参数为:

  1. 预测的障碍物信息(prediction_obstacles)

  2. 车辆底盘(chassis)信息(车辆的速度,加速度,航向角等信息)

  3. 车辆当前位置(localization_estimate)

实际上还有高精度地图信息,不在参数中传入,而是在函数中直接读取的。

Planning模块的输出结果在"PlanningComponent::Proc()"中,为规划好的线路,发布到Control模块订阅的Topic中。

输出结果为:规划好的路径。

 

planning_writer_->Write(std::make_shared<ADCTrajectory>(adc_trajectory_pb));

Planning整个流程

下图是整个Planning模块的执行过程:

  1. 模块的入口是PlanningComponent,在Cyber中注册模块,订阅和发布消息,并且注册对应的Planning类。

  2. Planning的过程之前是定时器触发,即每隔一段固定的时间执行一次,现已经改为事件触发,即只要收集完成对应TOPIC的消息,就会触发执行,这样的好处是提高的实时性。

  3. Planning类主要实现了2个功能,一个是启动ReferenceLineProvider来提供参考线,后面生成的轨迹都是在参考线的基础上做优化,ReferenceLineProvider启动了一个单独的线程,每隔50ms执行一次,和Planning主流程并行执行。Planning类另外的一个功能是执行Planning主流程。

  4. Planning主流程先是选择对应的Planner,我们这里主要分析PublicRoadPlanner,在配置文件中定义了Planner支持的场景(Scenario),把规划分为具体的几个场景来执行,每个场景又分为几个阶段(Stage),每个阶段会执行多个任务(Task),任务执行完成后,对应的场景就完成了。不同场景间的切换是由一个状态机(ScenarioDispatch)来控制的。规划控制器根据ReferenceLineProvider提供的参考线,在不同的场景下做切换,生成一条车辆可以行驶的轨迹,并且不断重复上述过程直到到达目的地。

接下来我们逐步分析整个planning模块的代码结构。

Planning模块入口

模块注册

Planning模块的入口为"planning_component.h"和"http://planning_component.cc"两个文件,实现的功能如下:

 

// 订阅和发布消息

std::shared_ptr<cyber::Reader<perception::TrafficLightDetection>>

traffic_light_reader_;

std::shared_ptr<cyber::Reader<routing::RoutingResponse>> routing_reader_;

std::shared_ptr<cyber::Reader<planning::PadMessage>> pad_message_reader_;

std::shared_ptr<cyber::Reader<relative_map::MapMsg>> relative_map_reader_;

std::shared_ptr<cyber::Writer<ADCTrajectory>> planning_writer_;

std::shared_ptr<cyber::Writer<routing::RoutingRequest>> rerouting_writer_;

// 在Cyber中注册模块

CYBER_REGISTER_COMPONENT(PlanningComponent)

模块初始化

除了注册模块,订阅和发布消息之外,planning模块实现了2个主要函数"init"和"proc"。

Init中实现了模块的初始化:

 

if (FLAGS_open_space_planner_switchable) {

planning_base_ = std::make_unique<OpenSpacePlanning>();

} else {

if (FLAGS_use_navigation_mode) {

planning_base_ = std::make_unique<NaviPlanning>();

} else {

planning_base_ = std::make_unique<OnLanePlanning>();

}

}

上面实现了3种Planning的注册,planning模块根据配置选择不同的Planning实现方式,"FLAGS_open_space_planner_switchable"和"FLAGS_use_navigation_mode"在Planning模块的conf目录中。因为上述2个配置默认都为false,Planning默认情况下的实现是"OnLanePlanning"。下面介绍下这3种Planning的区别。

  • OpenSpacePlanning- 主要的应用场景是自主泊车和狭窄路段的掉头。[参考](ApolloAuto/apollo)

  • NaviPlanning

  • OnLanePlanning- 主要的应用场景是

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值