apollo规划架构

算法的基本架构

我们在最开始直接给出规划决策算法架构框图,然后一一介绍每个框图结构的细节:

在这里插入图片描述

  1. 模块的入口是 PlanningComponent,在 Cyber 中注册模块,订阅和发布消息,并且注册对应的 Planning 类。
  2. Planning 的过程之前是定时器触发,即每隔一段固定的时间执行一次,现已经改为事件触发,即只要收集完成对应 TOPIC 的消息,就会触发执行,这样的好处是提高的实时性。
  3. Planning 类主要实现了 2 个功能,一个是启动 ReferenceLineProvider 来提供参考线,后面生成的轨迹都是在参考线的基础上做优化,ReferenceLineProvider 启动了一个单独的线程,每隔 50ms 执行一次,和 Planning 主流程并行执行。Planning 类另外的一个功能是执行 Planning 主流程。
  4. Planning 主流程先是选择对应的 Planner,我们这里主要分析 PublicRoadPlanner,在配置文件中定义了 Planner 支持的场景(Scenario),把规划分为具体的几个场景来执行,每个场景又分为几个阶段(Stage),每个阶段会执行多个任务(Task),任务执行完成后,对应的场景就完成了。不同场景间的切换是由一个状态机(ScenarioDispatch)来控制的。规划控制器根据 ReferenceLineProvider 提供的参考线,在不同的场景下做切换,生成一条车辆可以行驶的轨迹,并且不断重复上述过程直到到达目的地。

PlanningComponent

规划模块的入口是 PlanningComponent。PlanningComponent 的两大核心函数是 Init 和 Proc.

在初始化中,我们可以看到如下的代码,FLAGS_use_navigation_mode 的标志位直接决定了我们等等实例化的 planning_base_ 的具体 planner,到底是 NaviPlanning 还是 OnLanePlanning:

if (FLAGS_use_navigation_mode) {planning_base_ = std::make_unique<NaviPlanning>(injector_);} else {planning_base_ = std::make_unique<OnLanePlanning>(injector_);}

其实在更早的版本中有更多选项,7.0 为什么简化了呢?

if (FLAGS_open_space_planner_switchable) {planning_base_ = std::make_unique<OpenSpacePlanning>();} else {if (FLAGS_use_navigation_mode) {planning_base_ = std::make_unique<NaviPlanning>();} else {planning_base_ = std::make_unique<OnLanePlanning>();}}

而在 Proc(…)函数中,最核心部分则是调用对应 planner 的 RunOnce 函数:

planning_base_->RunOnce(local_view_, &adc_trajectory_pb);

接下来的具体例子中我们都以这个 planing_base_被实例化为 OnLanePlanning 作为前提。

下图是几个规划器的结构。这里我们要讨论的是 PublicRoadPlanner,这里只是简单的给出结构,后面的对应小节会具体介绍函数中如何运行和管理。

在这里插入图片描述

OnLanePlanning

RunOnce 函数的三大重要函数是:

// 初始化frame
status = InitFrame(frame_num, stitching_trajectory.back(), vehicle_state);
......
//进行traffic decider
for (auto& ref_line_info : *frame_->mutable_reference_line_info()) {TrafficDecider traffic_decider;traffic_decider.Init(traffic_rule_configs_);auto traffic_status =traffic_decider.Execute(frame_.get(), &ref_line_info, injector_);if (!traffic_status.ok() || !ref_line_info.IsDrivable()) {ref_line_info.SetDrivable(false);AWARN << "Reference line " << ref_line_info.Lanes().Id()<< " traffic decider failed";}}......//plan主函数
status = Plan(start_timestamp, stitching_trajectory, ptr_trajectory_pb);

Plan

这个 plan 函数中主要核心则是:

auto status = planner_->Plan(stitching_trajectory.back(), frame_.get(),ptr_trajectory_pb);

而这个 planner_则是通过 DispatchPlanner 来指定:

// dispatch plannerplanner_ = planner_dispatcher_->DispatchPlanner(config_, injector_);

具体来说就是:

