Files
pallet_storage_detection_sy…/docs/project_architecture.md
2026-01-06 10:21:22 +08:00

514 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目架构及调用关系文档
## 1. 系统概述
本系统是一个基于立体视觉的仓库巡检图像采集与处理系统。它集成了图漾(Percipio)工业深度相机SDK和海康(MVS)工业2D相机SDK进行多相机图像采集使用OpenCV进行图像处理Qt6作为用户界面框架并通过Redis与外部系统如WMS仓库管理系统、机器人控制系统进行通信和任务调度。
系统主要功能包括:
- **多相机统一管理**同时支持深度相机Percipio和2D相机MVS的数据采集
- **实时图像预览与状态监控**GUI界面实时显示相机图像支持深度图伪彩色显示
- **基于Redis的任务触发与结果上报**:支持跨数据库的任务监听和结果写入
- **多种检测算法**
- 货位占用检测Flag 1基于2D图像的目标检测
- 托盘位置偏移检测Flag 2基于深度数据的3D位置计算
- 横梁/立柱变形检测Flag 3基于深度数据的结构变形测量
- 视觉盘点检测Flag 4基于Halcon的QR码识别支持连续扫描和去重
- 盘点停止信号Flag 5停止Flag 4的连续扫描循环
- **智能相机分配**:根据任务类型自动选择合适的相机设备
- **系统配置管理与日志记录**:支持参数持久化、实时日志显示和错误处理
## 2. 目录结构说明
```text
scripts/ # 批处理脚本 (Redis数据库配置、模拟WMS任务等)
docs/ # 项目文档
├── project_architecture.md # 项目架构文档 (本文档)
├── project_class_interaction.md # 类交互关系文档
└── cmake_configuration_summary.md # CMake构建配置文档
image_capture/
├── CMakeLists.txt # 主构建配置文件
├── cmake/ # CMake模块配置
│ ├── CompilerOptions.cmake # 编译器选项配置
│ ├── Dependencies.cmake # 依赖项管理 (Qt6, OpenCV, Open3D)
│ └── PercipioSDK.cmake # Percipio相机SDK配置
├── config.json # 系统配置文件 (相机参数、算法阈值、Redis配置等)
└── src/
├── algorithm/ # 核心算法库
│ ├── core/ # 算法基类与结果定义
│ │ ├── detection_base.h/cpp # 检测算法基类
│ │ └── detection_result.h/cpp # 检测结果数据结构
│ ├── detections/ # 具体检测算法实现
│ │ ├── slot_occupancy/ # 货位占用检测
│ │ ├── pallet_offset/ # 托盘偏移检测
│ │ ├── beam_rack_deflection/ # 横梁立柱变形检测
│ │ └── visual_inventory/ # 视觉盘点检测
│ └── utils/ # 图像处理工具
├── camera/ # 相机驱动层
│ ├── ty_multi_camera_capture.h/cpp # 图漾(Percipio)深度相机封装
│ └── mvs_multi_camera_capture.h/cpp # 海康(MVS)2D相机封装
├── common/ # 通用设施
│ ├── config_manager.h/cpp # 配置管理单例 (JSON配置加载/保存)
│ ├── log_manager.h/cpp # 日志管理 (spdlog封装)
│ └── log_streambuf.h # std::cout重定向到GUI
├── device/ # 硬件设备管理
│ └── device_manager.h/cpp # 相机设备单例管理 (统一设备接口)
├── gui/ # 用户界面 (Qt6)
│ └── mainwindow.h/cpp/ui # 主窗口实现 (实时预览+设置界面)
├── redis/ # 通信模块
│ └── redis_communicator.h/cpp # Redis客户端封装 (跨数据库支持)
├── task/ # 任务调度
│ └── task_manager.h/cpp # 任务管理器 (队列+线程+算法调度)
├── vision/ # 系统控制
│ └── vision_controller.h/cpp # 顶层控制器 (Redis+Task协调)
├── common_types.h # 通用数据类型 (Point3D, CameraIntrinsics等)
├── tools/ # 工具程序目录
│ ├── calibration_tool/ # 相机标定工具
│ ├── slot_algo_tuner/ # 货位算法调参工具
│ └── intrinsic_dumper/ # 相机内参导出工具
└── main.cpp # 程序入口
```
## 3. 核心架构设计
系统采用分层架构设计,各模块职责明确:
- **展示层 (Presentation)**: `MainWindow` 负责Qt6界面显示、实时相机预览、手动控制、参数配置及日志展示。
- **控制层 (Control)**: `VisionController` 作为系统级控制器,负责服务的启动/停止协调Redis通信和任务管理使用回调机制解耦模块间依赖。
- **业务逻辑层 (Business Logic)**: `TaskManager` 负责任务队列管理、算法调度和结果处理;`DeviceManager` 作为硬件资源的统一访问点(单例模式)。
- **算法层 (Algorithm)**: 提供具体的视觉检测功能,所有算法继承自 `DetectionBase`,支持统一的 `execute()` 接口。
- **基础设施层 (Infrastructure)**: `CameraCapture` 封装底层相机SDK调用`RedisCommunicator` 处理跨数据库通信,`ConfigManager` 管理系统配置。
### 系统分层架构图
```mermaid
graph TB
subgraph Presentation ["展示层 (Presentation)"]
direction TB
GUI[MainWindow]
end
subgraph Control ["控制层 (Control)"]
VC[VisionController]
end
subgraph Business ["业务逻辑层 (Business Logic)"]
direction TB
TM[TaskManager]
DM[DeviceManager]
end
subgraph Algorithm ["算法层 (Algorithm)"]
direction TB
DB[DetectionBase]
Det[Concrete Detections<br/>(Slot, Beam, etc.)]
end
subgraph Infrastructure ["基础设施层 (Infrastructure)"]
direction TB
Cam[CameraCapture]
Redis[RedisCommunicator]
Conf[ConfigManager]
end
%% 层级调用关系
GUI --> VC
VC --> TM
VC --> Redis
TM --> DM
TM --> DB
DB <|-- Det
DM --> Cam
DM --> MVS[MvsMultiCameraCapture]
%% 跨层辅助调用
GUI -.-> Conf
TM -.-> Conf
style Presentation fill:#e1f5fe,stroke:#01579b
style Control fill:#e8f5e9,stroke:#2e7d32
style Business fill:#fff3e0,stroke:#ef6c00
style Algorithm fill:#f3e5f5,stroke:#7b1fa2
style Infrastructure fill:#eceff1,stroke:#455a64
```
### 系统类图
```mermaid
classDiagram
class MainWindow {
+VisionController visionController_
+QTimer imageTimer_
+updateImage()
+onSaveSettings()
+showLogMessage()
}
class VisionController {
+shared_ptr<RedisCommunicator> redis_comm_
+shared_ptr<RedisCommunicator> redis_result_comm_
+shared_ptr<TaskManager> task_manager_
+initialize()
+start()
+stop()
-onTaskReceived()
}
class DeviceManager {
<<Singleton>>
+shared_ptr<CameraCapture> capture_
+unique_ptr<MvsMultiCameraCapture> mvs_cameras_
+initialize()
+startAll()
+getLatestImages()
+computePointCloud()
+get2DCameraImage()
}
class TaskManager {
+queue<RedisTaskData> task_queue_
+map<int, DetectionBase*> detectors_
+thread execution_thread_
+handleTask()
+executeDetectionTask()
-executeVisualInventoryLoop()
-processResult()
-addWarningAlarmSignals()
}
class CameraCapture {
+vector<CameraInfo> cameras_
+getLatestImages()
+computePointCloud()
+start()
-captureThreadFunc()
}
class MvsMultiCameraCapture {
+vector<CameraInfo> cameras_
+getLatestImage()
+start()
}
class RedisCommunicator {
+connect()
+startListening()
+writeString()
+setTaskCallback()
}
class ConfigManager {
<<Singleton>>
+json config_data_
+loadConfig()
+saveConfig()
+getValue()
}
class DetectionBase {
<<Abstract>>
+execute(depth, color, side, result, point_cloud, beam_length)
}
class SlotOccupancyDetection {
+execute()
}
class PalletOffsetDetection {
+execute()
}
class BeamRackDeflectionDetection {
+execute()
}
class VisualInventoryDetection {
+execute()
}
MainWindow --> VisionController : 拥有并管理
VisionController --> RedisCommunicator : 管理 (任务监听)
VisionController --> TaskManager : 分发任务
RedisCommunicator --> VisionController : 回调通知 (onTaskReceived)
VisionController ..> DeviceManager : 依赖(全局单例)
TaskManager ..> DeviceManager : 获取图像数据 (Dependency)
DeviceManager --> CameraCapture : 拥有 (深度相机)
DeviceManager --> MvsMultiCameraCapture : 拥有 (2D相机)
TaskManager --> DetectionBase : 调用算法
DetectionBase <|-- SlotOccupancyDetection : 继承
DetectionBase <|-- PalletOffsetDetection : 继承
DetectionBase <|-- BeamRackDeflectionDetection : 继承
DetectionBase <|-- VisualInventoryDetection : 继承
MainWindow ..> ConfigManager : 读写配置 (Dependency)
TaskManager ..> ConfigManager : 读取参数 (Dependency)
MainWindow ..> DeviceManager : 图像显示 (Dependency)
```
## 4. 关键模块详解
### 4.1 GUI与主入口 (MainWindow)
- **职责**: Qt6应用程序主窗口负责UI渲染、用户交互、参数配置、实时预览及日志展示。
- **调用关系**:
- 程序启动时创建 `VisionController` 并初始化系统。
- 通过 `QTimer` (30FPS) 定期从 `DeviceManager` 获取最新图像更新界面显示。
- **实时预览**: 支持深度图伪彩色显示和彩色图显示,带自适应缩放。
- **设置界面**: Settings Tab提供完整的算法参数配置包括
- Beam/Rack Deflection: 横梁/立柱变形检测阈值和ROI配置
- Pallet Offset: 托盘位置偏移检测参数
- 系统配置: Redis连接参数、相机设置等
- **日志显示**: 通过 `LogStreamBuf``std::cout/cerr` 重定向到GUI日志窗口。
- 通过 `ConfigManager` 加载和保存 `config.json` 配置,支持热重载。
### 4.2 视觉控制器 (VisionController)
- **职责**: 系统的核心控制器协调Redis通信和任务管理支持无头模式运行。
- **架构特点**:
- 使用智能指针管理 `RedisCommunicator``TaskManager` 生命周期。
- 支持跨数据库Redis操作任务监听DB(输入)和结果写入DB(输出)。
- 通过回调机制实现模块解耦,避免循环依赖。
- **工作流程**:
1. `initialize()`: 创建并初始化两个Redis连接器任务DB和结果DB
2. 初始化 `TaskManager`传入Redis连接器用于结果写入和任务状态清空。
3. `start()`: 启动Redis任务监听线程设置任务接收回调。
4. `onTaskReceived()`: 收到Redis任务时通过回调转发给 `TaskManager::handleTask()`
### 4.3 任务管理 (TaskManager)
- **职责**: 任务队列管理、算法调度、结果处理和跨线程执行的核心业务逻辑处理器。
- **架构特点**:
- **异步处理**: 使用任务队列 + 独立执行线程避免阻塞Redis监听和GUI。
- **相机智能分配**: 根据任务Flag自动选择合适的相机设备和数据类型。
- **去重机制**: Flag 4视觉盘点支持连续扫描和QR码去重。
- **状态管理**: 提供任务执行状态查询接口,支持外部监控。
- **工作流**:
1. `handleTask()`: 接收Redis任务加入线程安全的任务队列。
2. `taskExecutionThreadFunc()`: 后台线程持续处理队列任务。
3. **相机选择**: 根据Flag选择相机
- Flag 1: MVS 2D相机 (SN: DA8743029左/DA8742900右)
- Flag 2/3: Percipio深度相机 (SN: 207000146458左/207000146703右)
- Flag 4: MVS 2D相机 (SN: DA8789631) + 连续扫描循环
4. **数据获取**: 调用 `DeviceManager` 获取图像Flag 2/3时生成点云。
5. **算法执行**: 调用对应的 `DetectionBase::execute()` 方法。
6. **结果处理**: `processResult()` 格式化JSON、计算警告/报警、写入Redis结果DB。
### 4.4 设备管理 (DeviceManager)
- **职责**: 多类型相机的统一管理接口,全系统硬件资源的单例访问点。
- **架构特点**:
- **双SDK支持**: 同时管理Percipio深度相机和MVS 2D相机。
- **统一接口**: 提供一致的设备枚举、启动/停止和数据获取接口。
- **线程安全**: 所有接口都是线程安全的,支持并发访问。
- **资源管理**: 使用智能指针和RAII确保相机资源正确释放。
- **功能**:
- `initialize()`: 扫描并初始化所有类型的相机设备。
- `getLatestImages()`: 统一的图像获取接口,支持深度图+彩色图。
- `get2DCameraImage()`: 专门的2D相机图像获取接口。
- `computePointCloud()`: 基于深度图和相机内参计算3D点云。
- **相机索引映射**: 内部管理深度相机和2D相机的索引映射。
### 4.5 相机驱动层
- **Percipio深度相机** (`ty_multi_camera_capture.cpp`):
- 基于图漾工业相机SDK支持TY系列深度相机。
- 为每个相机维护独立采集线程和帧缓冲区。
- 支持深度图和彩色图同步采集,内部处理时间戳对齐。
- **点云计算**: 集成 `TYMapDepthImageToPoint3d`利用相机标定参数生成精确3D点云。
- 自动畸变校正和深度数据滤波。
- **MVS 2D相机** (`mvs_multi_camera_capture.cpp`):
- 基于海康工业相机SDK支持MV系列2D相机。
- 支持连续采集模式,内部缓冲区管理。
- 提供高帧率彩色图像采集,适用于快速检测场景。
- 支持相机序列号匹配,便于多相机场景下的设备识别。
### 4.6 配置管理 (ConfigManager)
- **职责**: 管理 `config.json` 文件,集中管理系统配置。
- **管理内容**:
- Redis 连接信息。
- 算法阈值 (Beam/Rack, Pallet Offset 等)。
- ROI (Region of Interest) 坐标点。
- 系统通用参数 (最小/最大深度等)。
- **特性**: 单例模式,支持热加载(部分参数)和持久化保存。程序启动时由 `MainWindow` 加载确保算法使用持久化的用户设置。GUI中的Settings Tab直接操作此模块。
## 5. 系统执行与数据流
### 5.1 初始化流程
1. **程序启动**: `main.cpp` 创建Qt6应用程序设置Fusion样式。
2. **MainWindow构造**:
- 初始化Qt6 UI界面主窗口 + Settings选项卡
- **配置加载**: 调用 `ConfigManager::loadConfig()``config.json` 加载系统配置。
- **设备初始化**: 调用 `DeviceManager::initialize()` 扫描Percipio和MVS相机。
- **控制器创建**: 实例化 `VisionController`传入Redis配置参数。
- **Redis初始化**: `VisionController::initialize()` 创建任务监听和结果写入的Redis连接器。
- **定时器启动**: 启动30FPS的 `QTimer` 用于实时图像预览。
3. **设备启动**: 调用 `DeviceManager::startAll()` 启动所有相机采集线程。
4. **服务启动**: 调用 `VisionController::start()` 开启Redis监听确保设备就绪后再接收任务。
### 5.2 自动任务执行流 (Redis触发)
```mermaid
sequenceDiagram
participant WMS as WMS/外部系统
participant Redis_Task as Redis_Task_DB
participant RC_Task as RedisCommunicator_Task
participant VC as VisionController
participant TM as TaskManager
participant DM as DeviceManager
participant Algo as DetectionAlgorithm
participant RC_Result as RedisCommunicator_Result
participant Redis_Result as Redis_Result_DB
WMS->>Redis_Task: SET vision_task_flag=1,side=left,time=xxx
Redis_Task->>RC_Task: Key change notification
RC_Task->>VC: onTaskReceived(task_data)
VC->>TM: handleTask(task_data)
activate TM
TM->>TM: Queue task (async)
TM->>DM: getLatestImages() or get2DCameraImage()
DM-->>TM: images (depth+color or 2D only)
alt Flag 2/3 (需要点云)
TM->>DM: computePointCloud(depth)
DM-->>TM: point_cloud (vector<Point3D>)
end
TM->>Algo: execute(images, point_cloud, ...)
activate Algo
Algo-->>TM: DetectionResult
deactivate Algo
TM->>TM: processResult() + addWarningAlarmSignals()
TM->>RC_Result: writeDetectionResult(json_map)
RC_Result->>Redis_Result: MSET key1=value1 key2=value2 ...
TM->>RC_Task: writeString(vision_task_flag, "0")
TM->>RC_Task: writeString(vision_task_side, "")
TM->>RC_Task: writeString(vision_task_time, "")
RC_Task->>Redis_Task: Clear task flags
deactivate TM
```
1. **外部触发**: WMS系统通过Redis Task DB发布任务设置 `vision_task_flag``side``time`)。
2. **异步接收**: `RedisCommunicator_Task` 监听Task DB触发回调给 `VisionController`
3. **任务队列**: `VisionController` 将任务加入 `TaskManager` 的线程安全队列。
4. **后台执行**: `TaskManager` 执行线程处理任务根据Flag选择相机和算法
- **Flag 1**: MVS 2D相机 → `SlotOccupancyDetection`
- **Flag 2**: Percipio深度相机 → `PalletOffsetDetection` (带点云)
- **Flag 3**: Percipio深度相机 → `BeamRackDeflectionDetection` (带点云)
- **Flag 4**: MVS 2D相机 → `VisualInventoryDetection` (连续循环+QR识别)
5. **智能数据获取**: 根据任务类型调用相应的 `DeviceManager` 接口。
6. **结果处理**: 计算警告/报警信号格式化JSON结果。
7. **跨DB写入**: 结果写入Redis Result DB任务状态清理写入Task DB。
### 5.3 实时监控执行流 (GUI)
```mermaid
sequenceDiagram
participant Timer as QTimer (30FPS)
participant MainWin as MainWindow
participant DM as DeviceManager
loop 每33ms
Timer->>MainWin: timeout()
activate MainWin
MainWin->>DM: getLatestImages(0) + get2DCameraImage(0)
DM-->>MainWin: depth_img, color_img, mvs_img
alt 深度相机活跃
MainWin->>MainWin: applyColorMap(depth_img) → 伪彩色显示
else 2D相机活跃
MainWin->>MainWin: 显示彩色图像
end
MainWin->>MainWin: MatToQImage() + scaleToFit()
MainWin->>MainWin: update QLabel displays
deactivate MainWin
end
```
1. **高频刷新**: `QTimer` 以30FPS触发 `updateImage()`,确保流畅的实时预览。
2. **多相机预览**: 同时获取深度相机和2D相机的最新图像支持混合显示。
3. **图像处理**: 深度图应用伪彩色映射,便于观察深度信息;彩色图直接显示。
4. **自适应渲染**: OpenCV Mat转换为QImage支持窗口大小自适应缩放。
5. **状态同步**: 图像显示与任务执行异步进行,不影响检测性能。
## 6. 异常处理与日志
- **日志**: 使用 `LogManager``spdlog` (如果集成) 或标准输出。
- **重定向**: `LogStreamBuf``std::cout/cerr` 重定向到GUI的日志窗口方便现场调试。
- **错误恢复**: 相机掉线重连机制(在驱动层实现或计划中)。
## 6. 检测算法详解
### 6.1 算法框架 (DetectionBase)
所有检测算法继承自 `DetectionBase` 抽象基类,提供统一的接口:
```cpp
virtual bool execute(const cv::Mat& depth_img,
const cv::Mat& color_img,
const std::string& side,
DetectionResult& result,
const std::vector<Point3D>* point_cloud = nullptr,
double beam_length = 0.0) = 0;
```
### 6.2 具体算法实现
#### Flag 1: 货位占用检测 (SlotOccupancyDetection)
- **输入**: 2D彩色图像 (MVS相机)
- **算法**: 基于图像处理的目标检测和位置判断
- **输出**: 货位占用状态 (occupied/free)
- **相机**: DA8743029 (左侧), DA8742900 (右侧)
#### Flag 2: 托盘位置偏移检测 (PalletOffsetDetection)
- **输入**: 深度图 + 彩色图 + 3D点云
- **算法**: 基于点云的3D位置计算检测托盘相对于基准位置的偏移
- **输出**: 左右偏移(mm)、前后偏移(mm)、插孔变形(mm)、旋转角度(°)
- **相机**: 207000146458 (左侧), 207000146703 (右侧)
- **警告/报警**: 基于阈值的四级判断 (正常/警告/报警)
#### Flag 3: 横梁/立柱变形检测 (BeamRackDeflectionDetection)
- **输入**: 深度图 + 彩色图 + 3D点云
- **算法**: 基于点云的结构变形测量
- **输出**: 横梁弯曲量(mm)、立柱弯曲量(mm)
- **相机**: 207000146458 (左侧), 207000146703 (右侧)
- **警告/报警**: 基于阈值的四级判断
#### Flag 4: 视觉盘点检测 (VisualInventoryDetection)
- **输入**: 2D彩色图像 (MVS相机)
- **算法**: 基于Halcon的QR码识别支持连续扫描和去重
- **特殊机制**: 循环执行直到收到Flag 5停止信号支持实时去重
- **输出**: JSON格式的条码列表 `{"side": ["BOX001", "BOX002", ...]}`
- **相机**: DA8789631 (专用盘点相机)
#### Flag 5: 盘点停止信号
- **功能**: 停止Flag 4的连续扫描循环
- **无算法执行**: 仅作为控制信号
### 6.3 相机分配策略
系统根据任务Flag智能选择相机
| Flag | 相机类型 | 序列号 | 位置 | 数据类型 |
|------|---------|--------|------|----------|
| 1 | MVS 2D | DA8743029 / DA8742900 | 左/右 | 彩色图 |
| 2 | Percipio深度 | 207000146458 / 207000146703 | 左/右 | 深度+彩色+点云 |
| 3 | Percipio深度 | 207000146458 / 207000146703 | 左/右 | 深度+彩色+点云 |
| 4 | MVS 2D | DA8789631 | 盘点专用 | 彩色图 |
## 7. 编译与构建
- **构建系统**: CMake 3.10+
- **编程语言**: C++17
- **目标平台**: Windows 10/11 (MSVC 2022 v143)
- **主要依赖**:
- **Qt6**: Widgets组件 (GUI框架)
- **OpenCV 4.x**: 图像处理和计算机视觉
- **Open3D 0.17+**: 3D点云处理
- **Percipio SDK**: 图漾工业相机驱动
- **MVS SDK**: 海康工业相机驱动
- **Redis C++ Client**: hiredis + redis-plus-plus (Redis通信)
- **可选依赖**: Halcon (用于QR码识别在Flag 4中使用)
- **构建流程**: 标准CMake流程支持Release/Debug配置
---
*文档更新时间: 2025-01-06*