apollo_logo
5
0

工程框架升级之PnC包管理2.0解读

上周我们发布了Apollo开放平台9.0版本,为大家的学习和开发带来了新的体验。本节课我们将对planning模块的升级,进行详细的解读。Planning 模块框架比较复杂,代码量多,为了方便用户学习和上手,并能快速根据自己的需求开发扩展功能,planning 在框架上进行了一些调整,具体有如下内容:

  • 统一的对外接口:升级后 pnc 的接口统一封装在 external_command 模块处理,隔离了上层业务调用和 PNC 模块的接口变化。
  • 分级参数配置机制:划分全局参数和局部参数,局部参数放在插件中独立管理,便于开发者查询和修改。
  • 全新插件扩展机制:将 scenario,task 和 traffic rules 插件化,便于用户独立开发部署自己的插件,通过配置流程来启动运行插件。

统一的对外接口

apollo原来的接口是通过topic发送,接口命令直接分发到PNC的各个模块,数据流如下图所示:

在9.0版本中对这些接口进行了优化和升级:

  • 接口统一封装,增加了接口处理层external_command,隔离了业务层和PNC内部模块,两者中某个接口发生变化时不影响另外一个
  • 调用接口时,用户不需要关心命令发送给哪个模块,在external_command模块中可以统一查找所有支持的命令列表。
  • 改用cyber中service-client机制调用,用户可以通过client查询当前任务的执行状态。
  • 对常用导航命令RoutingRequest做了精简:
  • 原来的RoutingRequest需要查询地图,找到路由点和终点最近的车道,并得到在车道上对应的投影点;精简后的命令只需要给出坐标和朝向即可。
  • 发送导航命令不再需要发送车辆当前的位置作为起点位置,PNC会自动获取并处理起点位置。
  • 支持用户灵活扩展自己的命令,如清扫车添加打开盘刷的命令等

升级后的命令数据流程如下图:

命令升级后兼容旧的功能接口,对照关系如下表所示:

功能

升级前命令

升级后命令

升级说明

点到点沿道路行驶

routing::RoutingRequest

LaneFollowCommand

精简了路由点信息,新的命令给出坐标和朝向,不需要查询地图找到最近的LaneWayPoint

泊车

routing::RoutingRequest(包含parking_space_id)

ValetParkingCommand

升级前后都是给定parking_space_id进行泊车

PULL_OVER,START,STOP流程控制

planning::PadMessage

ActionCommand

升级后合并流程操作到一个命令中

切换自动/手动模式

control::PadMessage

ActionCommand

升级后合并流程操作到一个命令中


例如,当用户希望发送一个点到点行驶的命令时,按照以下步骤进行即可:

  1. 创建发送命令请求的cyber::Client
// 注册Node节点,节点名称用户自己定义
std::shared_ptr<apollo::cyber::Node> node = apollo::cyber::CreateNode("my_node");
// 注册client发送Command命令,Client为模板类,模板第一个参数是发送的命令类型,第二个参数类型固定,为planning模块反馈的任务执行状态类型
apollo::cyber::Client<apollo::external_command::LaneFollowCommand, apollo::external_command::CommandStatus>> client =
std::shared_ptr<node_->CreateClient<apollo::external_command::LaneFollowCommand, CommandStatus>("/apollo/external_command/lane_follow");
  1. 生成命令数据
auto command = std::make_shared<apollo::external_command::LaneFollowCommand>();
// 填充命令header信息,第一个参数为当前运行的模块名称,用户自定义
apollo::common::util::FillHeader("my_module", command.get());
command->set_command_id(1);
// 设置LaneFollow的终点坐标,在此给定终点坐标位姿即可,不再需要从地图中查询终点附近车道的信息
command->mutable_end_pose()->set_x(10.0);
command->mutable_end_pose()->set_y(3.5);
command->mutable_end_pose()->set_heading(0.5);
// 设置巡航速度。不设定的情况下,会按照planning中配置的默认巡航速度行驶
command->set_target_speed(3.0);
  1. 发送命令
auto response = client->SendRequest(command);
// 在此可以获得命令发送的结果
if(nullptr == response){
std::cout <<"Command sending failed, please check the service is on!\n"<< std::endl;
}else{
std::cout <<"******Finish sending command.******\n"<< std::endl;
}

从以上步骤可以看出,发送点到点行驶的命令时,用户需要发送的信息比原来简化了很多,并且可以获取命令接收的状态。

分级参数配置机制

planning中的配置参数量较大,入门调试时难度较高,用户想要修改的功能对应的参数不直观,并且不易快速定位需要修改的参数。针对这些问题,将参数分成全局变量和局部变量:

  • 全局变量是多个算法或插件中共同使用的参数;
  • 局部变量是专属于某个算法或插件的参数。如果用户需要调整某个插件的参数,直接在插件的目录中查找。

分级后的参数配置目录结构如下:

具体修改后主要参数的分布如下:

  1. 全局配置参数:

全局配置参数

文件目录结构

文件

说明

planning_base

proto

planning_config.proto

planing全局配置参数定义

traffic_rule_config.proto

traffic_rule生效列表配置定义

其他基础算法配置参数.proto

其他算法配置参数定义

conf

planning.conf

全局flag变量

planning_config.pb.txt

planning全局配置参数

traffic_rule_config.pb.txt

选择traffic_rule生成列表

其他基础算法配置参数.pb.txt

其他算法配置参数定义

common

planning_gflags.h

全局flag变量定义

scenario_base

proto/scenario_pipeline.proto

scenaro的pipeline定义


  1. 局部配置参数scenarios:

局部配置参数

场景

文件目录结构

一级目录

二级目录

说明

scenarios

park_and_go

proto

park_and_go.proto