std::unique_ptr<Planner> OnLanePlannerDispatcher::DispatchPlanner(const PlanningConfig& planning_config,const std::shared_ptr<DependencyInjector>& injector) {return planner_factory_.CreateObject(planning_config.standard_planning_config().planner_type(0), injector);
}
//其中这个config是:
standard_planning_config {planner_type: PUBLIC_ROADplanner_public_road_config {}
}

Plan 函数中主要的几个步骤是:

Status PublicRoadPlanner::Plan(const TrajectoryPoint& planning_start_point,Frame* frame,ADCTrajectory* ptr_computed_trajectory) {//更新当前的scenarioscenario_manager_.Update(planning_start_point, *frame);// 获取当前场景scenario_ = scenario_manager_.mutable_scenario();// 执行当前场景的任务auto result = scenario_->Process(planning_start_point, frame);。。。。。。
}

Scenario 是 apollo 决策规划算法中的重要概念,apollo 可以应对自动驾驶所面临的不同道路场景,都是通过 Scenario 统一注册与管理;Scenario 通过一个有限状态机来选择不同场景。

更新当前的 scenario

scenario_manager_.Update(planning_start_point, *frame);

我们来看 Update,做了这么几件事:

void ScenarioManager::Update(const common::TrajectoryPoint& ego_point,const Frame& frame) {ACHECK(!frame.reference_line_info().empty());// 保留当前帧Observe(frame);// 场景分发  ScenarioDispatch(frame);
}

这里能够提供的场景库包括:

enum ScenarioType {LANE_FOLLOW = 0;  // default scenario// intersection involvedBARE_INTERSECTION_UNPROTECTED = 2;STOP_SIGN_PROTECTED = 3;STOP_SIGN_UNPROTECTED = 4;TRAFFIC_LIGHT_PROTECTED = 5;TRAFFIC_LIGHT_UNPROTECTED_LEFT_TURN = 6;TRAFFIC_LIGHT_UNPROTECTED_RIGHT_TURN = 7;YIELD_SIGN = 8;// parkingPULL_OVER = 9;VALET_PARKING = 10;EMERGENCY_PULL_OVER = 11;EMERGENCY_STOP = 12;// miscNARROW_STREET_U_TURN = 13;PARK_AND_GO = 14;// learning model sampleLEARNING_MODEL_SAMPLE = 15;// turn aroundDEADEND_TURNAROUND = 16;
}

获取当前场景

//获取当前场景
Scenario* mutable_scenario() { return current_scenario_.get(); }

执行当前场景的任务

//通过Process函数进行场景运行
Scenario::ScenarioStatus Scenario::Process(const common::TrajectoryPoint& planning_init_point, Frame* frame)

场景下有 stage, 运行 stage 的 Process 函数:

auto ret = current_stage_->Process(planning_init_point, frame);

我们拿 LaneFollowStage 为例,则运行他的每个 task:

//首先进入函数:
auto cur_status =PlanOnReferenceLine(planning_start_point, frame, &reference_line_info);//然后是在PlanOnReferenceLine函数中遍历每个task
for (auto* task : task_list_) {const double start_timestamp = Clock::NowInSeconds();ret = task->Execute(frame, reference_line_info);。。。。。。}

以 lane follow 这个 stage 为例,这个 task list 包括:

