2026-02-01 14:51:16 +08:00

239 lines
8.8 KiB
C++
Raw 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.

#ifndef WORKPIECEHOLEPRESENTER_H
#define WORKPIECEHOLEPRESENTER_H
#include <condition_variable>
#include <thread>
#include <map>
#include <mutex>
#include <memory>
#include "BasePresenter.h"
#include "IVrEyeDevice.h"
#include "ConfigManager.h"
#include "TCPServerProtocol.h"
#include "IYWorkpieceHoleStatus.h"
#include "SG_baseDataType.h"
#include "workpieceHolePositioning_Export.h" // 算法输出类型定义
#include "VrConvert.h"
#include "LaserDataLoader.h"
#include "CommonDialogCameraLevel.h" // 引入通用对话框的接口
#include "CoordinateTransform.h" // 坐标转换库
#include "PLCModbusClient.h" // PLC Modbus 客户端
#include <QImage>
#include <QPainter>
#include <QColor>
#include <QObject>
#include <QTimer>
#include <memory>
// Forward declarations
class DetectPresenter;
class WorkpieceHolePresenter;
// 配置变化监听器代理类
class ConfigChangeListenerProxy : public IConfigChangeListener
{
public:
explicit ConfigChangeListenerProxy(WorkpieceHolePresenter* presenter) : m_presenter(presenter) {}
void OnSystemConfigChanged(const SystemConfig& config) override;
void OnCameraParamChanged(int cameraIndex, const CameraUIParam& cameraParam) override {}
void OnAlgorithmParamChanged(const VrAlgorithmParams& algorithmParams) override {}
private:
WorkpieceHolePresenter* m_presenter;
};
class WorkpieceHolePresenter : public BasePresenter, public IVrConfigChangeNotify,
public ICameraLevelCalculator, public ICameraLevelResultSaver
{
Q_OBJECT
// 声明友元类,允许访问 protected 成员
friend class ConfigChangeListenerProxy;
public:
explicit WorkpieceHolePresenter(QObject *parent = nullptr);
~WorkpieceHolePresenter();
// 初始化
int InitApp() override;
// 获取配置管理器
ConfigManager* GetConfigManager() { return m_pConfigManager; }
// 手眼标定矩阵管理
CalibMatrix GetClibMatrix(int index) const;
// ============ 坐标转换接口 ============
/**
* @brief 将算法检测结果(相机坐标系)转换为机器人坐标系
*
* @param workpieceInfo 算法输出的工件信息(相机坐标系)
* @param robotPose 机器人当前位姿
* @param handEye 六轴手眼标定矩阵
* @param targetPose 输出的目标抓取位姿(机器人坐标系)
*
* 使用说明:
* - Eye-in-Hand 模式:相机固定在机器人末端
* - 算法输出的 x_dir, y_dir, z_dir 为方向向量
* - 输出的 targetPose 为机器人基坐标系下的位姿
*/
void ConvertWorkpieceToRobotPose(const WD_workpieceInfo& workpieceInfo,
const CTRobotPose& robotPose,
const CTSixAxisCalibResult& handEye,
CTRobotPose& targetPose);
/**
* @brief 将算法检测结果转换为机器人坐标系Eye-to-Hand模式
*
* @param workpieceInfo 算法输出的工件信息(相机坐标系)
* @param cameraToBase 相机到机器人基座的标定矩阵
* @param targetPose 输出的目标抓取位姿(机器人坐标系)
*
* 使用说明:
* - Eye-to-Hand 模式:相机固定在外部
*/
void ConvertWorkpieceToRobotPoseEyeToHand(const WD_workpieceInfo& workpieceInfo,
const CTSixAxisCalibResult& cameraToBase,
CTRobotPose& targetPose);
// 实现IVrConfigChangeNotify接口
virtual void OnConfigChanged(const ConfigResult& configResult) override;
// ============ 实现 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;
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 工作状态变化通知(重写虚函数)
*
* 当BasePresenter的工作状态改变时此方法会被调用
* 在此调用UI回调接口通知状态变化
*/
void OnWorkStatusChanged(WorkStatus status) override;
/**
* @brief 相机数量变化通知(重写虚函数)
*
* 当相机初始化时,此方法会被调用
* 在此调用UI回调接口通知相机数量
*/
void OnCameraCountChanged(int count) override;
/**
* @brief 状态文字更新通知(重写虚函数)
*
* 当需要更新状态文字时,此方法会被调用
* 在此调用UI回调接口通知状态消息
*/
void OnStatusUpdate(const std::string& statusMessage) override;
private:
// TCP服务器相关方法
int InitTcpServer(int nPort);
int InitTCPServer(); // 初始化TCP服务器协议使用配置端口
bool startServer(quint16 port = 0); // port = 0 表示使用配置文件中的端口
void stopServer();
// TCP服务器回调处理方法
void onTcpDataReceivedFromCallback(const TCPClient* pClient, const char* pData, const unsigned int nLen);
void onTcpClientEventFromCallback(const TCPClient* pClient, TCPServerEventType eventType);
// TCP连接状态改变回调
void OnTCPConnectionChanged(bool connected);
// TCP检测触发回调
bool OnTCPDetectionTrigger(bool startWork, int cameraIndex, qint64 timestamp);
// 发送检测结果给TCP客户端
void _SendDetectionResultToTCP(const WorkpieceHoleDetectionResult& detectionResult, int cameraIndex);
// 连接状态检查和更新
void CheckAndUpdateWorkStatus();
// 根据相机索引获取调平参数
SSG_planeCalibPara _GetCameraCalibParam(int cameraIndex);
// PLC Modbus 相关方法
int InitPLCModbus(); // 初始化 PLC Modbus 客户端
void OnPLCPhotoRequested(int cameraIndex); // PLC 拍照请求回调
void SendCoordinateDataToPLC(const WorkpieceHoleDetectionResult& result); // 发送坐标数据到 PLC
private:
// WorkpieceHolePresenter 特有的成员变量
ConfigManager* m_pConfigManager = nullptr;
// TCP服务器相关
IYTCPServer* m_pTcpServer = nullptr;
TCPServerProtocol* m_pTCPServer = nullptr; // TCP服务器协议实例
quint16 m_port = 0;
bool m_bTcpClientConnected = false; // TCP客户端连接状态
bool m_bTCPConnected = false; // TCP客户端连接状态新协议
// 检测处理器
DetectPresenter* m_pDetectPresenter = nullptr;
// 手眼标定矩阵列表从独立文件加载暂时保留在Presenter中
std::vector<CalibMatrix> m_clibMatrixList;
// 配置变化监听器代理
std::shared_ptr<ConfigChangeListenerProxy> m_pConfigListener;
// PLC Modbus 客户端
PLCModbusClient* m_pPLCModbusClient = nullptr; // PLC Modbus 客户端实例
bool m_bPLCConnected = false; // PLC 连接状态
bool m_bRobotConnected = false; // 机械臂连接状态
};
#endif // WORKPIECEHOLEPRESENTER_H