Apollo虚拟仿真大赛-左转待转赛题解析(原创)

百度Apollo城市道路自动驾驶虚拟仿真赛-左转待转赛题解析

题目描述:主车在十字路口左转时,若直行绿灯灯,左转红灯时,则车辆进入左转待转区等待。

评分标准:直行及左转灯为红灯时,主车停止在停止线2-2.2米之内。 直行绿灯,左转红灯,主车15s内未进入待转区或行驶超出待转区,本场景分计0分;直行红灯,左转绿灯,主车未驶出左转待转区,进入左转道,本场景分计0分。

1赛题分析

Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第1张图片

 

左转待转场景示意图如上图所示,道路前方有两个红绿灯,一个控制直行车辆(图中右侧红绿灯)另外一个控制左转车辆(图中左侧红绿灯)。该场景下红绿灯情况无外乎以下3种:

  1. 直行红灯,左转红灯:此时车辆应当在直行红灯的停止线停车;

  2. 直行绿灯,左转红灯:此时车辆应当进入待转区域,在待转区域停止线前停车等待需要解决左转交通灯多停止线带来的重复停止墙的问题。;

  3. 左转绿灯时,则无论直行是否为绿灯,车辆可以直接通行。

理清场景逻辑以后,我们可以在不改动任何代码的情况下进行该场景的实验,实验发现如下几个问题:

  1. 该场景下,默认进入了无保护左转场景;

  2. 直行绿灯,左转红灯以后车辆依然停在直行红绿灯停止线前,未进入待转区域;

  3. 左转绿灯以后,车辆依据无保护左转场景定义进入了creep阶段会自动creep一段距离后才通过十字路口。

实际上,问题1和问题3都来源于进入了错误场景导致的,针对这两个问题,我们团队参考无保护左转场景添加了左转待转场景的相关代码,分为三个阶段,第一个阶段为车辆接近直行停止线的阶段,第二个阶段为车辆进入待转区域的阶段,第三个阶段为通过十字路口的阶段。

Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第2张图片

 

对于第二个问题,我发现左转红绿灯在其控制的车道上实际有两条停止线,其在reference_line_info中对应两个overlap,其id又是相同的,唯一不同的是位置。第一条停止线与直行红绿灯的停止线位置重合,第二条停止线为待转区的停止线。重复的停止线导致在进行交通信号检查(traffic_light.cc)的时候会在同一个位置生成两个停止墙(图中1和2),一个对应直行红灯,另外一个对应左转红灯。而且在生成待转区左转红灯停止墙的时候还会出现停止墙id重复的冲突(左转交通灯两条停止线id相同导致的)。因此,当两个交通灯都为红灯时,实际上有3个停止墙,如上图所示,分别为直行停止线处的两个(1和2)和待转区域的一个(3),当直行为绿灯左转红灯时,直行的停止墙消失,但左转的停止墙还是没有消失(dreamview也不显示,但是实际是存在的),这是导致车辆依旧停在原地的主要原因。

由是,根据上面的分析,本赛题的主要问题可以概括为以下两个:

  1. 需要自己新建场景,单独处理车辆行停逻辑;

  2. 需要解决左转交通灯多停止线带来的重复停止墙的问题。

2参考解法

2.1左转待转场景添加及阶段划分

2.1.1 新增场景

场景添加的详细过程这里不赘述,可以参考无保护左转,主要的步骤如下:

1 在planning_config.proto中增加场景

2 新建场景的配置文件“xxxx.pb.txt"

3 在planning_gflags.h/cc文件中添加配置路径

4 在/planning/scenario/traffic_light下增加场景实现的具体代码

5 增加编译配置

2.1.2 进入左转待转的判断

方法一:根据上面的分析,以及浏览整个地图及赛题,发现“左转红绿灯在同一车道上有两个id相同的停止线“这一特征,具有独一性,我们只需要判断十字路口场景下是否有上述特征的红绿灯便可。

方法二:此方法有一些取巧,但是针对比赛来说也是有效且简单的,纵观六个赛题,只有左转待转有两个有效红绿灯,那我们只需要判断当前场景下有效红绿灯的个数是否为2,便可以确定是否进入左转待转场景,我们使用的便是方法二。

方法二代码在scenario_manager.cc中的ScenarioManager::SelectTrafficLightScenario中,核心代码如下:

Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第3张图片 

上面的TRAFFIC_LIGHT_PROTECTED_LEFT_TURN便是我们新增的场景名称,方法二在实际情况下可能出现bug,但是在比赛中好像没出问题:)哈哈哈。

2.1.3 阶段划分及阶段结束判断

解决了场景选择的问题,下面就是阶段划分了,由于新建场景时,stage的划分与task都是照搬无保护左转的,这里需要着重说几个需要更改的点:

  1. 左转待转不需要creep阶段了,所以我们删除了creep阶段中的creep_decider,令其控制从直行停止线到待转停止线这一段,也就是stage2;

  2. stage1和stage3与无保护左转保持一致。

Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第4张图片上图为stage2的task配置(名字偷懒没有改) 

下面介绍一下各个阶段结束的判定:

stage1:

Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第5张图片 上图中traffic_light_ids这个vector来自当前场景的上下文Context,在traffic_light_protected_left_turn_scenario.cc中,通过计算stop_line之间的距离,对左转红绿灯和直行红绿灯作了区分,左转红绿灯在后面。相关代码如下:

Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第6张图片

stage2:

Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第7张图片 

只要左转绿灯亮着就可以经入下一阶段。

stage3跟无保护左转相同。

2.2左转红绿灯重复停止线的剔除

此处代码逻辑主要在modules/planning/traffic_rules/traffic_light.cc中,具体为TrafficLight::MakeDecisions此函数中。

原本的代码逻辑是遍历每一个traffic_light_overlap,满足对应要求的traffic_light_overlap会生成停止墙,即添加停止决策,如下:

Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第8张图片 可以看到,停止决策需要的关键信息为obstacle_id和start_s。如前面分析的那样,按照如此逻辑最终会生成三个停止墙,其中在直行停止线处有一个左转的多余停止墙。如何处理呢?我利用左转红绿灯stop_line的id是重复的但是start_s不同这一特性进行剔除。具体方法如下:

先定义一个存储符合条件的stop_line的容器:

std::map good_traffic_stop_line;

如果有符合要求的traffic_light_overlap需要生成停止墙时,先在good_traffic_stop_line中查找是否存在同id的元素,如果不存在则直接插入进去,如果存在同id元素则比较两个overlap的start_s较大的替换较小的,这样便可以去除近处stop_line生成的停止墙。

 遍历生成停止墙的代码如下:Apollo虚拟仿真大赛-左转待转赛题解析(原创)_第9张图片

你可能感兴趣的:(算法竞赛,自动驾驶)