scenario_type: LANE_FOLLOW
stage_type: LANE_FOLLOW_DEFAULT_STAGE
stage_config: {stage_type: LANE_FOLLOW_DEFAULT_STAGEenabled: truetask_type: LANE_CHANGE_DECIDERtask_type: PATH_REUSE_DECIDERtask_type: PATH_LANE_BORROW_DECIDERtask_type: PATH_BOUNDS_DECIDERtask_type: PIECEWISE_JERK_PATH_OPTIMIZERtask_type: PATH_ASSESSMENT_DECIDERtask_type: PATH_DECIDERtask_type: RULE_BASED_STOP_DECIDERtask_type: SPEED_BOUNDS_PRIORI_DECIDERtask_type: SPEED_HEURISTIC_OPTIMIZERtask_type: SPEED_DECIDERtask_type: SPEED_BOUNDS_FINAL_DECIDERtask_type: PIECEWISE_JERK_SPEED_OPTIMIZER# task_type: PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZERtask_type: RSS_DECIDER

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络技术原理需要解决的5个问题

解决世界上任意两台设备时如何通讯的&#xff1f;&#xff1f; 第一个问题&#xff0c;pc1和pc3是怎么通讯的&#xff1f; 这俩属于同一个网段&#xff0c;那么同网段的是怎么通讯的&#xff1f; pc1和pc2属于不同的网段&#xff0c;第二个问题&#xff0c;不同网段的设备是…

敏捷开发笔记(第7章节)--什么是敏捷设计

目录 1&#xff1a;PDF上传链接 7.1: 软件出了什么错 7.2: 设计的臭味--腐化软件的气味 7.2.1: 什么激化了软件的腐化 7.2.2: 敏捷团体不允许软件腐化 7.3: “copy”程序 1: 初始设计 2: 需求在变化 3: 得寸进尺 4: 期望变化 7.3.1: “copy”程序的敏捷设计 7.3.2:…

leetcode 二分查找·系统掌握 有效的完全平方数

题目&#xff1a; 题解&#xff1a; 就是一个非常普通的二分查找&#xff0c;但是需要注意的是查找的上下界&#xff0c;因为是完全平方&#xff0c;所以可以把上界设为这个数的一半&#xff0c;但是要特殊处理num等于1的时候。 bool isPerfectSquare(int num) {if(num1)retur…

element-plus form表单组件之el-date-picker日期选择器组件

el-date-picker日期选择器组件可根据年&#xff0c;月&#xff0c;日期&#xff0c;时间范围来进行选择&#xff0c;可以自定义日期格式&#xff0c;和样式&#xff0c;还提供多种内置事件。 主要属性如下 属性名说明类型可选值默认值model-value / v-model绑定值&#xff0c…

qt开发-11_Dialog 仿苹果支付界面

QDialog 是 Qt 框架中用于创建对话框的一个基类。对话框是一种特殊类型的窗口&#xff0c;通常用于短暂的交互和信息交换&#xff0c;如接收用户输入、显示消息、询问用户决定等。QDialog 提供了一种方便的方式来实现这些功能&#xff0c;并能够控制用户与其他窗口的交互性&…

自动更新阿里云CDN SSL证书

deploy-certificate-to-aliyun 随着各大CA机构开始收割用户&#xff0c;云厂商们提供的免费SSL证书也由之前的12个月变成现在的3个月。笔者一直使用阿里云的OSS作为图床&#xff0c;说实话在如果继续在阿里云上三个月免费一换也太频繁了 笔者在这里使用github action来每隔两个…

C++ (week9):Git

文章目录 1.git介绍2.git安装3.git配置4.获取自己的SSH公钥5.新建仓库6.邀请开发者7.克隆远程仓库到本地8.在本地进行开发9.本地项目推送到远程仓库10.git的工作原理11.分支管理(1)合作开发的方式(2)分支管理(3)分支合并的原理、冲突管理 12.git 与 svn 的区别13.设置alias别名…

内容安全复习 8 - 视觉内容伪造与检测

文章目录 研究背景内容伪造方法虚假人脸生成人脸替换属性编辑表情重演跨模态人脸编辑 伪造检测方法眨眼检测交互式人脸活体检测一些了解方法挑战 研究背景 图像内容篡改造成新闻报道的偏颇易导致社会和公共秩序的不安&#xff0c;对公共安全产生不良影响。 造成的影响&#x…

达梦8 通过日志解释数据守护系统的关闭顺序

关闭守护系统时&#xff0c;必须按照一定的顺序来关闭守护进程和数据库实例。特别是自动切换 模式&#xff0c;如果退出守护进程或主备库的顺序不正确&#xff0c;可能会引起主备切换&#xff0c;甚至造成守护进程 DM 数据守护与读写分离集群组分裂。 官方推荐通过在监视器执行…

macbook配置adb环境和用adb操作安卓手机

&#xff08;参考&#xff1a;ADB工具包的安装与使用_adb工具箱-CSDN博客&#xff09; 第一步&#xff1a;从Android开发者网站下载Android SDK&#xff08;软件开发工具包&#xff09;。下载地址为&#xff1a; 第二步&#xff1a;解压下载的SDK压缩文件到某个目录中。 进入解…

现在的Android程序员为什么会感到焦虑?焦虑的源头在哪里?该怎么去缓解焦虑呢?——没有无中生有的贩卖焦虑,只有你的挣扎和不甘。

二、知识为何产生焦虑 先说两个世界&#xff0c;知识的世界和现实的世界。 知识的世界&#xff0c;由承载知识的那些载体组成&#xff0c;比如图书、音视频、报刊、自媒体等。 现实的世界&#xff0c;就是我们每天生活的、做出各种行为的世界。 学习的目的是什么呢&#xff1…

[spring] Spring MVC Thymeleaf(下)

[spring] Spring MVC & Thymeleaf&#xff08;下&#xff09; 上篇笔记讲了一下怎么使用 thymeleaf 作为 HTML 模板&#xff0c;与 Spring MVC 进行沟通&#xff0c;这里主要说一下验证的部分 常用表单验证 一些 Spring MVC 内置的常用验证注解如下&#xff1a; Annota…

[面试题]MongoDB

[面试题]Java【基础】[面试题]Java【虚拟机】[面试题]Java【并发】[面试题]Java【集合】[面试题]MySQL[面试题]Maven[面试题]Spring Boot[面试题]Spring Cloud[面试题]Spring MVC[面试题]Spring[面试题]MyBatis[面试题]Nginx[面试题]缓存[面试题]Redis[面试题]消息队列[面试题]…

uniapp运行到模拟器(联想模拟器)

记录一下uniapp项目运行到联想模拟器的流程 先配置一下模拟器端口 填写对应的adb路径&#xff0c;也就是模拟器安装路径下的adb.exe的路径 然后打开模拟器的设置&#xff0c;搜索版本找到版本号&#xff0c;多次点击打开开发者模式 进入开发者选项&#xff0c;打开USB调试 …

Android实战之app版本更新升级全文章(二)

BaseAndroid.checkUpdate(MainActivity.this, 2, “http://f5.market.mi-img.com/download/AppStore/0f4a347f5ce5a7e01315dda1ec35944fa56431d44/luo.footprint.apk”, “更新了XXX\n修复OOO”, false); 看看效果图 界面有点丑&#xff0c;自己修改下吧 当然啦&#xff0c…

Golang | Leetcode Golang题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; func twoSum(numbers []int, target int) []int {low, high : 0, len(numbers) - 1for low < high {sum : numbers[low] numbers[high]if sum target {return []int{low 1, high 1}} else if sum < target {low} else {high--}}r…

Ubuntu系统通过GRUB引导菜单进入恢复模式修改账户密码

当在Ubuntu系统中忘记了账户密码时&#xff0c;有几种方法可以破解或重置密码。 本指引文档方法&#xff1a;通过GRUB引导菜单进入恢复模式 实践环境为&#xff1a;20.04.6 LTS (Focal Fossa) 1. 重启Ubuntu系统&#xff1a;首先&#xff0c;你需要重启你的Ubuntu系统。 2. …

Redis 7.x 系列【3】多种连接方式

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. Redis Cli3. 可视化管理工具3.1 Redis Insight3.2 RedisDesktopManager 4. …

Windows环境利用 OpenCV 中 CascadeClassifier 分类器识别人眼 c++

Windows环境中配置OpenCV 关于在Windows环境中配置opencv的说明&#xff0c;具体可以参考&#xff1a;VS2022 配置OpenCV开发环境详细教程。 CascadeClassifier 分类器 CascadeClassifier 是 OpenCV 库中的一个类&#xff0c;它用于实现一种快速的物体检测算法&#xff0c;称…

day41--Redis(三)高级篇之最佳实践

Redis高级篇之最佳实践 今日内容 Redis键值设计批处理优化服务端优化集群最佳实践 1、Redis键值设计 1.1、优雅的key结构 Redis的Key虽然可以自定义&#xff0c;但最好遵循下面的几个最佳实践约定&#xff1a; 遵循基本格式&#xff1a;[业务名称]:[数据名]:[id]长度不超过…