【赛题解析】丨人行道避让场景解析
本赛题解析由山东科技大学冯永康同学提供,欢迎各位同学提供赛题解析,有apollo周边精美礼品相送。
场景位置
本场景车辆是从上方接近人形道,建议先跑一遍全图,查看各个场景与参考线的位置,以免后续的各个场景路线出现错误,导致解题思路出现偏差。
赛题描述
主车向前行驶,前方遇到有人通过人行道,主车需要停止在人行道前 5m~ 5.5m 内停车。
评判标准
主车未停止在人行道前 5~5.5m 外,本场景分扣20 分,若未避让行人或超出停止线停车,本场景计 0 分
赛题解读
车辆经过人行道时,只要有人在人行道上,就必须按赛题要求停止在距离人行道5~5.5m的位置。停止决策栅栏区对应的图标为下图。
此处应注意粗体字,必须人走过整条人行道,车辆才能行驶过人行道,这也是很多同学赛题得0分得原因。 当车辆距离人行道一定距离时,行人障碍物开始通过人行道,因此在测试场景的时候需要将车辆起点与终点距离人行道设置的远一些,此外想要重置行人位置,只需要重新启动Sim Obstacle模块即可。
解题思路
根据赛事培训视频可以了解到,本题场景可以通过调参解决。初步测试该该赛题,我们了解到该赛题只涉及LANE_FOLLOW场景中的DEFAULT_STAGE阶段。
我们可以从题目中提取到关键词人行道(CROSSWLAK),根据文章,我们可以了解到人行道(CROSSWLAK)属于交通规则的应用。我们可以通过/apollo/modules/planning/conf/traffic_rule_config.pb.txt文件,对交通规则的一些基础参数配置进行更改满足部分赛题要求,此外只更改conf文件的参数并不能满足完整赛题要求,还需要通过/apollo/modules/planning/traffic_rules/crosswalk.cc相关参数的更改实现。
技术详解
以下是/apollo/modules/planning/conf/traffic_rule_config.pb.txt文件中人行道(CROSSWALK)相关的参数配置。
config: {
rule_id: CROSSWALK
enabled: true
crosswalk {
stop_distance: 1.0
max_stop_deceleration: 6.0
min_pass_s_distance: 1.0
max_valid_stop_distance: 3.5
expand_s_distance: 2.0
stop_strict_l_distance: 6.0
stop_loose_l_distance: 8.0
stop_timeout: 4.0
}
首先我们来解决停车的问题,在未改动代码之前,我们通过测试发现,当行人走过人行道时,虽然出现了信号停止墙,车辆是无法停下的。
因此第一步我们需要解决车辆停止的问题,为了更好的对参数配置进行更改,首先要去/apollo/modules/planning/traffic_rules/crosswalk.cc了解一下人行道有行人时的停车逻辑。 车辆在人行道是否停止主要通过调用函数crosswalk.cc中的CheckStopForObstacle函数来进行判断的。
boolCheckStopForObstacle(ReferenceLineInfo* const reference_line_info,const hdmap::CrosswalkInfoConstPtr crosswalk_ptr,const Obstacle& obstacle,;
constdouble stop_deceleration)
我们来查看第一个判断,根据障碍物类型判断是否停车。
if (obstacle_type != PerceptionObstacle::PEDESTRIAN &&
obstacle_type != PerceptionObstacle::BICYCLE &&
obstacle_type != PerceptionObstacle::UNKNOWN_MOVABLE &&
obstacle_type != PerceptionObstacle::UNKNOWN) {
AINFO << "obstacle_id[" << obstacle_id << "] type[" << obstacle_type_name
<< "]. skip";
returnfalse;
}
也就是说人行道上的障碍物不是以上这几类障碍物,车辆是不会停车的。但是我们障碍物是行人,属于以上停车类型障碍物,我们接着往下看第二个判断,根据障碍物是否在扩展后的人行道上判断是否停车。如果行人障碍物不在拓展后的范围内则不需要停车。
Vec2d point(perception_obstacle.position().x(),
perception_obstacle.position().y());
const Polygon2d crosswalk_exp_poly =
crosswalk_ptr->polygon().ExpandByDistance(
config_.crosswalk().expand_s_distance());
bool in_expanded_crosswalk = crosswalk_exp_poly.IsPointIn(point);
if (!in_expanded_crosswalk) {
ADEBUG << "skip: obstacle_id[" << obstacle_id << "] type["
<< obstacle_type_name << "] crosswalk_id[" << crosswalk_id
<< "]: not in crosswalk expanded area";
returnfalse;
}
根据赛题位置以及日志打印可以了解到(如果不在会打印日志信息),行人障碍物是在范围内,因此需要停车。我们接着往下看第三个判断,这里便涉及到apollo/modules/planning/conf/traffic_rule_config.pb.txt文件中 stop_strict_l_distance与stop_loose_l_distance相关的内容。
bool stop = false;
if (obstacle_l_distance >= config_.crosswalk().stop_loose_l_distance()){
// (1) when obstacle_l_distance is big enough(>= loose_l_distance),// STOP only if paths crossesif (is_path_cross) {
stop = true;
ADEBUG << "need_stop(>=l2): obstacle_id[" << obstacle_id << "] type["
<< obstacle_type_name << "] crosswalk_id[" << crosswalk_id << "]";
}
}
当障碍物的横向距离(obstacle_l_distance)大于stop_loose_l_distance
如果障碍物的轨迹与参考线相交,则需要停车,我们将stop_loose_l_distance调小后,进行测试。
发现如果没有减速过程,车辆参考线(红线)与与行人障碍物的轨迹线(黄线)没有相交。
当障碍物的横向距离小于严格的横向停车距离时
障碍物在当前车道范围内,并且满足(obstacle_sl_point.s() > adc_end_edge_s)条件时停车。
elseif (obstacle_l_distance <=
config_.crosswalk().stop_strict_l_distance()) {
if (is_on_road) {
// (2) when l_distance <= strict_l_distance + on_road// always STOPif (obstacle_sl_point.s() > adc_end_edge_s) {
stop = true;
ADEBUG << "need_stop(<=l1): obstacle_id[" << obstacle_id << "] type["
<< obstacle_type_name << "] s[" << obstacle_sl_point.s()
<< "] adc_end_edge_s[ " << adc_end_edge_s << "] crosswalk_id["
<< crosswalk_id << "] ON_ROAD";
}
}
障碍物不在当前车道范围内,障碍物即将穿过车辆所在车道时,也就是障碍物轨迹与车辆参考相交时停车。
else {
// (3) when l_distance <= strict_l_distance// + NOT on_road(i.e. on crosswalk/median etc)// STOP if paths crossif (is_path_cross) {
stop = true;
ADEBUG << "need_stop(<=l1): obstacle_id[" << obstacle_id << "] type["
<< obstacle_type_name << "] crosswalk_id[" << crosswalk_id
<< "] PATH_CRSOSS";
}
障碍物不在当前车道范围内,障碍物正在趋向车辆时需要停车。
else {
// (4) when l_distance <= strict_l_distance// + NOT on_road(i.e. on crosswalk/median etc)// STOP if he pedestrian is moving toward the ego vehicleconstauto obstacle_v = Vec2d(perception_obstacle.velocity().x(),
perception_obstacle.velocity().y());
constauto adc_path_point =
Vec2d(injector_->ego_info()->start_point().path_point().x(),
injector_->ego_info()->start_point().path_point().y());
constauto ovstacle_position =
Vec2d(perception_obstacle.position().x(),
perception_obstacle.position().y());
auto obs_to_adc = adc_path_point - ovstacle_position;
constdouble kEpsilon = 1e-6;
if (obstacle_v.InnerProd(obs_to_adc) > kEpsilon) {
stop = true;
ADEBUG << "need_stop(<=l1): obstacle_id[" << obstacle_id << "] type["
<< obstacle_type_name << "] crosswalk_id[" << crosswalk_id
<< "] MOVING_TOWARD_ADC";
}
}
}
当障碍物的横向距离在严格的停车距离与宽松的停车距离之间时,障碍物即将穿过车辆所在车道时,也就是障碍物轨迹与车辆参考相交时停车。
else {
// (4) when l_distance is between loose_l and strict_l// use history decision of this crosswalk to smooth unsteadiness// TODO(all): replace this temp implementationif (is_path_cross) {
stop = true;
}
ADEBUG << "need_stop(between l1 & l2): obstacle_id[" << obstacle_id
<< "] type[" << obstacle_type_name << "] obstacle_l_distance["
<< obstacle_l_distance << "] crosswalk_id[" << crosswalk_id
<< "] USE_PREVIOUS_DECISION";
}
通过调节以上参数可以满足让车辆在人行道前停下来的要求,但并不满足所有赛题的要求(注意全场景的约束如加速度),此外我们还需要注意还需更改其他参数。
停止距离参数此处不做讲解,此处讲一下行人障碍物走过当前车道后车辆驶过人行道的问题。
当障碍物走过左中两个车道时,可以满足停车的条件,但是进入右车道后,就不满足部分停车的条件了,我们将目光放在以下部分代码中。
if (stop && !is_on_lane &&
crosswalk_overlap->start_s - adc_front_edge_s <=
kStartWatchTimerDistance) {
// check on stop timer for static pedestrians/bicycles// if NOT on_lane ahead of adcconstdouble kMaxStopSpeed = 0.3;
auto obstacle_speed = std::hypot(perception_obstacle.velocity().x(),
perception_obstacle.velocity().y());
if (obstacle_speed <= kMaxStopSpeed) {
if (crosswalk_stop_timer[crosswalk_id].count(obstacle_id) < 1) {
// add timestamp
ADEBUG << "add timestamp: obstacle_id[" << obstacle_id
<< "] timestamp[" << Clock::NowInSeconds()
<< "]";
crosswalk_stop_timer[crosswalk_id].insert(
{obstacle_id, Clock::NowInSeconds()});
} else {
double stop_time = Clock::NowInSeconds() -
crosswalk_stop_timer[crosswalk_id][obstacle_id];
ADEBUG << "stop_time: obstacle_id[" << obstacle_id << "] stop_time["
<< stop_time << "]";
if (stop_time >= config_.crosswalk().stop_timeout()) {
stop = false;
}
}
}
}
根据文章的解读,障碍物不在当前的参考线所对应的车道上,且车辆到停止线的距离小于40米,当障碍物移动的速度小于等于0.3时,如果当前障碍物不在crosswalk_stop_timer[crosswalk_id]中,则将其插入其中;如果障碍物已经在了并且stop_time >= config_.crosswalk().stop_timeout(),则不再需要停车,因此我们可以更改相关的参数就可以实现当行人完全走过人行道,车辆才能驶过人行道。
参赛入口
想真实体验一下吗?快来参赛体验吧,参赛链接:https://studio.apollo.auto/community/article/43