【Apollo学习笔记】——规划模块TASK之PATH_BORROW_DECIDER

文章目录

  • 前言
  • PATH_BORROW_DECIDER功能简介
  • PATH_BORROW_DECIDER相关配置
  • PATH_BORROW_DECIDER总体流程
  • PATH_BORROW_DECIDER相关子函数
    • IsNecessaryToBorrowLane
    • IsBlockingObstacleFarFromIntersection
    • IsNonmovableObstacle
    • CheckLaneBorrow
  • 参考

前言

在Apollo星火计划学习笔记——Apollo路径规划算法原理与实践与【Apollo学习笔记】——Planning模块讲到……Stage::Process的PlanOnReferenceLine函数会依次调用task_list中的TASK,本文将会继续以LaneFollow为例依次介绍其中的TASK部分究竟做了哪些工作。由于个人能力所限,文章可能有纰漏的地方,还请批评斧正。

modules/planning/conf/scenario/lane_follow_config.pb.txt配置文件中,我们可以看到LaneFollow所需要执行的所有task。

stage_config: {
  stage_type: LANE_FOLLOW_DEFAULT_STAGE
  enabled: true
  task_type: LANE_CHANGE_DECIDER
  task_type: PATH_REUSE_DECIDER
  task_type: PATH_LANE_BORROW_DECIDER
  task_type: PATH_BOUNDS_DECIDER
  task_type: PIECEWISE_JERK_PATH_OPTIMIZER
  task_type: PATH_ASSESSMENT_DECIDER
  task_type: PATH_DECIDER
  task_type: RULE_BASED_STOP_DECIDER
  task_type: SPEED_BOUNDS_PRIORI_DECIDER
  task_type: SPEED_HEURISTIC_OPTIMIZER
  task_type: SPEED_DECIDER
  task_type: SPEED_BOUNDS_FINAL_DECIDER
  task_type: PIECEWISE_JERK_SPEED_OPTIMIZER
  # task_type: PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER
  task_type: RSS_DECIDER

本文将继续介绍第三个TASK——PATH_BORROW_DECIDER

PATH_BORROW_DECIDER功能简介

在这里插入图片描述

主要功能:产生是否借道的决策
判断条件
• 是否只有一条车道
• 是否存在阻塞道路的障碍物
• 阻塞障碍物是否远离路口
• 阻塞障碍物长期存在
• 旁边车道是实线还是虚线
当所有判断条件都满足时,会产生借道决策。

PATH_BORROW_DECIDER相关配置

PATH_BORROW_DECIDER的相关配置集中在以下两个文件:modules/planning/conf/planning_config.pb.txtmodules/planning/conf/scenario/lane_follow_config.pb.txt

// modules/planning/conf/scenario/lane_follow_config.pb.txt
  task_config: {
    task_type: PATH_LANE_BORROW_DECIDER
    path_lane_borrow_decider_config {
      allow_lane_borrowing: true
    }
  }
// modules/planning/conf/planning_config.pb.txt
default_task_config: {
  task_type: PATH_LANE_BORROW_DECIDER
  path_lane_borrow_decider_config {
    allow_lane_borrowing: true
  }
}

PATH_BORROW_DECIDER总体流程

在这里插入图片描述

流程依旧看Process:

主要完成数据检查;判断是否启用reuse path,若有则跳过剩余步骤;判断是否有必要进行借道操作等步骤。

Status PathLaneBorrowDecider::Process(
    Frame* const frame, ReferenceLineInfo* const reference_line_info) {
  // Sanity checks.
  CHECK_NOTNULL(frame);
  CHECK_NOTNULL(reference_line_info);

  // skip path_lane_borrow_decider if reused path
  if (FLAGS_enable_skip_path_tasks && reference_line_info->path_reusable()) {
    // for debug
    AINFO << "skip due to reusing path";
    return Status::OK();
  }

  // By default, don't borrow any lane.
  reference_line_info->set_is_path_lane_borrow(false);
  // Check if lane-borrowing is needed, if so, borrow lane.
  if (Decider::config_.path_lane_borrow_decider_config()
          .allow_lane_borrowing() &&
      IsNecessaryToBorrowLane(*frame, *reference_line_info)) {
    reference_line_info->set_is_path_lane_borrow(true);
  }
  return Status::OK();
}

同时还可以注意一下相关结构体定义:
modules/planning/proto/planning_status.proto

message PathDeciderStatus {
  enum LaneBorrowDirection {
    LEFT_BORROW = 1;   // borrow left neighbor lane
    RIGHT_BORROW = 2;  // borrow right neighbor lane
  }
  optional int32 front_static_obstacle_cycle_counter = 1 [default = 0];
  optional int32 able_to_use_self_lane_counter = 2 [default = 0];
  optional bool is_in_path_lane_borrow_scenario = 3 [default = false];
  optional string front_static_obstacle_id = 4 [default = ""];
  repeated LaneBorrowDirection decided_side_pass_direction = 5;
}

PATH_BORROW_DECIDER相关子函数

IsNecessaryToBorrowLane

借道判断主要通过核心函数IsNecessaryToBorrowLane()判断是否借道,主要涉及一些rules,包括距离信号交叉口的距离,与静态障碍物的距离,是否是单行道,是否所在车道左右车道线是虚线等规则。主要有两个功能:

  • 已处于借道场景下判断是否退出避让;
  • 未处于借道场景下判断是否具备借道能力。
bool PathLaneBorrowDecider::IsNecessaryToBorrowLane(
    const Frame& frame, const ReferenceLineInfo& reference_line_info) {
  auto* mutable_path_decider_status = injector_->planning_context()
                                          ->mutable_planning_status()
                                          ->mutable_path_decider();
  // 如果当前处于借道场景中                                        
  if (mutable_path_decider_status->is_in_path_lane_borrow_scenario()) {
    // If originally borrowing neighbor lane:
    // 如果当前已经在借道状态了,并且自车车道可用的counter >=6,取消lane_borrow scenario 状态
    if (mutable_path_decider_status->able_to_use_self_lane_counter() >= 6) {
      // If have been able to use self-lane for some time, then switch to
      // non-lane-borrowing.
      mutable_path_decider_status->set_is_in_path_lane_borrow_scenario(false);
      mutable_path_decider_status->clear_decided_side_pass_direction();
      AINFO << "Switch from LANE-BORROW path to SELF-LANE path.";
    }
  } else {
    // If originally not borrowing neighbor lane:
    // 如果未在借道的状态
    ADEBUG << "Blocking obstacle ID["
           << mutable_path_decider_status->front_static_obstacle_id() << "]";
    // ADC requirements check for lane-borrowing:
    // 只有一条参考线,才能借道
    if (!HasSingleReferenceLine(frame)) {
      return false;
    }
    // 起点速度小于最大借道允许速度
    if (!IsWithinSidePassingSpeedADC(frame)) {
      return false;
    }

    // Obstacle condition check for lane-borrowing:
    // 阻塞障碍物是否远离路口
    if (!IsBlockingObstacleFarFromIntersection(reference_line_info)) {
      return false;
    }
    // 阻塞障碍物长期存在
    if (!IsLongTermBlockingObstacle()) {
      return false;
    }
    // 阻塞障碍物是否在终点位置与自车间距之内
    if (!IsBlockingObstacleWithinDestination(reference_line_info)) {
      return false;
    }
    // 为可侧面通过的障碍物
    if (!IsSidePassableObstacle(reference_line_info)) {
      return false;
    }

    // switch to lane-borrowing
    // set side-pass direction
    const auto& path_decider_status =
        injector_->planning_context()->planning_status().path_decider();
    if (path_decider_status.decided_side_pass_direction().empty()) {
      // first time init decided_side_pass_direction
      bool left_borrowable;
      bool right_borrowable;
      CheckLaneBorrow(reference_line_info, &left_borrowable, &right_borrowable);
      if (!left_borrowable && !right_borrowable) {
        mutable_path_decider_status->set_is_in_path_lane_borrow_scenario(false);
        return false;
      } else {
        mutable_path_decider_status->set_is_in_path_lane_borrow_scenario(true);
        if (left_borrowable) {
          mutable_path_decider_status->add_decided_side_pass_direction(
              PathDeciderStatus::LEFT_BORROW);
        }
        if (right_borrowable) {
          mutable_path_decider_status->add_decided_side_pass_direction(
              PathDeciderStatus::RIGHT_BORROW);
        }
      }
    }

    AINFO << "Switch from SELF-LANE path to LANE-BORROW path.";
  }
  return mutable_path_decider_status->is_in_path_lane_borrow_scenario();
}

IsBlockingObstacleFarFromIntersection

IsBlockingObstacleFarFromIntersection流程部分在总体流程图中已经展示。

bool PathLaneBorrowDecider::IsBlockingObstacleFarFromIntersection(
    const ReferenceLineInfo& reference_line_info) {
  const auto& path_decider_status =
      injector_->planning_context()->planning_status().path_decider();
  const std::string blocking_obstacle_id =
      path_decider_status.front_static_obstacle_id();
  if (blocking_obstacle_id.empty()) {
    ADEBUG << "There is no blocking obstacle.";
    return true;
  }
  const Obstacle* blocking_obstacle =
      reference_line_info.path_decision().obstacles().Find(
          blocking_obstacle_id);
  if (blocking_obstacle == nullptr) {
    ADEBUG << "Blocking obstacle is no longer there.";
    return true;
  }

  // Get blocking obstacle's s.
  double blocking_obstacle_s =
      blocking_obstacle->PerceptionSLBoundary().end_s();
  ADEBUG << "Blocking obstacle is at s = " << blocking_obstacle_s;
  // Get intersection's s and compare with threshold.
  const auto& first_encountered_overlaps =
      reference_line_info.FirstEncounteredOverlaps();
  for (const auto& overlap : first_encountered_overlaps) {
    ADEBUG << overlap.first << ", " << overlap.second.DebugString();
    // if (// overlap.first != ReferenceLineInfo::CLEAR_AREA &&
    // overlap.first != ReferenceLineInfo::CROSSWALK &&
    // overlap.first != ReferenceLineInfo::PNC_JUNCTION &&
    if (overlap.first != ReferenceLineInfo::SIGNAL &&
        overlap.first != ReferenceLineInfo::STOP_SIGN) {
      continue;
    }

    auto distance = overlap.second.start_s - blocking_obstacle_s;
    if (overlap.first == ReferenceLineInfo::SIGNAL ||
        overlap.first == ReferenceLineInfo::STOP_SIGN) {
      if (distance < kIntersectionClearanceDist) {
        ADEBUG << "Too close to signal intersection (" << distance
               << "m); don't SIDE_PASS.";
        return false;
      }
    } else {
      if (distance < kJunctionClearanceDist) {
        ADEBUG << "Too close to overlap_type[" << overlap.first << "] ("
               << distance << "m); don't SIDE_PASS";
        return false;
      }
    }
  }

  return true;
}

IsNonmovableObstacle

在IsNonmovableObstacle() 中主要对前方障碍物进行判断,利用预测以及参考线的信息来进行判断。代码位置在modules/planning/common/obstacle_blocking_analyzer.cc。大致流程在总体流程图中已经展示。

bool IsNonmovableObstacle(const ReferenceLineInfo& reference_line_info,
                          const Obstacle& obstacle) {
  // Obstacle is far away.
  const SLBoundary& adc_sl_boundary = reference_line_info.AdcSlBoundary();
  if (obstacle.PerceptionSLBoundary().start_s() >
      adc_sl_boundary.end_s() + kAdcDistanceThreshold) {
    ADEBUG << " - It is too far ahead and we are not so sure of its status.";
    return false;
  }

  // Obstacle is parked obstacle.
  if (IsParkedVehicle(reference_line_info.reference_line(), &obstacle)) {
    ADEBUG << "It is Parked and NON-MOVABLE.";
    return true;
  }

  // Obstacle is blocked by others too.
  for (const auto* other_obstacle :
       reference_line_info.path_decision().obstacles().Items()) {
    if (other_obstacle->Id() == obstacle.Id()) {
      continue;
    }
    if (other_obstacle->IsVirtual()) {
      continue;
    }
    if (other_obstacle->PerceptionSLBoundary().start_l() >
            obstacle.PerceptionSLBoundary().end_l() ||
        other_obstacle->PerceptionSLBoundary().end_l() <
            obstacle.PerceptionSLBoundary().start_l()) {
      // not blocking the backside vehicle
      continue;
    }
    double delta_s = other_obstacle->PerceptionSLBoundary().start_s() -
                     obstacle.PerceptionSLBoundary().end_s();
    if (delta_s < 0.0 || delta_s > kObstaclesDistanceThreshold) {
      continue;
    }

    // TODO(All): Fix the segmentation bug for large vehicles, otherwise
    // the follow line will be problematic.
    ADEBUG << " - It is blocked by others, and will move later.";
    return false;
  }

  ADEBUG << "IT IS NON-MOVABLE!";
  return true;
}

CheckLaneBorrow

主要根据前方道路的线型判断是否可以借道;在此函数中2m间隔一个点遍历前视距离。

void PathLaneBorrowDecider::CheckLaneBorrow(
    const ReferenceLineInfo& reference_line_info,
    bool* left_neighbor_lane_borrowable, bool* right_neighbor_lane_borrowable) {
  const ReferenceLine& reference_line = reference_line_info.reference_line();
  // 定义左、右车道是否可借用的标志位,并初始化为true
  *left_neighbor_lane_borrowable = true;
  *right_neighbor_lane_borrowable = true;
  
  static constexpr double kLookforwardDistance = 100.0;
  // 获取自车的S坐标
  double check_s = reference_line_info.AdcSlBoundary().end_s();
  // 前视距离
  const double lookforward_distance =
      std::min(check_s + kLookforwardDistance, reference_line.Length());
  while (check_s < lookforward_distance) {
    auto ref_point = reference_line.GetNearestReferencePoint(check_s);
    // 找不到在参考线上的邻近点,左右车道均不可借用,直接返回
    if (ref_point.lane_waypoints().empty()) {
      *left_neighbor_lane_borrowable = false;
      *right_neighbor_lane_borrowable = false;
      return;
    }

    const auto waypoint = ref_point.lane_waypoints().front();
    hdmap::LaneBoundaryType::Type lane_boundary_type =
        hdmap::LaneBoundaryType::UNKNOWN;

    if (*left_neighbor_lane_borrowable) {
      lane_boundary_type = hdmap::LeftBoundaryType(waypoint);
      if (lane_boundary_type == hdmap::LaneBoundaryType::SOLID_YELLOW ||
          lane_boundary_type == hdmap::LaneBoundaryType::DOUBLE_YELLOW ||
          lane_boundary_type == hdmap::LaneBoundaryType::SOLID_WHITE) {
        *left_neighbor_lane_borrowable = false;
      }
      ADEBUG << "s[" << check_s << "] left_lane_boundary_type["
             << LaneBoundaryType_Type_Name(lane_boundary_type) << "]";
    }
    if (*right_neighbor_lane_borrowable) {
      lane_boundary_type = hdmap::RightBoundaryType(waypoint);
      if (lane_boundary_type == hdmap::LaneBoundaryType::SOLID_YELLOW ||
          lane_boundary_type == hdmap::LaneBoundaryType::SOLID_WHITE) {
        *right_neighbor_lane_borrowable = false;
      }
      ADEBUG << "s[" << check_s << "] right_neighbor_lane_borrowable["
             << LaneBoundaryType_Type_Name(lane_boundary_type) << "]";
    }
    check_s += 2.0;
  }
}

参考

[1] Apollo Planning决策规划代码详细解析 (8): PathLaneBorrowDecider
[2] Apollo规划模块详解(六):算法实现-path lane borrow decider
[3] https://www.cnblogs.com/icathianrain/p/14407619.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/86108.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序 echarts 画多个横向柱状图

然后是json {"usingComponents": {"ec-canvas": "../../common/ec-canvas/ec-canvas"},"navigationBarTitleText": "主题活动" } ec-canvas获取方式 在链接里下载代码 然后copy ec-canvas文件夹到自己的项目 https://gi…

长胜证券:越南首富,又火了!旗下汽车股市值盘中超越比亚迪!

当地时刻8月22日&#xff0c;美股三大股指涨跌纷歧&#xff0c;其中&#xff0c;道指跌0.51%&#xff0c;标普500指数跌0.28%&#xff0c;纳斯达克指数涨0.06%。 异动股方面&#xff0c;8月22日周二&#xff0c;越南电动轿车出产商VinFast Auto ADR盘中上涨超越167%&#xff0c…

Python 合并多个 PDF 文件并建立书签目录

今天在用 WPS 的 PDF 工具合并多个文件的时候&#xff0c;非常不给力&#xff0c;居然卡死了好几次&#xff0c;什么毛病&#xff1f;&#xff01; 心里想&#xff0c;就这么点儿功能&#xff0c;居然收了我会员费都实现不了&#xff1f;不是吧…… 只能自己来了&#xff0c;…

职业学院物联网实训室建设方案

一、概述 1.1专业背景 物联网&#xff08;Internet of Things&#xff09;被称为继计算机、互联网之后世界信息产业第三次浪潮&#xff0c;它并非一个全新的技术领域&#xff0c;而是现代信息技术发展到一定阶段后出现的一种聚合性应用与技术提升&#xff0c;是随着传感网、通…

Googel Earth Engine 配置Python 环境

1. 安装并配置python环境 此处不再赘述 2. 安装 earthengine-api pip install earthengine-api C:\Users\xixi>pip install earthengine-api Collecting earthengine-apiUsing cached earthengine_api-0.1.363-py3-none-any.whl Requirement already satisfied: google-c…

数据结构 - 线性表的定义和基本操作

一、定义 线性表是具有相同特性的数据元素的一个有限序列。 线性表&#xff1a; 由n(n≥0)个数据元素&#xff08;结点&#xff09;组成的有限序列。线性表中数据元素是一对一的关系&#xff0c;每个结点最多有一个直接前驱&#xff0c;和一个直接后继 二、线性表的基本操作 …

无涯教程-PHP - 条件判断

if... elseif ... else和switch语句用于根据不同条件进行判断。 您可以在代码中使用条件语句来做出决定&#xff0c; PHP支持以下三个决策语句- if ... else语句 - 如果要在条件为真时执行&#xff0c;而在条件不为真时执行另一个代码&#xff0c;请使用此语句 els…

江西萍乡能源石油化工阀门三维扫描3d测量抄数建模-CASAIM中科广电

长期以来&#xff0c;石油天然气、石油石化、发电和管道输送行业在环保、健康和安全保障方面一直承受着巨大的压力&#xff0c;他们必须确保相关规程在各项作业中得到全面贯彻。 阀门作为流体管道运输中的组成部分&#xff0c;其装配密封度是保证流体运输安全的重要一环&#…

Git如何操作本地分支仓库?

基本使用TortoiseGit 操作本地仓库(分支) 分支的概念 几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离开来&#xff0c;避免影响开发主线。多线程开发,可以同时开启多个任务的开发&#xff0c;多个任务之间互不影响。 为何要…

Lazada为什么成为卖家新宠?趋势如何?

其实跨境销售是网络发达以来,很多国内的商家都在突破的点。只有真正打开自己的市场,这样才可以让销售能够直线上升。如果永远在国内进行销售,那么不仅仅会增加难度,并且也很有可能无法打开自己的销售思路,导致最终在时代的潮流中没落。那么如果想要进行跨境销售,渠道就是相当重…

ASR(自动语音识别)任务中的LLM(大语言模型)

一、LLM大语言模型的特点 二、大语言模型在ASR任务中的应用 浅度融合 浅层融合指的是LLM本身并没有和音频信息进行直接计算。其仅对ASR模型输出的文本结果进行重打分或者质量评估。 深度融合 LLM与ASR模型进行深度结合&#xff0c;统一语音和文本的编码空间或者直接利用ASR…

springboot+docker实现微服务的小例子

【任务】&#xff1a; 创建一个服务A&#xff1a;service_hello 创建一个服务B&#xff1a;service_name service_name负责提供一个api接口返回一个name字符串。 service_hello负责从这个接口获取name字符串&#xff0c;然后进行一个字符串拼接&#xff0c;在后面加一个hello&…

Stable Diffusion 系列教程 | 文生图 - 提示词

目录 1.提示词 基本的规则 2.提示词分类 2.1内容性提示词 2.2 画风艺术派提示词 2.3 画幅视角 2.4画质提示词 3 反向提示词 3.1 内容性反向提示词 3.2 画质性反向提示词 4 实例分析 5 权重 5.1 方法一 5.2 方法二 6.参数 7. 学习and 技巧 7.1 辅助写提示词的网…

ARL资产侦察灯塔 指纹增强

项目&#xff1a;https://github.com/loecho-sec/ARL-Finger-ADD 下载项目后运行 python3 ARl-Finger-ADD.py https://你的vpsIP:5003/ admin password该项目中的finger.json可以自己找到其他的指纹完善&#xff0c;然后运行脚本添加指纹。

ChatGPT应用于高职教育的四大潜在风险

目前&#xff0c;ChatGPT还是一种仍未成熟的技术&#xff0c;当其介入高职教育生态后&#xff0c;高职院校师生在享受ChatGPT带来的便利的同时&#xff0c;也应该明白ChatGPT引发的风险也会随之进入高职教育领域&#xff0c;如存在知识信息、伦理意识与学生主体方面的风险与挑战…

EasyExcel+POI制作带有有效性校验及下拉联动的Excel模板

文章目录 1.背景2.实现功能的Excel特性2.1.特性介绍2.2.下拉框联动2.3.单元格自动匹配Id2.4.错误提示 3.代码实现3.1.基础流程代码3.2.名称管理器配置3.3.有效性配置3.4.函数填充3.5.其他补充 4.总结 1.背景 最近在做一个CRM系统的人员销售目标导入的相关需求&#xff0c;需要…

K8s学习笔记1

一、课程介绍&#xff1a; 1、背景&#xff1a; 1&#xff09;从基础设备主机化向容器化转换。 2&#xff09;从人肉式运维工作模式向自动化运维模式转换。 3&#xff09;从自动化运维体系向全体系智能化运维模式转换。 2、课程目标人群: 1&#xff09;掌握Linux操作系统基…

C语言:选择+编程(每日一练Day6)

目录 ​编辑选择题&#xff1a; 题一&#xff1a; 题二&#xff1a; 题三&#xff1a; 题四&#xff1a; 题五&#xff1a; 编程题&#xff1a; 题一&#xff1a;至少是其他数字两倍的最大数 思路一&#xff1a; 思路二&#xff1a; 题二&#xff1a;两个数组的交集…

问道管理:数字经济概念走势强劲,竞业达、久其软件等涨停,观想科技等大涨

信创、智慧政务等数字经济概念22日盘中走势微弱&#xff0c;截至发稿&#xff0c;观想科技、慧博云通涨超15%&#xff0c;竞业达、中远海科、久其软件等涨停&#xff0c;云赛智联、延华智能、汇纳科技涨约9%&#xff0c;天玑科技、安硕信息、思特奇、零点稀有涨逾7%。 音讯面上…

Linux后门大全-xinetd后门(二)

环境 靶机&#xff1a;centos7.6 攻击机&#xff1a;Linux 使用docker搭建靶机环境&#xff0c;当然也可以不使用docker&#xff0c;直接跳过创建容器的步骤即可 创建容器 #创建名为backdoorT4的特权容器&#xff0c;并使用/usr/sbin/init&#xff0c;因为容器默认不开启sy…