Apollo Perception 感知模块接口调用流程图与源码分析


  团队博客: 汽车电子社区


一、模块概述

  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 整体感知流程图

摄像头
激光雷达
毫米波雷达
传感器数据输入
数据预处理
传感器类型
相机检测
激光雷达检测
雷达检测
CameraDetectionBEV
CameraDetectionMultiStage
CameraTracking
LidarDetection
RadarDetection
多传感器融合
感知结果输出
障碍物列表
车道线信息
交通信号灯
Prediction模块

3.2 相机检测详细流程图

相机图像输入
图像预处理
畸变校正
色彩空间转换
BEV变换
特征提取
深度学习推理
后处理
候选框生成
NMS过滤
置信度筛选
障碍物检测
目标分类
3D框生成
结果输出

3.3 激光雷达检测流程图

点云数据输入
点云预处理
地面分割
聚类
特征提取
目标检测
分类识别
3D框拟合
速度估计
结果输出

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等模块提供了可靠的环境感知基础,是整个自动驾驶系统的重要组成部分。

### Apollo 自动驾驶平台感知模块API接口文档 #### 概述 Apollo自动驾驶平台的感知模块是整个系统的关键部分,主要负责处理来自各种传感器的数据并识别周围环境中的对象。这些对象可以包括但不限于车道线、交通标志、行人和其他车辆等。该模块通过一系列复杂的算法来解析原始传感数据,并将其转换成结构化的信息供下游组件使用。 #### 主要功能 感知模块的主要职责如下: - **多源融合**:集成多种类型的传感器输入,如摄像头图像、LiDAR点云以及毫米波雷达信号。 - **目标检测分类**:利用机器学习模型对环境中存在的实体进行辨认和类别划分。 - **语义分割**:将场景划分为不同的区域,比如可通行区、不可通行区等。 - **跟踪预测**:持续监测移动物体的位置变化趋势,预估它们未来可能采取的动作。 #### API设计原则 为了确保高效性和易用性,在设计上遵循RESTful风格的同时也考虑到了实时性能的要求。具体来说: - 使用HTTP协议传输JSON格式的消息体; - 提供同步调用方式以满足低延迟需求; - 支持异步回调机制以便于长时间任务执行期间的状态更新通知; #### 关键接口列表 ##### 获取最新帧的结果 此接口允许外部应用程序请求最新的感知结果快照。返回的内容通常会包含所有被探测到的对象及其属性描述。 ```http GET /perception/latest_frame HTTP/1.1 Host: localhost:8080 Accept: application/json ``` 响应示例: ```json { "timestamp": 1672531199, "objects": [ { "type": "car", "position": {"x": 10.0, "y": 5.0}, "velocity": {"vx": 2.0, "vy": 0} }, ... ] } ``` ##### 订阅连续流式的感知事件 当需要长期监听感知系统的输出时可以选择订阅模式。一旦有新的发现就会立即推送至客户端。 ```http POST /perception/events/subscribe HTTP/1.1 Host: localhost:8080 Content-Type: application/json ``` 发送主体应指定感兴趣的特定类型或全部种类的目标。 ```json {"types":["pedestrian", "vehicle"]} ``` 服务器将以WebSocket连接的形式维持通信链路,并按照设定条件触发消息传递给接收方[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值