Apollo学习——planning模块(3)之planning_base
planning_component、planning_base、on_lane_planning 和 navi_planning 的关系
1. 模块关系总览
继承层次
PlanningComponent
:Cyber RT 框架中的 入口组件,负责调度规划模块的输入输出和管理生命周期。PlanningBase
:规划算法的 抽象基类,定义通用接口(如Init()
,RunOnce()
)。OnLanePlanning
与NaviPlanning
:继承自PlanningBase
的 具体规划器实现,分别针对不同场景设计的动态多态子类。
调用关系
PlanningComponent → (通过指针调用) PlanningBase → OnLanaPlanning/NaviPlanning → 具体规划算法
2. 各模块作用详解
(1) PlanningComponent
-
功能定位:
- 数据集成:接收上游模块的输入(如
PredictionObstacles
障碍物预测、LocalizationEstimate
定位数据、Chassis
底盘信息)。 - 生命周期管理:通过
Init()
初始化规划器(选择OnLanePlanning
或NaviPlanning
),在Proc()
中触发规划主流程。 - 消息发布:输出规划轨迹
ADCTrajectory
、路由请求RoutingRequest
和学习数据PlanningLearningData
。
- 数据集成:接收上游模块的输入(如
-
核心代码逻辑:
// 初始化时根据配置选择规划模式 if (FLAGS_use_navigation_mode) {planning_base_ = std::make_unique<NaviPlanning>(injector_); } else {planning_base_ = std::make_unique<OnLanePlanning>(injector_); }
(2) PlanningBase
-
功能定位:
- 抽象接口定义:提供规划算法的统一接口(如
RunOnce()
和Plan()
),确保子类实现一致性。 - 数据封装:管理
Frame
对象(包含车辆状态、环境信息)和DependencyInjector
(依赖注入容器,集成场景、车辆模型等)。 - 多态支持:通过虚函数机制实现动态绑定,允许运行时切换
OnLanePlanning
或NaviPlanning
。
- 抽象接口定义:提供规划算法的统一接口(如
-
关键成员:
Frame
:整合当前车辆状态、障碍物信息、参考线等上下文数据。ReferenceLineInfo
:存储参考线及其动态决策信息,供轨迹规划使用。
(3) OnLanePlanning
-
功能定位:
- 高精地图规划:基于高精地图生成参考线,适用于 城市道路、复杂交通场景(如红绿灯路口、人行道)。
- 场景机制:内置双层状态机(Scenario + Stage),支持
LaneFollowScenario
(车道保持)、TrafficLightProtectedScenario
(交通灯路口)等场景。 - 任务调度:调用
PublicRoadPlanner
等规划器,执行具体的路径优化算法(如 EM Planner、Lattice Planner)。
-
典型流程:
- 生成参考线(
ReferenceLineProvider
)。 - 场景切换判定(
ScenarioManager::Update()
)。 - 执行场景内的多阶段任务(Stage + Task)。
- 生成参考线(
(4) NaviPlanning
-
功能定位:
- 相对地图规划:基于实时生成的相对地图(
relative_map
),适用于 高速公路 或其他 规则简单场景。 - 轻量化设计:简化参考线生成逻辑,依赖车道级导航信息而非全局高精地图。
- 高效处理:优化算法复杂度,适合长距离、低动态障碍物的场景。
- 相对地图规划:基于实时生成的相对地图(
-
与 OnLanePlanning 的差异:
特性 OnLanePlanning NaviPlanning 地图依赖 高精地图 相对地图(动态生成) 适用场景 城市道路、复杂交通 高速公路、规则简单道路 场景切换机制 支持多场景状态机 场景逻辑简化 计算资源消耗 较高 较低
3. 数据流与功能协作
协作流程
- 输入触发:
PlanningComponent
的Proc()
由上游消息(如障碍物预测)触发,整合LocalView
数据包。
- 规划执行:
- 调用
planning_base_->RunOnce()
,由具体子类(OnLanePlanning
或NaviPlanning
)实现规划逻辑。
- 调用
- 场景与任务:
OnLanePlanning
中通过ScenarioManager
切换场景,执行阶段任务(如绕障、停车)。NaviPlanning
直接生成参考线并规划轨迹,跳过复杂场景判定。
- 结果输出:
- 发布
ADCTrajectory
轨迹至控制模块,完成闭环。
- 发布
关键交互点
DependencyInjector
:注入全局依赖(如车辆状态、历史轨迹),供所有子类共享。PlanningLearningData
:在RL_TEST
模式下收集强化学习训练数据。
总结
PlanningComponent
是入口,负责数据集成与调度。PlanningBase
定义框架,实现多态支持。OnLanePlanning
面向复杂场景,NaviPlanning
面向高速场景,二者通过继承实现功能差异化。
基类:planning_base
规划器(OnLanePlanning、NaviPlanning)需要重写的函数有
//初始化virtual apollo::common::Status Init(const PlanningConfig& config);//可以不重写virtual std::string Name() const = 0;virtual void RunOnce(const LocalView& local_view, ADCTrajectory* const adc_trajectory) = 0;virtual apollo::common::Status Plan( const double current_time_stamp, const std::vector<common::TrajectoryPoint>& stitching_trajectory, ADCTrajectory* const trajectory) = 0;
不需要重写的有
//判断规划是否完成bool IsPlanningFinished( const ADCTrajectory::TrajectoryType& current_trajectory_type) const;// 为轨迹添加设置路的左右边界bool GenerateWidthOfLane(const Vec2d& current_location, Vec2d& left_point, Vec2d& right_point);protected://规划模块生成轨迹数据时填充协议头信息(Header)的核心方法virtual void FillPlanningPb(const double timestamp, ADCTrajectory* const trajectory_pb);//加载规划器 默认使用apollo::planning::PublicRoadPlannervoid LoadPlanner();
代码解释
namespace apollo {
namespace planning {using apollo::common::Status;PlanningBase::PlanningBase(const std::shared_ptr<DependencyInjector>& injector): injector_(injector) {}PlanningBase::~PlanningBase() {}
//如果不重写,则使用基类Init,加载参数
Status PlanningBase::Init(const PlanningConfig& config) {injector_->planning_context()->Init();config_ = config;return Status::OK();
}
//判断规划状态是否完成
bool PlanningBase::IsPlanningFinished(const ADCTrajectory::TrajectoryType& current_trajectory_type) const {const auto frame = injector_->frame_history()->Latest();//判断当前轨迹类型是否为OPEN SPACE 泊车if (current_trajectory_type == apollo::planning::ADCTrajectory::OPEN_SPACE) {AINFO << "Current trajectory type is: OPEN SPACE";if (frame->open_space_info().openspace_planning_finish()) {AINFO << "OPEN SPACE: planning finished";return true;} else {AINFO << "OPEN SPACE: planning not finished";return false;}} else {// const auto frame = injector_->frame_history()->Latest();if (nullptr == frame || frame->reference_line_info().empty() ||nullptr == local_view_.planning_command) {AINFO << "Current reference point is empty;";return true;}const auto& reference_line_info = frame->reference_line_info().front();// Check if the ReferenceLineInfo is the last passage.const auto& reference_points =reference_line_info.reference_line().reference_points();if (reference_points.empty()) {AINFO << "Current reference points is empty;";return true;}const auto& last_reference_point = reference_points.back();const std::vector<hdmap::LaneWaypoint>& lane_way_points =last_reference_point.lane_waypoints();if (lane_way_points.empty()) {AINFO << "Last reference point is empty;";return true;}// Get the end lane way point.if (nullptr == frame->local_view().end_lane_way_point) {AINFO << "Current end lane way is empty;";return true;}bool is_has_passed_destination = injector_->planning_context()->planning_status().destination().has_passed_destination();AINFO << "Current passed destination:" << is_has_passed_destination;return is_has_passed_destination;}
}
// 规划模块生成轨迹数据时填充协议头信息(Header)的核心方法
// 时间戳同步:设置轨迹消息的全局时间戳
// 多传感器时间对齐:记录激光雷达、摄像头、雷达等传感器的原始数据时间戳
// 路由信息传递:复制当前路由请求的元数据
void PlanningBase::FillPlanningPb(const double timestamp,ADCTrajectory* const trajectory_pb) {trajectory_pb->mutable_header()->set_timestamp_sec(timestamp); // timestamp通常通过Clock::NowInSeconds()获取系统当前时间// 多传感器时间对齐if (local_view_.prediction_obstacles->has_header()) {trajectory_pb->mutable_header()->set_lidar_timestamp(local_view_.prediction_obstacles->header().lidar_timestamp());trajectory_pb->mutable_header()->set_camera_timestamp(local_view_.prediction_obstacles->header().camera_timestamp());trajectory_pb->mutable_header()->set_radar_timestamp(local_view_.prediction_obstacles->header().radar_timestamp());}// local_view_.planning_command包含来自Routing模块的全局路径请求trajectory_pb->mutable_routing_header()->CopyFrom(local_view_.planning_command->header());
}
//加载规划器默认apollo::planning::PublicRoadPlanner
void PlanningBase::LoadPlanner() {// Use PublicRoadPlanner as default Plannerstd::string planner_name = "apollo::planning::PublicRoadPlanner";if ("" != config_.planner()) {planner_name = config_.planner();planner_name = ConfigUtil::GetFullPlanningClassName(planner_name);}planner_ =cyber::plugin_manager::PluginManager::Instance()->CreateInstance<Planner>(planner_name);
}
//设置路的左右边界
bool PlanningBase::GenerateWidthOfLane(const Vec2d& current_location,Vec2d& left_point, Vec2d& right_point) {double left_width = 0, right_width = 0;const auto frame = injector_->frame_history()->Latest();if (nullptr == frame || frame->reference_line_info().empty()) {AINFO << "Reference lane is empty!";return false;}const auto& reference_line_info = frame->reference_line_info().front();// get current SLcommon::SLPoint current_sl;reference_line_info.reference_line().XYToSL(current_location, ¤t_sl);// Get the lane width of vehicle locationbool get_width_of_lane = reference_line_info.reference_line().GetLaneWidth(current_sl.s(), &left_width, &right_width);AINFO << "get_width_of_lane: " << get_width_of_lane<< ", left_width: " << left_width << ", right_width: " << right_width;if (get_width_of_lane && left_width != 0 && right_width != 0) {AINFO << "Get the width of lane successfully!";SLPoint sl_left_point, sl_right_point;sl_left_point.set_s(current_sl.s());sl_left_point.set_l(left_width);sl_right_point.set_s(current_sl.s());sl_right_point.set_l(-right_width);reference_line_info.reference_line().SLToXY(sl_left_point, &left_point);reference_line_info.reference_line().SLToXY(sl_right_point, &right_point);return true;} else {AINFO << "Failed to get the width of lane!";return false;}
}} // namespace planning
} // namespace apollo
相关文章:
Apollo学习——planning模块(3)之planning_base
planning_component、planning_base、on_lane_planning 和 navi_planning 的关系 1. 模块关系总览 继承层次 PlanningComponent:Cyber RT 框架中的 入口组件,负责调度规划模块的输入输出和管理生命周期。PlanningBase:规划算法的 抽象基类&…...

当 AI 邂逅丝路:揭秘「丝路智旅」,用 RAG 重塑中阿文化旅游体验
目录 系统命名:丝路智旅 (Silk Road Intelligent Travel)系统概述系统架构设计系统功能模块技术选型:为何是它们?系统优势与特点未来展望与扩展总结在数字浪潮席卷全球的今天,古老的丝绸之路正在以一种全新的方式焕发生机。当深厚的文化底蕴遇上尖端的人工智能技术,会碰撞…...

18.Excel数据透视表:第1部分创建数据透视表
一 什么是数据透视表 通过万花筒可以用不同的方式査看里面画面图像,在excel中可以将数据透视表看作是对准数据的万花筒,用不同角度去观察数据,也可以旋转数据,对数据进行重新排列,对大量的数据可以快速的汇总和建立交叉…...

CSS AI 通义灵码 VSCode插件安装与功能详解
简介 在前端开发领域,页面调试一直是个繁琐的过程,而传统开发中美工与前端的对接也常常出现问题。如今,阿里云技术团队推出的通义灵码智能编码助手,为前端开发者带来了新的解决方案,让开发者可以像指挥者一样…...
每日c/c++题 备战蓝桥杯(P1002 [NOIP 2002 普及组] 过河卒)
洛谷P1002 [NOIP 2002 普及组] 过河卒 题解 题目描述 过河卒是一道经典的动态规划题目。题目大意是:一个卒子从棋盘左上角(0,0)出发,要走到右下角(n,m),棋盘上有一个马在(x,y)位置,卒子不能经过马所在位置及其周围8个位置。求卒…...

【Linux网络】TCP全连接队列
TCP 相关实验 理解 listen 的第二个参数 基于刚才封装的 TcpSocket 实现以下测试代码对于服务器, listen 的第二个参数设置为 1, 并且不调用 accept测试代码链接 test_server.cc #include "tcp_socket.hpp"int main(int argc, char* argv[]) {if (argc ! 3) {pri…...

HTML 颜色全解析:从命名规则到 RGBA/HSL 值,附透明度设置与场景应用指南
一、HTML 颜色系统详解 HTML 中的颜色可以通过多种方式定义,包括颜色名称、RGB 值、十六进制值、HSL 值等,同时支持透明度调整。以下是详细分类及应用场景: 1. 颜色名称(预定义关键字) HTML 预定义了 140 个标准颜色名…...
蓝桥杯12届国B 完全日期
题目描述。 如果一个日期中年月日的各位数字之和是完全平方数,则称为一个完全日期。 例如:2021 年 6 月 5 日的各位数字之和为 20216516,而 16 是一个完全平方数,它是 4 的平方。所以 2021 年 6 月 5 日是一个完全日期。 例如&…...

深度剖析多模态大模型中的视频编码器算法
写在前面 随着多模态大型语言模型(MLLM)的兴起,AI 理解世界的能力从静态的文本和图像,进一步拓展到了动态的、包含丰富时空信息的视频。视频作为一种承载了动作、交互、场景变化和声音(虽然本文主要聚焦视觉部分)的复杂数据形式,为 MLLM 提供了理解真实世界动态和因果关…...

游戏引擎学习第282天:Z轴移动与摄像机运动
运行游戏,展示目前进展 我们目前正在进行一个游戏开发项目。昨天,我们实现了基于房间的角色移动系统,并且加入了摄像机的跟随滚动功能。这是我们首次进入“游戏逻辑设计”阶段,也就是说,我们开始构建游戏本身的行为和…...
C++中的std::allocator
C中的std::allocator 文章目录 C中的std::allocator1.std::allocator1.1C中的placement new 和operator new1.2一个custom allocator的实现1.3使用std::allocator_traits实现allocator 1.std::allocator C中的std::allocator默默工作在CSTL中的所有容器的内存分配上࿰…...
Git/GitLab日常使用的命令指南来了!
在 GitLab 中拉取并合并代码的常见流程是通过 Git 命令来完成的。以下是一个标准的 Git 工作流,适用于从远程仓库(如 GitLab)拉取代码、切换分支、合并更新等操作。 🌐 一、基础命令:拉取最新代码 # 拉取远程仓库的所…...

aws 实践创建policy + Role
今天Cyber 通过image 来创建EC2 的时候,要添加policy, 虽然是administrator 的role, 参考Cyber 提供的link: Imageshttps://docs.cyberark.com/pam-self-hosted/14.2/en/content/pas%20cloud/images.htm#Bring 1 Step1:...
[Java实战]Spring Boot 解决跨域问题(十四)
[Java实战]Spring Boot 解决跨域问题(十四) 一、CORS 问题背景 什么是跨域问题? 当浏览器通过 JavaScript 发起跨域请求(不同协议、域名、端口)时,会触发同源策略限制,导致请求被拦截。 示例场…...

【HarmonyOS 5】鸿蒙星闪NearLink详解
【HarmonyOS 5】鸿蒙星闪NearLink详解 一、前言 鸿蒙星闪NearLink Kit 是 HarmonyOS 提供的短距离通信服务,支持星闪设备间的连接、数据交互。例如,手机可作为中心设备与外围设备(如鼠标、手写笔、智能家电、车钥匙等)通过星闪进…...
Python高级进阶:Vim与Vi使用指南
李升伟 整理 在 Python 高级进阶中,使用 Vim 或 Vi 作为代码编辑器可以显著提升开发效率,尤其是在远程服务器开发或快速脚本编辑时。以下是关于它们在 Python 开发中的高级应用详解: 1. Vim/Vi 简介 Vi:经典的 Unix 文本编辑器…...
【Python】对象生命周期全解析
Python对象生命周期全解析 在Python中,一个对象从创建到销毁会经历一系列过程,理解这些过程对于编写高效、可靠的Python代码非常重要。下面我将详细讲解Python对象的完整生命周期。 1. 对象创建阶段 (1) 内存分配 当使用类实例化时(obj MyClass())&…...
自然语言处理(NLP)在影评情感分析中的处理流程示例
自然语言处理(NLP)在影评情感分析中的处理流程示例 以影评情感分析为例,为你详细介绍自然语言处理的处理流程。在这个例子中,我们将使用 Python 和一些常用的 NLP 库,如nltk(自然语言工具包)和…...

WF24 wifi/蓝牙模块串口与手机蓝牙通信
usb-ttl ch340接线 打开串口工具SSCOM,端口号选择ch340接的那个口,波特率改成115200 DX-SMART_2.0.5.apk下载 手机打开DX-SMART软件 点击透传-搜索BLE-连接WF24-BLE 连接成功串口会收到消息 [14:37:10.591]收←◆ BLE_CONNECT_SUCCESS发送命令ATBLUFI…...
互联网大厂Java求职面试:优惠券服务架构设计与AI增强实践-3
互联网大厂Java求职面试:优惠券服务架构设计与AI增强实践-3 场景背景 面试场景设定在一家大型互联网公司,面试官为拥有10年以上经验的技术总监,专注于高并发、高可用系统的架构设计。候选人郑薪苦是一名技术潜力十足的程序员,擅…...
C++核心编程--1 内存分区模型
C程序执行时,内存可以划分为4部分 代码区:存放函数体的二进制代码 全局区:存放全局变量、静态变量、常量 栈区:局部变量、函数参数值,编译器自动分配和释放 堆区:程序员自己分配和释放 1.1 程序运行前…...
02_线性模型(回归分类模型)
用于分类的线性模型 线性模型也广泛应用于分类问题,可以利用下面的公式进行预测: $ \widehat y w[0]*x[0]w[1]*x[1]…w[p]*x[p]b > 0$ 公式看起来与线性回归的公式非常相似,但没有返回特征的加权求和,而是为预测设置了阈值…...

通义千问席卷日本!开源界“卷王”阿里通义千问成为日本AI发展新基石
据日本经济新闻(NIKKEI)报道,通义千问已成为日本AI开发的新基础,其影响力正逐步扩大,深刻改变着日本AI产业的格局。 同时,日本经济新闻将通义千问Qwen2.5-Max列为全球AI模型综合评测第六名,不仅…...

流程编辑器Bpmn与LogicFlow学习
工作流技术如何与用户交互结合(如动态表单、任务分配)处理过 XML 与 JSON 的转换自定义过 bpmn.js 的样式(如修改节点颜色、形状、图标)扩展过上下文菜单(Palette)或属性面板(Properties Panel&…...

Figma 新手教程学习笔记
📺 视频地址:Figma新手教程2025|30分钟高效掌握Figma基础操作与UI设计流程_哔哩哔哩_bilibili 🧭 课程结构 Figma 简介(00:38) 熟悉工作环境(01:49) 操作界面介绍(03:…...
RabbitMQ的工作队列模式和路由模式有什么区别?
RabbitMQ 的工作队列模式(Work Queues)和路由模式(Routing)是两种不同的消息传递模式,主要区别在于消息的分发逻辑和使用场景。以下是它们的核心差异: 1. 工作队列模式(Work Queues)…...
什么是 ANR 如何避免它
一、什么是 ANR? ANR(Application Not Responding) 是 Android 系统在应用程序主线程(UI 线程)被阻塞超过一定时间后触发的错误机制。此时系统会弹出一个对话框提示用户“应用无响应”,用户可以选择等待或强…...

配置Spark环境
1.上传spark安装包到某一台机器(自己在finaShell上的机器)。 2.解压。 把第一步上传的安装包解压到/opt/module下(也可以自己决定解压到哪里)。对应的命令是:tar -zxvf 安装包 -C /opt/module 3.重命名。进入/opt/mo…...
嵌入式硬件篇---IIC
文章目录 前言1. IC协议基础1.1 物理层特性两根信号线SCLSDA支持多主多从 标准模式电平 1.2 通信流程起始条件(Start Condition)从机地址(Slave Address)应答(ACK/NACK)数据传输:停止条件&#…...

Window下Jmeter多机压测方法
1.概述 Jmeter多机压测的原理,是通过单个jmeter客户端,控制多个远程的jmeter服务器,使他们同步的对服务器进行压力测试。 以此方式收集测试数据的好处在于: 保存测试采样数据到本地机器通过单台机器管理多个jmeter执行引擎测试…...