Scenario:park_and_go scenario的配置参数定义

conf

pipeline.pb.txt

Scenario Pipeline :park_and_go scenario的PiPeline参数配置

scenario_conf.pb.txt

Scenario :park_and_go scenario的配置参数

park_and_go_adjustStage目录:park_and_go just stage的task配置参数

open_space_roi_decider.pb.txt

Task:open_space_roi_decider task的配置参数

open_space_trajectory_provider.pb.txt

Task:open_space_trajectory_provider的配置参数

park_and_go_checkStage目录:park_and_go_check stage的task配置参数

open_space_roi_decider.pb.txt

Task:open_space_roi_decider task的配置参数

lane_follow

proto

Scenario :lane_follow的配置参数定义

conf

Scenario :lane_follow的配置参数

bare_intersection_unprotected

proto

Scenario :bare_intersection_unprotected的配置参数定义

conf

Scenario :bare_intersection_unprotected的配置参数

…


  1. 局部配置参数tasks:

局部配置参数

场景

文件目录结构

文件

说明

tasks

lane_borrow_pathtask默认配置

proto

lane_borrow_path.proto

lane_borrow_path task的配置参数定义

conf

default_conf.pb.txt

lane_borrow_path task的配置参数

open_space_roi_decidertask默认配置

proto

open_space_roi_decider.proto

open_space_roi_decider的配置参数定义

conf

default_conf.pb.txt

open_space_roi_decider的配置参数

path_decidertask默认配置

proto

path_decider.proto

path_decider的配置参数定义

conf

default_conf.pb.txt

path_decider的配置参数

…


  1. 局部配置参数traffic_rules:

局部配置参数

场景

文件目录结构

文件

说明

traffic_rules

baskside_vehicletask默认配置

proto

backside_vihicle.proto

backside_vihicle的配置参数定义

conf

default_conf.pb.txt

backside_vihicle的配置参数

crosswalktraffic_rules默认配置

proto

crosswalk.proto

crosswalk的配置参数定义

conf

default_conf.pb.txt

crosswalk的配置参数

keepcleartraffic_rules默认配置

proto

backside_vihicle.proto

keepclear的配置参数定义

conf

keepclearpb.txt

keepclear的配置参数

…


总结来说,9.0版本对参数配置进行了以下升级:

  • 添加对常用功能使用到的参数的说明文档,方便用户调试时查询。
  • 参数的目录跟随作用范围和功能,这样对参数的定位更清晰和直观。
  • 用户新增的插件所使用的参数,可以跟随插件进行发布和管理。

参数配置相关的云实验:Apollo规划之减速带配置仿真实践

全新插件扩展机制

插件是9.0版本中的支持用户灵活扩展新功能的一种方式,用户新扩展的插件符合父类程序接口规范,通过重新实现接口来增加新的功能。对planning模块进行扩展是通过插件的形式,通常有三种类型的插件:

  • scenario:定义一种新的场景,在这个场景下使用特定的交通规则或行驶流程,例如新增左转待转场景,用于处理在有红绿灯路口的左转待转区的驾驶行为
  • task:在scenario的处理过程,添加一些额外的处理,例如在ValetParkingScenario中,添加一个ReplanTask,用于在遇到障碍物时重新规划路径
  • traffic rule:在运行scenario流程之前的处理,如添加一个在学校附近行驶时限制巡航速度的traffic rule

用户可以根据实际业务的需要,自定义添加自己的scenario,task或traffic rule。增加的插件在一个独立的包中,用户只需要实现插件的接口,以及配置是否要加载这个插件即可。例如用户新增左转待转场景插件,增加一个left_turn_waiting_zone包,在这个包中添加左转待转场景的实现代码,以及相关的工程文件,编译调试后发布即可。

需要运行这个场景时,在planning的配置文件中,添加这个场景的pipeline:

旧版本中没有使用插件的方式扩展,用户想新增一个scenario,流程比较繁琐,除了创建场景本身的源代码之外,还需要额外做以下改动:

  • 修改原有的ScenaioType和StageType,新增场景类型
  • 修改原有的ScenaioConfig,新增场景配置定义
  • 在原有的场景配置文件中,新增新的场景配置参数
  • 修改ScenarioManager类:
  • 修改RegisterScenarios函数
  • 修改CreateScenario函数
  • 修改Observe函数
  • 修改ScenarioDispatchNonLearning函数
  • 修改SelectTrafficLightScenario函数
  • 修改UpdatePlanningContextTrafficLightScenario函数
  • 增加scenario_manager.cc对新场景的BUILD依赖
  • 修改planning模块对新场景的BUILD依赖

由此可见,旧版本中的改动比较分散,修改的原则不容易记忆,新增场景的门槛比较高。使用9.0版本中插件的方式扩展场景时,只需要做以下修改即可:

  • 使用工具模板创建scenario,实现新scenario的相关接口和业务代码
  • 在配置文件planning_config.pb.txt文件的pipeline中,增加新的场景

升级后新增场景代码集中,容易掌握。此外用插件开发的模式还有以下好处:

  • 用户根据自己的场景,使用包管理的方式,选择性下载安装自己需要的scenario,task,traffic rules即可。
  • 用户新增的插件独立开发,编译,发布和运行。
  • 用户新增了插件后,可以直接跟随apollo一起升级。


扫码关注【Apollo开发者社区】第一时间获取Apollo动态!

扫码关注【百度技术沙龙】获取更多百度技术动态!

原创声明,本文由作者授权发布于Apollo开发者社区,未经许可,不得转载。
发表评论已发表 0 条评论
登录后可评论,请前往 登录
暂无评论~快去发表自己的独特见解吧!
目录
统一的对外接口
分级参数配置机制
全新插件扩展机制