2025-12-29 01:16:58 +08:00
|
|
|
|
#ifndef TUNNELCHANNELPRESENTER_H
|
|
|
|
|
|
#define TUNNELCHANNELPRESENTER_H
|
|
|
|
|
|
|
|
|
|
|
|
#include <condition_variable>
|
|
|
|
|
|
#include <thread>
|
|
|
|
|
|
#include <map>
|
|
|
|
|
|
#include <mutex>
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
#include <chrono>
|
|
|
|
|
|
|
|
|
|
|
|
#include "BasePresenter.h"
|
|
|
|
|
|
#include "IVrEyeDevice.h"
|
|
|
|
|
|
#include "IHikDevice.h"
|
|
|
|
|
|
#include "ConfigManager.h"
|
|
|
|
|
|
#include "IYTunnelChannelStatus.h"
|
|
|
|
|
|
#include "VrConvert.h"
|
|
|
|
|
|
#include "LaserDataLoader.h"
|
|
|
|
|
|
#include "CommonDialogCameraLevel.h"
|
2026-01-07 00:34:37 +08:00
|
|
|
|
#include "channelSpaceMeasure_Export.h"
|
2025-12-29 01:16:58 +08:00
|
|
|
|
#include <QImage>
|
|
|
|
|
|
#include <QPainter>
|
|
|
|
|
|
#include <QColor>
|
|
|
|
|
|
#include <QObject>
|
|
|
|
|
|
#include <QTimer>
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
|
|
// Forward declarations
|
|
|
|
|
|
class DetectPresenter;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 隧道通道检测业务逻辑类
|
|
|
|
|
|
*
|
|
|
|
|
|
* 集成两种相机:
|
|
|
|
|
|
* 1. 海康相机 (IHikDevice) - 实时2D图像采集
|
|
|
|
|
|
* 2. 3D相机 (VrEyeDevice/VzNLSDK) - 3D点云采集进行算法检测
|
|
|
|
|
|
*
|
|
|
|
|
|
* 流程与 WorkpieceApp 一致
|
|
|
|
|
|
*/
|
|
|
|
|
|
class TunnelChannelPresenter : public BasePresenter, public IVrConfigChangeNotify,
|
|
|
|
|
|
public ICameraLevelCalculator, public ICameraLevelResultSaver
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit TunnelChannelPresenter(QObject *parent = nullptr);
|
|
|
|
|
|
~TunnelChannelPresenter();
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化
|
|
|
|
|
|
int InitApp() override;
|
|
|
|
|
|
|
|
|
|
|
|
// 获取配置管理器
|
|
|
|
|
|
ConfigManager* GetConfigManager() { return m_pConfigManager; }
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置海康相机显示窗口(用于硬件渲染)
|
|
|
|
|
|
* @param hWnd 窗口句柄,设置后将使用硬件解码直接渲染
|
|
|
|
|
|
*/
|
|
|
|
|
|
void SetHikDisplayWindow(void* hWnd) { m_hHikDisplayWnd = hWnd; }
|
|
|
|
|
|
|
|
|
|
|
|
// 实现IVrConfigChangeNotify接口
|
|
|
|
|
|
virtual void OnConfigChanged(const ConfigResult& configResult) override;
|
|
|
|
|
|
|
|
|
|
|
|
// ============ 海康相机相关 ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 初始化海康设备
|
|
|
|
|
|
* @return 0: 成功, 其他: 错误码
|
|
|
|
|
|
*/
|
|
|
|
|
|
int InitHikDevice();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 连接海康相机
|
|
|
|
|
|
* @param config 海康相机配置
|
|
|
|
|
|
* @return 0: 成功, 其他: 错误码
|
|
|
|
|
|
*/
|
|
|
|
|
|
int ConnectHikCamera(const HikCameraConfig& config);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 断开海康相机
|
|
|
|
|
|
*/
|
|
|
|
|
|
void DisconnectHikCamera();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 开始海康相机实时预览
|
|
|
|
|
|
* @return 0: 成功, 其他: 错误码
|
|
|
|
|
|
*/
|
|
|
|
|
|
int StartHikPreview();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 开始海康相机实时预览(直接渲染到窗口,低延迟)
|
|
|
|
|
|
* @param hWnd 窗口句柄
|
|
|
|
|
|
* @return 0: 成功, 其他: 错误码
|
|
|
|
|
|
*/
|
|
|
|
|
|
int StartHikPreviewEx(void* hWnd);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 停止海康相机实时预览
|
|
|
|
|
|
*/
|
|
|
|
|
|
void StopHikPreview();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取海康相机当前帧图像
|
|
|
|
|
|
* @return 当前帧图像
|
|
|
|
|
|
*/
|
|
|
|
|
|
QImage GetCurrentHikFrame() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 判断海康相机是否已连接
|
|
|
|
|
|
* @return true: 已连接, false: 未连接
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool IsHikCameraConnected() const;
|
|
|
|
|
|
|
|
|
|
|
|
// ============ 实现 ICameraLevelCalculator 接口 ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 计算平面调平参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool CalculatePlaneCalibration(
|
|
|
|
|
|
const std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& scanData,
|
|
|
|
|
|
double planeCalib[9],
|
|
|
|
|
|
double& planeHeight,
|
|
|
|
|
|
double invRMatrix[9]) override;
|
|
|
|
|
|
|
|
|
|
|
|
// ============ 实现 ICameraLevelResultSaver 接口 ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 保存相机调平结果到配置文件
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool SaveLevelingResults(double planeCalib[9], double planeHeight, double invRMatrix[9],
|
|
|
|
|
|
int cameraIndex, const QString& cameraName) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 从配置文件加载相机调平结果
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool LoadLevelingResults(int cameraIndex, const QString& cameraName,
|
|
|
|
|
|
double planeCalib[9], double& planeHeight, double invRMatrix[9]) override;
|
|
|
|
|
|
|
2026-01-07 00:34:37 +08:00
|
|
|
|
// ============ 算法参数配置接口 ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取算法参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
void GetAlgoParams(SSG_cornerParam& cornerParam,
|
|
|
|
|
|
SSG_outlierFilterParam& filterParam,
|
|
|
|
|
|
SSG_treeGrowParam& treeParam,
|
|
|
|
|
|
SSX_channelParam& channelParam,
|
|
|
|
|
|
bool& horizonScan) const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置算法参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
void SetAlgoParams(const SSG_cornerParam& cornerParam,
|
|
|
|
|
|
const SSG_outlierFilterParam& filterParam,
|
|
|
|
|
|
const SSG_treeGrowParam& treeParam,
|
|
|
|
|
|
const SSX_channelParam& channelParam,
|
|
|
|
|
|
bool horizonScan);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 保存算法参数到配置文件
|
|
|
|
|
|
* @return 保存成功返回true,失败返回false
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool SaveAlgoParamsToConfig();
|
|
|
|
|
|
|
2025-12-29 01:16:58 +08:00
|
|
|
|
protected:
|
|
|
|
|
|
// ============ 实现 BasePresenter 纯虚函数 ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 初始化算法参数(实现纯虚函数)
|
|
|
|
|
|
*/
|
|
|
|
|
|
int InitAlgoParams() override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 执行算法检测(实现纯虚函数)
|
|
|
|
|
|
* @param detectionDataCache 检测数据缓存的引用
|
|
|
|
|
|
*/
|
|
|
|
|
|
int ProcessAlgoDetection(std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& detectionDataCache) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取检测数据类型(实现纯虚函数)
|
|
|
|
|
|
* 隧道通道项目使用Position点云数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
EVzResultDataType GetDetectionDataType() override {
|
|
|
|
|
|
return keResultDataType_Position;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 相机状态变化通知(实现纯虚函数)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void OnCameraStatusChanged(int cameraIndex, bool isConnected) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 工作状态变化通知(重写虚函数)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void OnWorkStatusChanged(WorkStatus status) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 相机数量变化通知(重写虚函数)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void OnCameraCountChanged(int count) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 状态文字更新通知(重写虚函数)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void OnStatusUpdate(const std::string& statusMessage) override;
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
// ============ 海康相机相关私有方法 ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 海康相机帧数据回调处理
|
|
|
|
|
|
*/
|
|
|
|
|
|
void OnHikFrameReceived(unsigned char* pRGBData, int dataSize,
|
|
|
|
|
|
const HikFrameInfo& frameInfo);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 海康相机状态变化回调处理
|
|
|
|
|
|
*/
|
|
|
|
|
|
void OnHikDeviceStatusChanged(EHikDeviceStatus status);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 海康相机异常回调处理
|
|
|
|
|
|
*/
|
|
|
|
|
|
void OnHikExceptionReceived(EHikExceptionType exceptionType);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 海康相机重连定时器处理
|
|
|
|
|
|
*/
|
|
|
|
|
|
void OnHikReconnectTimer();
|
|
|
|
|
|
|
|
|
|
|
|
// ============ 连接状态管理 ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 检查并更新工作状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
void CheckAndUpdateWorkStatus();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 通知海康相机状态变化
|
|
|
|
|
|
*/
|
|
|
|
|
|
void NotifyHikCameraStatus(bool isConnected);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 通知机械臂连接状态变化
|
|
|
|
|
|
*/
|
|
|
|
|
|
void NotifyRobotConnectionStatus(bool isConnected);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 通知串口连接状态变化
|
|
|
|
|
|
*/
|
|
|
|
|
|
void NotifySerialConnectionStatus(bool isConnected);
|
|
|
|
|
|
|
|
|
|
|
|
signals:
|
|
|
|
|
|
// ============ 跨线程信号(用于SDK回调到主线程) ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 海康相机图像更新信号(跨线程)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void sigHikImageUpdated(const QImage& image);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 海康相机状态变化信号(跨线程)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void sigHikStatusChanged(int status);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 海康相机异常信号(跨线程)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void sigHikException(int exceptionType);
|
|
|
|
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
|
|
// ============ 跨线程槽函数 ============
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 处理海康图像更新(主线程)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void onHikImageUpdatedInMainThread(const QImage& image);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 处理海康状态变化(主线程)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void onHikStatusChangedInMainThread(int status);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 处理海康异常(主线程)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void onHikExceptionInMainThread(int exceptionType);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
// 配置管理器
|
|
|
|
|
|
ConfigManager* m_pConfigManager = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
// ============ 海康相机设备(使用封装接口) ============
|
|
|
|
|
|
|
|
|
|
|
|
IHikDevice* m_pHikDevice = nullptr; // 海康相机设备接口
|
|
|
|
|
|
bool m_bHikConnected = false; // 海康相机连接状态
|
|
|
|
|
|
QTimer* m_pHikReconnectTimer = nullptr; // 海康相机重连定时器
|
|
|
|
|
|
|
|
|
|
|
|
// 海康相机当前帧
|
|
|
|
|
|
mutable std::mutex m_hikFrameMutex;
|
|
|
|
|
|
QImage m_currentHikFrame;
|
|
|
|
|
|
|
|
|
|
|
|
// 帧率限制(避免过度刷新UI)
|
|
|
|
|
|
std::chrono::steady_clock::time_point m_lastHikFrameTime;
|
|
|
|
|
|
static constexpr int HIK_FRAME_INTERVAL_MS = 33; // 约30fps
|
|
|
|
|
|
|
|
|
|
|
|
// 海康相机显示窗口句柄(用于硬件渲染)
|
|
|
|
|
|
void* m_hHikDisplayWnd = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
// 检测处理器
|
|
|
|
|
|
DetectPresenter* m_pDetectPresenter = nullptr;
|
2026-01-07 00:34:37 +08:00
|
|
|
|
|
|
|
|
|
|
// ============ 通道间距测量算法参数 ============
|
|
|
|
|
|
SSG_cornerParam m_cornerParam; // 角点检测参数
|
|
|
|
|
|
SSG_outlierFilterParam m_outlierFilterParam; // 离群点过滤参数
|
|
|
|
|
|
SSG_treeGrowParam m_treeGrowParam; // 树生长参数
|
|
|
|
|
|
SSX_channelParam m_channelParam; // 通道参数
|
|
|
|
|
|
bool m_bHorizonScan = true; // 扫描方向:true-水平扫描,false-垂直扫描
|
2025-12-29 01:16:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif // TUNNELCHANNELPRESENTER_H
|