Apollo10.0学习——planning模块(10)之依赖注入器injector_
好不好奇injector_是干什么用的?为什么planning每个模块都要初始化这个变量?
类功能概述
DependencyInjector
(依赖注入器)是一个 集中管理规划模块关键数据和服务 的容器类。它通过提供统一的访问接口,解耦各个组件之间的直接依赖关系,实现以下目标:
- 资源集中管理:避免模块内部重复创建对象,简化生命周期管理。
- 数据一致性:确保不同算法组件访问的是同一份上下文数据。
- 可测试性:方便在单元测试中替换 Mock 对象注入。
代码逐行解析
1. 命名空间与类定义
namespace apollo {
namespace planning {class DependencyInjector {public:DependencyInjector() = default; // 默认构造函数~DependencyInjector() = default; // 默认析构函数
- 作用域:归属于 Apollo 的
planning
命名空间,标识为规划模块专用。 - 构造函数/析构函数:使用编译器默认生成版本,所有成员变量自动构造/析构。
2. 公有成员方法(访问接口)
PlanningContext* planning_context() { return &planning_context_; }FrameHistory* frame_history() { return &frame_history_; }History* history() { return &history_; }EgoInfo* ego_info() { return &ego_info_; }apollo::common::VehicleStateProvider* vehicle_state() {return &vehicle_state_;}LearningBasedData* learning_based_data() { return &learning_based_data_; }
- 功能:提供对私有成员变量的 指针访问(注意此处是指针,不是引用)。
- 接口用途:
planning_context()
: 获取规划上下文(如当前决策状态、障碍物交互信息)。frame_history()
: 获取历史帧数据(用于轨迹预测或回滚)。history()
: 全局历史记录(长期驾驶行为分析)。ego_info()
: 自车动态信息(位置、速度、航向等)。vehicle_state()
: 车辆状态提供器(实时传感器数据融合结果)。learning_based_data()
: 学习模型输出数据(如深度学习预测的轨迹)。
3. 私有成员变量(依赖项实例)
private:PlanningContext planning_context_; // 规划上下文数据FrameHistory frame_history_; // 帧历史缓存History history_; // 全局历史记录EgoInfo ego_info_; // 自车状态信息apollo::common::VehicleStateProvider vehicle_state_; // 车辆状态提供器LearningBasedData learning_based_data_; // 学习模型数据
- 关键成员说明:
-
PlanningContext
:
存储当前规划周期内的动态上下文,如:- 参考线选择状态
- 障碍物的预测轨迹与交互优先级
- 交通规则应用结果(如红灯停车、让行)
-
FrameHistory
:
按时间戳缓存历史帧数据,用于:- 轨迹连续性检查(防止突变)
- 回滚调试(重现规划失败场景)
- 多帧信息融合(如滤波算法)
-
VehicleStateProvider
:
提供实时车辆状态,数据来源于:- 底盘 CAN 信号(速度、转向角)
- 定位模块(GNSS/RTK 位置)
- IMU(加速度、角速度)
-
设计模式解析
依赖注入模式
-
传统问题:模块内部直接创建依赖对象会导致:
- 高耦合:组件难以独立替换或测试。
- 资源竞争:多个实例可能导致数据不一致。
-
解决方案:
- 单一容器:
DependencyInjector
集中管理所有依赖项。 - 接口隔离:外部组件通过接口获取依赖,不关心实现细节。
- 单一容器:
-
Apollo 应用场景:
// 示例:规划算法中获取车辆状态 void PlanningAlgorithm::Run() {auto vehicle_state = injector_->vehicle_state();double speed = vehicle_state->linear_velocity(); }
线程安全与数据同步
- 潜在问题:多线程环境下,不同组件可能同时读写同一依赖项。
- Apollo 处理策略:
- 写时复制:关键数据(如
EgoInfo
)更新时生成副本,避免锁竞争。 - 时序控制:规划周期内依赖项状态冻结,确保一致性。
- 写时复制:关键数据(如
演进与扩展性
- 新增依赖项:只需在
DependencyInjector
中添加成员变量和访问接口,无需修改已有代码。 - 动态替换:通过子类化实现依赖项的动态替换(如测试专用注入器)。
与 Apollo 其他模块的交互
- 定位模块:
VehicleStateProvider
依赖定位数据更新。 - 感知模块:
PlanningContext
整合感知障碍物信息。 - 控制模块:最终规划轨迹通过
DependencyInjector
共享给控制模块执行。
通过这种设计,Apollo 的规划模块实现了 高内聚、低耦合 的架构,为复杂的自动驾驶决策规划提供了高效可靠的基础设施。
详细代码:
namespace apollo {
namespace planning {class DependencyInjector {public:DependencyInjector() = default;~DependencyInjector() = default;// 获取规划上下文(如当前决策状态、障碍物交互信息)。PlanningContext* planning_context() { return &planning_context_; } // 获取历史帧数据(用于轨迹预测或回滚)。FrameHistory* frame_history() { return &frame_history_; }// 全局历史记录(长期驾驶行为分析)。History* history() { return &history_; }// 自车动态信息(位置、速度、航向等)。EgoInfo* ego_info() { return &ego_info_; }// 车辆状态提供器(实时传感器数据融合结果)。apollo::common::VehicleStateProvider* vehicle_state() {return &vehicle_state_;}// 学习模型输出数据(如深度学习预测的轨迹)。LearningBasedData* learning_based_data() { return &learning_based_data_; }private:PlanningContext planning_context_;FrameHistory frame_history_;History history_;EgoInfo ego_info_;apollo::common::VehicleStateProvider vehicle_state_;LearningBasedData learning_based_data_;
};} // namespace planning
} // namespace apollo