apollo规划架构

2024-06-23 14:12
文章标签 apollo 架构 规划

本文主要是介绍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

这篇关于apollo规划架构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1087384

相关文章

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

通信系统网络架构_2.广域网网络架构

1.概述          通俗来讲,广域网是将分布于相比局域网络更广区域的计算机设备联接起来的网络。广域网由通信子网于资源子网组成。通信子网可以利用公用分组交换网、卫星通信网和无线分组交换网构建,将分布在不同地区的局域网或计算机系统互连起来,实现资源子网的共享。 2.网络组成          广域网属于多级网络,通常由骨干网、分布网、接入网组成。在网络规模较小时,可仅由骨干网和接入网组成

响应式架构

介绍 响应式架构(Reactive Architecture)是一种面向服务和事件的系统设计方法,旨在提高系统的可扩展性、弹性和容错能力。它适用于构建分布式系统,特别是在云环境和微服务架构中。响应式架构的核心理念是通过事件驱动和数据流来实现各个组件之间的解耦,从而提高整个系统的响应能力和可靠性。 响应式架构的主要特点包括: 响应性:系统能够快速响应外部事件和内部变化,确保在各种负载和故障情

大型网站架构演化(六)——使用反向代理和CDN加速网站响应

随着网站业务不断发展,用户规模越来越大,由于中国复杂的网络环境,不同地区的用户访问网站时,速度差别也极大。有研究表明,网站访问延迟和用户流失率正相关,网站访问越慢,用户越容易失去耐心而离开。为了提供更好的用户体验,留住用户,网站需要加速网站访问速度。      主要手段:使用CDN和反向代理。如图。     使用CDN和反向代理的目的都是尽早返回数据给用户,一方面加快用户访问速

大型网站架构演化(五)——数据库读写分离

网站在使用缓存后,使绝大部分数据读操作访问都可以不通过数据库就能完成,但是仍有一部分读操作(缓存访问不命中、缓存过期)和全部的写操作需要访问数据库,在网站的用户达到一定规模后,数据库因为负载压力过大而成为网站的瓶颈。      目前豆粉的主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上。网站利用数据库的这一功能,

大型网站架构演化(四)——使用应用服务器集群改善网站的并发能力

使用集群是网站解决高并发、海量数据问题的常用手段。当一台服务器的处理能力、存储空间不足时,不要企图去更换更强大的服务器,对大型服务器而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求。这种情况下,更恰当的做法是增加一台服务器分担原有服务器的访问及存储压力。 对网站架构而言,只要能通过增加一台服务器的方式改善负载压力,就可以以同样的方式持续增加服务器不断改善系统性能,从而实现系统

大型网站架构演化(二)——应用服务和数据服务分离

随着网站业务的发展,一台服务器逐渐不能满足需求:越来越多的用户访问导致性能越来越差,越来越多的数据导致存储空间不足。这时就需要将应用和数据分离。应用和数据分离后整个网站使用三台服务器:应用服务器、文件服务器和数据库服务器,如图。              这三台服务器对硬件资源的要求各不相同: 应用服务器需要处理大量的业务逻辑,因此需要更快更强大的CPU;

大型网站架构演化(一)——初始阶段的网站架构

大型网站的技术挑战主要来自于庞大的用户,高并发的访问和海量的数据,任何简单的业务一旦需要处理数以P计的数据和面对数以亿计的用户,问题就会变得很棘手。大型网站架构主要是解决这类问题。         大型网站都是从小型网站发展而来,网站架构也是一样,是从小型网站架构逐步演化而来。小型网站最开始时没有太多人访问,只需要一台服务器就绰绰有余,这时的网站架构如图所示。

IPD推行成功的核心要素(十一)技术规划与平台规划促进公司战略成功

随着外部大环境的影响,各企业仅有良好的愿望是不够的。预测并顺应新兴市场和技术的变化,变危机为转机,不断推出强大的产品才是一个公司持续繁荣的根本保障。而高效的产品开发往往是基于某些关键技术,针对市场推出的一个或几个产品系列,这些产品系列通常共用一些产品平台,共用一种或者几种关键技术。当一家企业进入了平稳发展期,已经建立了较为完善的管理制度和产品开发流程,但是依然认为竞争对手是那样强大,那样不可战胜。

大型网站架构演化(总)

如果把上世纪90年代初CERN正式发布WEB标准和第一个WEB服务的出现当做互联网站的开始,那么互联网站的发展只经历了短短20多年的时间。在20多年的时间里,互联网的世界发生了巨大变化,今天,全球有近一半的人口使用互联网,人们的生活因为互联网而产生了巨大变化。从信息检索到即时通信,从电子购物到文化娱乐,互联网渗透到生活的每个角落,而且这种趋势还在加速。因为互联网,我们的世界正变得越来越小