团队博客: 汽车电子社区
一、模块概述
Perception模块是Apollo自动驾驶系统的"眼睛",负责处理来自各种传感器(摄像头、激光雷达、毫米波雷达等)的数据,实现对周围环境的感知和理解,包括障碍物检测、分类、跟踪和预测。
二、模块架构
2.1 目录结构
modules/perception/
├── camera_detection_bev/ # 鸟瞰图相机检测
├── camera_detection_multi_stage/ # 多阶段相机检测
├── camera_detection_occupancy/ # 占用栅格检测
├── camera_location_estimation/ # 相机定位估计
├── camera_tracking/ # 相机目标跟踪
├── common/ # 感知通用组件
├── fusion/ # 多传感器融合
├── lidar_detection/ # 激光雷达检测
├── radar_detection/ # 毫米波雷达检测
├── perception_component/ # 感知主组件
├── proto/ # 消息定义
└── tools/ # 工具
2.2 核心组件
1. CameraDetectionBEVComponent - 鸟瞰图相机检测组件
2. CameraDetectionMultiStageComponent - 多阶段相机检测组件
3. LidarDetectionComponent - 激光雷达检测组件
4. RadarDetectionComponent - 毫米波雷达检测组件
5. FusionComponent - 多传感器融合组件
6. CameraTrackingComponent - 相机目标跟踪组件
三、接口调用流程图
3.1 整体感知流程图
3.2 相机检测详细流程图
3.3 激光雷达检测流程图
3.4 多传感器融合流程图
四、关键源码分析
4.1 主组件源码分析
4.1.1 CameraDetectionBEVComponent 核心源码分析
类定义位置: modules/perception/camera_detection_bev/camera_detection_bev_component.h
核心功能:
- 继承自 cyber::Component<>,是Apollo Cyber框架下的组件
- 负责接收相机图像数据,执行鸟瞰图(BEV)障碍物检测
- 支持多相机输入融合检测
关键成员变量:
private:
int image_height_; // 图像高度
int image_width_; // 图像宽度
uint32_t seq_num_ = 0; // 序列号
double timestamp_offset_ = 0; // 时间戳偏移
std::shared_ptr<CameraFrame> frame_ptr_; // 相机帧数据
std::shared_ptr<BaseObstacleDetector> detector_; // 障碍物检测器
std::shared_ptr<onboard::TransformWrapper> trans_wrapper_; // 坐标变换
std::vector<std::shared_ptr<cyber::Reader<drivers::Image>>> readers_; // 图像订阅者
std::shared_ptr<cyber::Writer<PerceptionObstacles>> writer_; // 检测结果发布者
初始化流程 (Init() 方法):
bool CameraDetectionBevComponent::Init() {
// 1. 加载配置参数
CameraDetectionBEV detection_param;
if (!GetProtoConfig(&detection_param)) return false;
// 2. 初始化检测器
InitDetector(detection_param);
// 3. 初始化相机帧
InitCameraFrame(detection_param);
// 4. 初始化订阅者
InitListeners(detection_param);
// 5. 初始化坐标变换
InitTransformWrapper(detection_param);
// 6. 创建发布者
writer_ = node_->CreateWriter<PerceptionObstacles>(
detection_param.channel().output_obstacles_channel_name());
return true;
}
检测核心流程 (OnReceiveImage() 方法):
bool CameraDetectionBevComponent::OnReceiveImage(
const std::shared_ptr<drivers::Image>& msg) {
// 1. 处理时间戳
const double msg_timestamp = msg->measurement_time() + timestamp_offset_;
// 2. 填充图像数据到多相机帧
for (size_t i = 0; i < readers_.size(); ++i) {
readers_[i]->Observe();
const auto& camera_msg = readers_[i]->GetLatestObserved();
frame_ptr_->data_provider[i]->FillImageData(
image_height_, image_width_,
reinterpret_cast<const uint8_t*>(camera_msg->data().data()),
camera_msg->encoding());
}
// 3. 设置帧信息
frame_ptr_->timestamp = msg_timestamp;
++frame_ptr_->frame_id;
// 4. 执行障碍物检测
detector_->Detect(frame_ptr_.get());
// 5. 坐标系转换:相机坐标 -> 世界坐标
Eigen::Affine3d lidar2world_trans;
if (!trans_wrapper_->GetSensor2worldTrans(msg_timestamp, &lidar2world_trans)) {
AERROR << "Failed to get camera to world pose";
}
CameraToWorldCoor(lidar2world_trans, &frame_ptr_->detected_objects);
// 6. 构造并发布消息
std::shared_ptr<PerceptionObstacles> out_message(new PerceptionObstacles);
if (MakeProtobufMsg(msg_timestamp, seq_num_, frame_ptr_->detected_objects,
out_message.get()) != cyber::SUCC) {
return false;
}
seq_num_++;
writer_->Write(out_message);
return true;
}
关键技术特点:
1. 多相机融合: 支持多个相机输入同时检测
2. 鸟瞰图检测: 将图像转换为BEV视角进行检测
3. 实时坐标变换: 使用TransformWrapper获取实时位姿
4. 插件化检测器: 通过BaseObstacleDetector接口支持不同算法
4.1.2 BaseObstacleDetector 接口分析
位置: modules/perception/camera_detection_bev/interface/base_obstacle_detector.h
核心接口设计:
class BaseObstacleDetector {
public:
// 初始化检测器
virtual bool Init(const ObstacleDetectorInitOptions& options) = 0;
// 主检测函数
virtual bool Detect(CameraFrame* frame) = 0;
// 获取检测器名称
virtual std::string Name() const = 0;
// 网络初始化
virtual bool InitNetwork(const common::ModelInfo& model_info,
const std::string& model_root);
protected:
int gpu_id_ = 0; // GPU设备ID
std::shared_ptr<inference::Inference> net_; // 深度学习推理引擎
};
插件注册机制:
PERCEPTION_REGISTER_REGISTERER(BaseObstacleDetector);
#define REGISTER_OBSTACLE_DETECTOR(name) \
PERCEPTION_REGISTER_CLASS(BaseObstacleDetector, name)
初始化选项:
struct ObstacleDetectorInitOptions : public BaseInitOptions {
int image_height; // 图像高度
int image_width; // 图像宽度
Eigen::Matrix3f intrinsic; // 相机内参矩阵
};
4.1.3 LidarDetectionComponent 激光雷达检测组件
位置: modules/perception/lidar_detection/lidar_detection_component.h
核心功能:
class LidarDetectionComponent : public cyber::Component<LidarFrameMessage> {
public:
bool Init() override; // 初始化组件
bool Proc(const std::shared_ptr<LidarFrameMessage>& message) override; // 处理点云数据
private:
bool InternalProc(const std::shared_ptr<LidarFrameMessage>& in_message); // 内部处理
private:
std::string sensor_name_; // 传感器名称
bool use_object_builder_ = true; // 是否使用对象构建器
std::shared_ptr<BaseLidarDetector> detector_; // 激光雷达检测器
ObjectBuilder builder_; // 对象构建器
std::string output_channel_name_; // 输出通道名称
std::shared_ptr<apollo::cyber::Writer<onboard::LidarFrameMessage>> writer_; // 发布者
};
处理流程:
1. 输入: 接收LidarFrameMessage包含点云数据
2. 检测: 调用BaseLidarDetector进行目标检测
3. 构建: 使用ObjectBuilder构建障碍物对象
4. 输出: 发布检测结果到指定通道
4.2 感知通用组件分析
4.2.1 DataProvider 数据提供者
位置: modules/perception/common/camera/common/data_provider.h
核心功能:
- 管理原始图像数据的加载、转换和预处理
- 提供统一的图像数据访问接口
- 支持图像格式转换和畸变校正
初始化选项:
struct InitOptions {
InitOptions() : image_height(0), image_width(0), device_id(-1), do_undistortion(false) {}
int image_height; // 图像高度
int image_width; // 图像宽度
int device_id; // GPU设备ID
bool do_undistortion; // 是否进行畸变校正
std::string sensor_name; // 传感器名称
};
图像选项:
struct ImageOptions {
base::Color target_color = base::Color::BGR; // 目标颜色格式
bool do_crop = false; // 是否裁剪
base::RectI crop_roi; // 裁剪区域
};
核心接口:
class DataProvider {
public:
// 初始化数据提供者
bool Init(const InitOptions& options = InitOptions());
// 填充原始图像数据
bool FillImageData(int rows, int cols, const uint8_t* data, const std::string& encoding);
// 获取图像Blob数据
bool GetImageBlob(const ImageOptions& options, base::Blob<uint8_t>* blob);
// 获取Image8U格式图像
bool GetImage(const ImageOptions& options, base::Image8U* image);
// 颜色空间转换
bool to_gray_image();
bool to_rgb_image();
bool to_bgr_image();
// 访问器
int src_height() const { return src_height_; }
int src_width() const { return src_width_; }
const std::string& sensor_name() const { return sensor_name_; }
protected:
// 内部图像缓存
std::shared_ptr<base::Image8U> ori_gray_; // 原始灰度图像
std::shared_ptr<base::Image8U> ori_rgb_; // 原始RGB图像
std::shared_ptr<base::Image8U> ori_bgr_; // 原始BGR图像
std::shared_ptr<base::Image8U> gray_; // 处理后灰度图像
std::shared_ptr<base::Image8U> rgb_; // 处理后RGB图像
std::shared_ptr<base::Image8U> bgr_; // 处理后BGR图像
// 状态标记
bool gray_ready_ = false; // 灰度图像是否就绪
bool rgb_ready_ = false; // RGB图像是否就绪
bool bgr_ready_ = false; // BGR图像是否就绪
// 临时存储和处理器
base::Blob<float> temp_float_;
base::Blob<uint8_t> temp_uint8_;
std::shared_ptr<UndistortionHandler> handler_; // 畸变校正处理器
};
数据流转过程:
1. 接收数据: FillImageData() 接收原始图像数据
2. 格式转换: 根据需要转换为RGB/BGR/灰度格式
3. 预处理: 可选的畸变校正和裁剪
4. 提供接口: GetImageBlob() 和 GetImage() 提供统一访问
4.2.2 消息接口定义
PerceptionObstacles消息: modules/common_msgs/perception_msgs/perception_obstacle.proto
message PerceptionObstacles {
// 消息头信息
apollo.common.Header header = 1;
// 障碍物列表
repeated PerceptionObstacle perception_obstacle = 2;
// 错误代码
apollo.common.ErrorCode error_code = 3;
// 感知延迟(毫秒)
int32 latency = 4;
// 传感器源信息
repeated SensorSources sensor_sources = 5;
}
message PerceptionObstacle {
// 唯一ID
int32 id = 1;
// 3D位置和尺寸
apollo.common.Point3D position = 2; // 中心点位置
double theta = 3; // 朝向角
double length = 4; // 长度
double width = 5; // 宽度
double height = 6; // 高度
// 运动信息
apollo.common.Point3D velocity = 7; // 速度
apollo.common.Point3D acceleration = 8; // 加速度
// 类型信息
Type type = 9; // 主要类型
SubType sub_type = 10; // 子类型
// 跟踪信息
double timestamp = 11; // 时间戳
int32 track_id = 12; // 跟踪ID
double tracking_time = 13; // 跟踪时长
// 置信度和特征
double confidence = 14; // 置信度
PolygonPoint polygon_point = 15; // 多边形轮廓
// 传感器补充信息
repeated CameraSupplement camera_supplement = 16;
RadarSupplement radar_supplement = 17;
LidarSupplement lidar_supplement = 18;
}
4.3 配置文件分析
4.3.1 主配置文件
CameraDetectionBEV配置: modules/perception/camera_detection_bev/conf/camera_detection_bev.pb.txt
plugin_param {
name: "BEVObstacleDetector" // 检测器插件名称
config_path: "perception/camera/data" // 配置文件路径
config_file: "bev_obstacle_detector.pt" // 模型文件
}
camera_name: "CAM_BACK" // 相机名称
frame_id: "camera_back" // 坐标系ID
gpu_id: 0 // GPU设备ID
enable_undistortion: true // 启用畸变校正
channel {
input_camera_channel_name: "/apollo/sensor/camera/CAM_BACK/image"
output_obstacles_channel_name: "/apollo/perception/obstacles"
}
4.3.2 DAG配置文件
启动配置: modules/perception/camera_detection_bev/dag/camera_detection_bev.dag
# 定义组件
timer_component {
name: "CameraDetectionBEVComponent"
config_path: "conf/perception/camera_detection_bev"
config_name: "camera_detection_bev.pb.txt"
}
# 定义调度器
scheduler {
type: "SCHEDULER_CHOREOGRAPHER"
routine: "CYBER_CPU"
priority: 3
}
# 定义定时器
timer {
name: "CameraDetectionBEVTimer"
interval: 100 // 100ms = 10Hz
components: ["CameraDetectionBEVComponent"]
}
五、性能优化特点
5.1 实时性能保障
- GPU加速: 使用CUDA进行深度学习推理加速
- 内存池管理: 减少动态内存分配开销
- 异步处理: 图像处理与推理并行执行
5.2 多传感器同步
- 时间戳对齐: 确保多传感器数据时间同步
- 空间对齐: 通过坐标变换实现空间统一
- 数据融合: 多模态信息融合提高检测精度
5.3 容错机制
- 重试机制: 检测失败时的重试策略
- 降级处理: 部分传感器失效时的备用方案
- 异常监控: 实时监控模块运行状态
六、总结
Perception模块通过以下关键技术实现了高精度的环境感知:
1. 模块化设计: 清晰的组件分离和接口定义
2. 插件化架构: 支持多种检测算法的灵活替换
3. 多传感器融合: 提高检测的鲁棒性和准确性
4. 实时性能: 优化的数据处理流程和GPU加速
5. 统一接口: 标准化的消息格式和数据访问
该模块为下游的Prediction、Planning等模块提供了可靠的环境感知基础,是整个自动驾驶系统的重要组成部分。

6703

被折叠的 条评论
为什么被折叠?



