2026-02-11 00:53:51 +08:00

249 lines
8.5 KiB
C++
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.

#ifndef BAGTHREADPOSITIONPRESENTER_H
#define BAGTHREADPOSITIONPRESENTER_H
#include <condition_variable>
#include <thread>
#include <map>
#include <mutex>
#include <memory>
#include "BasePresenter.h"
#include "IVrEyeDevice.h"
#include "ConfigManager.h"
#include "IVrConfig.h"
#include "IYBagThreadPositionStatus.h"
#include "SG_baseDataType.h"
#include "VrConvert.h"
#include "LaserDataLoader.h"
#include "CommonDialogCameraLevel.h" // 引入通用对话框的接口
#include "IYModbusTCPClient.h" // ModbusTCP客户端接口
#include <QImage>
#include <QPainter>
#include <QColor>
#include <QObject>
#include <QTimer>
#include <memory>
// Forward declarations
class DetectPresenter;
class BagThreadPositionPresenter : public BasePresenter, public IVrConfigChangeNotify,
public ICameraLevelCalculator, public ICameraLevelResultSaver
{
Q_OBJECT
public:
explicit BagThreadPositionPresenter(QObject *parent = nullptr);
~BagThreadPositionPresenter();
// 初始化
int InitApp() override;
// 反初始化
void DeinitApp();
// 触发检测
bool TriggerDetection(int cameraIndex = -1);
// 加载文件并检测
int LoadAndDetect(const QString& fileName);
// 重连相机
void ReconnectCamera();
// 获取/设置算法参数
struct AlgoParams {
VrThreadParam threadParam;
VrCornerParam cornerParam;
VrOutlierFilterParam filterParam;
VrTreeGrowParam growParam;
};
AlgoParams GetAlgoParams() const;
void SetAlgoParams(const AlgoParams& params);
// 获取配置管理器
ConfigManager* GetConfigManager() { return m_pConfigManager; }
// 应用基准距离到指定相机设备
void ApplyBaseDistance(int cameraIndex, double baseDistance);
// 应用ModbusTCP配置IP和大小端
void ApplyModbusConfig(const std::string& ip, bool bigEndian);
// 手眼标定矩阵管理
CalibMatrix GetClibMatrix(int index) const;
// 面标定辅助函数
SSG_planeCalibPara GetBaseCalibPara(const std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& scanData);
// 实现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 工作状态变化通知(重写虚函数)
*/
void OnWorkStatusChanged(WorkStatus status) override;
/**
* @brief 相机数量变化通知(重写虚函数)
*/
void OnCameraCountChanged(int count) override;
/**
* @brief 状态文字更新通知(重写虚函数)
*/
void OnStatusUpdate(const std::string& statusMessage) override;
/**
* @brief ModbusTCP连接状态变化通知重写虚函数
*/
void OnModbusServerStatusChanged(bool isConnected) override;
/**
* @brief 创建设备对象(重写虚函数)
* BagThreadPosition项目使用GlLineLaserDevice
*/
int CreateDevice(IVrEyeDevice** ppDevice) override;
/**
* @brief 跳过BasePresenter的ModbusTCP Server启动
* BagThreadPosition使用Client模式主动连接PLC
*/
bool ShouldStartModbusServer() const override { return false; }
private:
// 连接状态检查和更新
void CheckAndUpdateWorkStatus();
// 根据相机索引获取调平参数
SSG_planeCalibPara _GetCameraCalibParam(int cameraIndex);
// 发送检测结果到ModbusTCP寄存器
void _SendDetectionResultToModbus(const DetectionResult& detectionResult);
// Float转寄存器支持大小端切换
void _FloatToRegisters(float value, uint16_t* regs, bool bigEndian);
// ============ ModbusTCP Client 方法 ============
// 初始化ModbusTCP客户端
void InitModbusClient(const std::string& ip, uint16_t port, int pollingInterval);
// 关闭ModbusTCP客户端
void ShutdownModbusClient();
// 启动轮询线程
void StartModbusPolling();
// 停止轮询线程
void StopModbusPolling();
// 轮询线程函数
void ModbusPollingThreadFunc();
// 检查连接状态
bool CheckModbusConnection();
// 尝试连接
bool TryConnectModbus();
// 读取扫描请求寄存器
int ReadScanRequest();
// 写入远端PLC多个寄存器
bool WriteRemoteRegisters(uint16_t startAddress, const std::vector<uint16_t>& values);
// 写入远端PLC单个寄存器
bool WriteRemoteSingleRegister(uint16_t address, uint16_t value);
// 检查ModbusTCP客户端是否已连接
bool IsModbusClientConnected() const;
private:
// BagThreadPositionPresenter 特有的成员变量
ConfigManager* m_pConfigManager = nullptr;
// 检测处理器
DetectPresenter* m_pDetectPresenter = nullptr;
// 手眼标定矩阵列表从独立文件加载暂时保留在Presenter中
std::vector<CalibMatrix> m_clibMatrixList;
// ModbusTCP协议相关
DetectionResult m_lastDetectionResult; // 最新的检测结果
std::mutex m_modbusResultMutex; // 保护检测结果的互斥锁
bool m_modbusBigEndian = true; // ModbusTCP大小端配置
// ============ ModbusTCP Client 成员 ============
IYModbusTCPClient* m_modbusClient = nullptr; // Modbus客户端实例
std::string m_modbusClientIP; // 远端PLC IP
uint16_t m_modbusClientPort = 502; // 远端PLC端口
int m_modbusPollingInterval = 200; // 轮询间隔(毫秒)
std::thread m_modbusPollingThread; // 轮询线程
std::atomic<bool> m_modbusPollingRunning{false}; // 轮询线程运行标志
std::atomic<bool> m_modbusPollingPaused{false}; // 轮询暂停标志(检测期间暂停)
std::atomic<bool> m_modbusShutdownRequested{false}; // 关闭请求标志
mutable std::mutex m_modbusClientMutex; // 保护 m_modbusClient
bool m_lastScanRequestState = false; // 上次扫描请求状态(边沿检测)
bool m_lastModbusConnectedState = false; // 上次连接状态
int m_modbusReconnectAttempts = 0; // 重连次数
int m_modbusReadFailCount = 0; // 连续读取失败次数
static constexpr int MAX_READ_FAIL_COUNT = 3; // 最大连续失败次数,超过则断开重连
};
#endif // BAGTHREADPOSITIONPRESENTER_H