星火自动驾驶大赛赛事集锦--红绿灯路口减速慢行(方法一)
交通灯场景(TRAFFIC_LIGHT)
场景描述:
当主车在监测到前方的红灯时, 主车停车在停止线前1.5-2.0米处,不得超过停止线。当红灯变为绿灯后,主车可以通过该路段,在通过交通灯区域时,主车的速度不得超过 6 m/s。
场景图示:
在交通规则中,当我们的车辆遇到红灯或者黄灯时就需要停车等待。在Apollo中设置的交通规则中也满足了这点。当我们的主车检测到前方为红或者黄灯时 (代码如下),在dreamview中的会显示以下界面:如图1 所示;同时也会在实线前多少米(看具体设置的距离,默认值为1米)外生成一道停止墙如图2所示:
图1:红灯显示 图2:停止墙
评判标准
主车未停车在停止线1.5-2.0米之间, 本场景分扣20分; 速度每超速1m/s, 本场景分扣20分, 超过停止线或者红灯状态未停止, 本场景计0分;
运行视频回放
【百度Apollo星火自动驾驶大赛城市道路预选赛——交通灯路口赛题】 https://www.bilibili.com/video/BV1Ez4y187hG/?share_source=copy_web&vd_source=c5757152d93e2f5dba69049264ebea4e
实验流程:
实验流程大纲
- 默认配置参数规划效果
- 启动dreamview并观察默认配置参数下车辆遇到交通灯的仿真效果。
- 红绿灯场景实践:
- a. 找到planning2.0中Traffic Rules配置的相关文件。
- b. 根据要求,调整Traffic Rules配置参数,确保车辆停车在距离停止线2米至2.5米的位置停车。
- c. 调整通过交叉路口的速度
- d.保存修改后的配置参数,并重新启动planning模块。
- e. 运行车辆规划模块,并在dreamview上观察车辆遇到红绿灯场景的停车变化和通过交叉路口速度
使用插件配置参数流程
生成和使用traffic light插件
输入配置参数同步指令,系统将自动将全局配置参数复制到profile的default目录中,然后就可以在profile目录上轻松修改配置参数。
buildtool profile config init --package planning-traffic-rules-traffic-light --profile=default
使用目录名为default的这份配置参数
aem profile use defaul
查看profile插件目录结构:
tree profiles/default/modules/planning/traffic_rules/
目录结构:
profiles/default/modules/planning/traffic_rules/`-- traffic_light`-- conf`-- default_conf.pb.txt//traffic_light插件参数配置文件
修改插件配置参数
在工作apollo_workspace工作目录找到profiles/default/modules/planning/traffic_rules/traffic_light/conf/default_conf.pb.txt配置文件,调整红绿灯场景停止配置参数,达到我们期望路径规划效果。
(1) 使用在线编辑工具修改profiles/default/modules/planning/traffic_rules/traffic_light/conf/default_conf.pb.txt配置文件,将stop_distance 参数
在全局配置参数中找到红绿灯场景停止配置参数:
stop_distance: 1.0
将配置参数的值修改为:
stop_distance: 2.0
仿真对比:
原始 | 修改后 | |
绕行距离配置实践 |
云实验链接:
该实践内容已经上线Apollo云实验室,开快速启动进行实践体验: https://apollo.baidu.com/community/course/9
技术详解
交通灯场景运行流程框图
一、进入TRAFFIC_LIGHT_PROTECTED场景
代码以及代码路径(节选):
.aem/envroot/opt/apollo/neo/src/modules/planning/scenarios/traffic_light_protected/conf/scenario_conf.pb.txt
start_traffic_light_scenario_distance: 5.0#当距离红绿灯的停车道5.0米时进入TRAFFIC_LIGHT_PROTECTED场景
代码以及代码路径(节选):
.aem/envroot/opt/apollo/neo/src/modules/planning/scenarios/traffic_light_protected/traffic_light_protected_scenario.cc
如果 adc_distance_to_traffic_light 小于等于0(表示车辆已经过了交通信号灯)或者大于起始检查距离(start_check_distance),那么就不进入交通信号灯场景,继续下一个信号灯的判断。否则进入交通信号灯场景
// enter traffic-light scenarios: based on distance onlyif (adc_distance_to_traffic_light <= 0.0 ||adc_distance_to_traffic_light > start_check_distance) {continue;}
交通灯场景TRAFFIC_LIGHT_PROTECTED定义了两个stage
.aem/envroot/opt/apollo/neo/share/modules/planning/scenarios/traffic_light_protected/conf/pipeline.pb.txt
stage: {name: "TRAFFIC_LIGHT_PROTECTED_APPROACH"type: "TrafficLightProtectedStageApproach"enabled: true…}stage: {name: "TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISE"type: "TrafficLightProtectedStageIntersectionCruise"enabled: true…}
TRAFFIC_LIGHT_PROTECTED_APPROACH和TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISE的注册
代码以及代码路径(节选):
s_stage_factory_.Register(ScenarioConfig::TRAFFIC_LIGHT_PROTECTED_APPROACH,[](const ScenarioConfig::StageConfig& config,const std::shared_ptr<DependencyInjector>& injector) -> Stage* {return new TrafficLightProtectedStageApproach(config, injector);});s_stage_factory_.Register(ScenarioConfig::TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISE,[](const ScenarioConfig::StageConfig& config,const std::shared_ptr<DependencyInjector>& injector) -> Stage* {return new TrafficLightProtectedStageIntersectionCruise(config,injector);});
如果自动驾驶车辆遇到交通灯为红灯
二、红绿灯检测:
代码以及代码路径(节选):
.aem/envroot/opt/apollo/neo/src/modules/planning/traffic_rules/traffic_light/traffic_light.cc
这段代码的作用是检查交通灯是否已经完成。它遍历已完成的交通灯重叠区域的ID列表,然后将当前交通灯的ID与这些ID进行比较。如果当前交通灯的ID在已完成的交通灯重叠区域的ID列表中,那么设置变量traffic_light_done为true,然后退出循环。
bool traffic_light_done = false;for (const auto& done_traffic_light_overlap_id :traffic_light_status.done_traffic_light_overlap_id()) {if (traffic_light_overlap.object_id == done_traffic_light_overlap_id) {traffic_light_done = true;break;}}if (traffic_light_done) {continue;}
2.1停止墙生成源码:
可能有小伙伴会问停止墙是如何生成的呢?停止墙的标志是什么?
首先当我们的主车确认前方交通灯不为绿灯时时,会生成停止墙,停止原因为黄/红信号灯,
代码以及代码路径(节选):
.aem/envroot/opt/apollo/neo/src/modules/planning/traffic_rules/traffic_light/traffic_light.cc
/*函数的作用是生成一条停车决策,并将其添加到参考线信息中。当交通规则需要控制车辆停止时,例如信号灯指示红灯时,就会生成这样的停车决策。*/
util::BuildStopDecision(virtual_obstacle_id, traffic_light_overlap.start_s,config_.stop_distance(), StopReasonCode::STOP_REASON_SIGNAL,wait_for_obstacles, Getname(), frame, reference_line_info);
2.2信号灯停止源码:
代码以及代码路径(节选):
/*这段代码是一个交通灯保护阶段(TrafficLightProtectedStage)中的交通灯靠近阶段(TrafficLightProtectedStageApproach)的处理函数(Process)。首先,它遍历当前交通灯重叠区域的ID列表,并检查每个交通灯的颜色是否为绿灯。如果存在任何一个交通灯不是绿灯,那么设置变量traffic_light_all_done为false,然后退出循环。否则,将变量traffic_light_all_done设置为true。如果所有交通灯都是绿灯,那么函数调用FinishStage()来结束该阶段,然后返回Stage::FINISHED状态。否则,返回Stage::RUNNING状态,表示该阶段仍在运行中。*/
StageResult TrafficLightProtectedStageApproach::Process(const TrajectoryPoint& planning_init_point, Frame* frame) {// traffic_light_all_done 用于标记是否所有交通信号灯都已处理完毕bool traffic_light_all_done = true;// 遍历当前交通信号灯的重叠区域for (const auto& traffic_light_overlap_id :context->current_traffic_light_overlap_ids) {// 获取交通信号灯在参考线上的重叠信息PathOverlap* current_traffic_light_overlap =reference_line_info.GetOverlapOnReferenceLine(traffic_light_overlap_id, ReferenceLineInfo::SIGNAL);if (!current_traffic_light_overlap) {continue;}// 设置交通信号灯不具备交通优先权reference_line_info.SetJunctionRightOfWay(current_traffic_light_overlap->start_s, false);// 获取车辆前沿位置相对于交通信号灯停车线的距离const double adc_front_edge_s = reference_line_info.AdcSlBoundary().end_s();const double distance_adc_to_stop_line =current_traffic_light_overlap->start_s - adc_front_edge_s;auto signal_color = frame->GetSignal(traffic_light_overlap_id).color();// 检查车辆到停车线的距离是否小于最大有效停车距离if (distance_adc_to_stop_line > scenario_config.max_valid_stop_distance()) {traffic_light_all_done = false;break;}// 检查交通信号灯的颜色是否为绿色if (signal_color != TrafficLight::GREEN) {traffic_light_all_done = false;break;}}// 如果所有交通信号灯都已经处理完毕,则返回 FinishStage() 表示阶段已完成if (traffic_light_all_done) {return FinishStage();}// 否则,返回 result.SetStageStatus(StageStatusType::RUNNING) 表示阶段仍在运行中return result.SetStageStatus(StageStatusType::RUNNING);}
当主车靠近红绿灯场景时,会进入Scenario 为TRAFFIC_LIGHT_PROTECTED的红绿灯场景
自动驾驶车辆接近交通信号灯
三、进入APPROACH的stage定义
代码以及代码路径(节选):
/*这段代码是交通灯保护阶段(TrafficLightProtectedStage)中的交通灯靠近阶段(TrafficLightProtectedStageApproach)的处理函数(Process)*/
StageResult TrafficLightProtectedStageApproach::Process(const TrajectoryPoint& planning_init_point, Frame* frame)//APPROACHstage 正在运行{return result.SetStageStatus(StageStatusType::RUNNING);}
/*这段代码是交通灯保护阶段(TrafficLightProtectedStage)中的交通灯靠近阶段(TrafficLightProtectedStageApproach)的结束函数(FinishStage)。当交通灯靠近阶段的任务完成后,该函数会将next_stage_设置为ScenarioConfig::TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISE,表示进入交通灯保护阶段的下一个阶段TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISE。然后,它返回Stage::FINISHED状态,表示该阶段已经完成。*/
Stage::StageStatus TrafficLightProtectedStageApproach::FinishStage()//APPROACHstage 正在完成{//省略next_stage_ = "TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISE";//进入下一个stage TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISEreturn StageResult(StageStatusType::FINISHED);//APPROACH的stage完成}
自动驾驶车辆进入红绿灯交叉路口区域
四、进入INTERSECTION_CRUISE的stage定义
代码以及代码路径(节选):
这段代码是交通灯保护阶段(TrafficLightProtectedStage)中的交通灯保护交叉路口阶段(TrafficLightProtectedStageIntersectionCruise)的处理函数(Process)。首先,它调用stage_impl_.CheckDone()函数,检查是否已经通过了交叉路口。如果已经通过了交叉路口,那么将返回true,表示该阶段已经完成。如果该阶段已经完成,那么函数调用FinishStage()来结束该阶段,然后返回Stage::FINISHED状态。否则,返回Stage::RUNNING状态,表示该阶段仍在运行中。
StageResult TrafficLightProtectedStageIntersectionCruise::Process(const common::TrajectoryPoint& planning_init_point, Frame* frame) {bool stage_done = CheckDone(*frame, injector_->planning_context(), true);//定义交叉路口if (stage_done)//如果通过交叉路口{return FinishStage();//INTERSECTION_CRUISE的stage完成}return result.SetStageStatus(StageStatusType::RUNNING);//进入INTERSECTION_CRUISE的RUNNING}
该函数调用FinishScenario()函数,结束整个交通灯保护阶段(TrafficLightProtectedStage),并返回Stage::FINISHED状态,表示该阶段已经完成。
StageResult TrafficLightProtectedStageIntersectionCruise::FinishStage() {return FinishScenario();//INTERSECTION_CRUISE的stage完成}
交通灯场景代码修改部分
任务实现:
停车距离:
输入traffic_rules参数同步指令,系统将自动将traffic_light的配置参数复制到profile的default目录中,然后就可以在profile目录上轻松修改配置参数。
buildtool profile config init --package planning-traffic-rules-traffic-light --profile=default && aem profile use default
profiles/default/modules/planning/traffic_rules/traffic_light/conf/default_conf.pb.txt
stop_distance: 1.0#停止距离为1.0 单位 m
代码实现(节选):
.aem/envroot/opt/apollo/neo/src/modules/planning/planning_base/common/util/common.cc
ObjectDecisionType stop;//定义一个停止墙auto* stop_decision = stop.mutable_stop();//stop决策的停车原因stop_decision->set_reason_code(stop_reason_code);stop_decision->set_distance_s(-stop_distance);//stop决策的停车安全距离
实现场景代码(修改参数的部分):
我们仅仅需要将配置文件TRAFFIC_LIGHT的stop_distance值改为1.5-2.0即可。
因为存在误差值,尽量取中间值。
stop_distance: 1.7#停止距离为1.0 单位 m
红绿灯路口限速:
可通过修改加速度实现
buildtool install planning-task-piecewise-jerk-speed
修改源码
piecewise_jerk_problem.set_ddx_bounds(veh_param.max_deceleration(),veh_param.max_acceleration());
调整最大加速度的大小,具体范围,需要调参解决
piecewise_jerk_problem.set_ddx_bounds(veh_param.max_deceleration(),1.0);