Files
eUi/include/yhGlobal.h
RCiRoot 9210b37b44 V20251116-2.2.0
优化文件结构,删除较老代码文件。
优化参数修改界面,更改的参数都会实时更新到程序以及json中。
优化SQL相关功能。
更改了存图格式。
2025-11-16 19:29:29 +08:00

292 lines
14 KiB
C++

#pragma once
#include <missionBase.hpp>
#include <detCallbackChain.hpp>
#include <share.h>
#include <QObject>
#include <opencvPaintAlgo.hpp>
#pragma region 基础函数
#define CATCH_EXCEPTIONS \
catch (HDevEngineCpp::HDevEngineException& ex) { \
std::cout << "HDevEngineException: " << ex.Message() << std::endl; \
qDebug() << "HDevEngineException: " << ex.Message(); \
} \
catch (HalconCpp::HException& ex) { \
std::cout << "Halcon Exception Caught!" << std::endl; \
std::cout << "Error Code: " << ex.ErrorCode() << std::endl; \
std::cout << "Error Message: " << ex.ErrorMessage() << std::endl; \
qDebug() << "Halcon Exception Caught!"; \
qDebug() << "Error Code: " << ex.ErrorCode(); \
qDebug() << "Error Message: " << ex.ErrorMessage(); \
} \
catch (const std::exception& e) { \
std::cout << "Caught exception: " << e.what() << std::endl; \
qDebug() << "Caught exception: " << e.what(); \
}
struct yh_581_address {
int triggerAddr = -1;
int snAddr = -1;
QByteArray completeAddr = "-1";
QByteArray resultAddr = "-1";
int valueOffsetAddr = -1;
};
static yh_581_address generateYh581Address(int startAddr, int offset) {//INPUT:开始地址/电芯地址偏移(0~3)
return yh_581_address{
startAddr + offset * 2,
startAddr + 10 + offset * 22 ,
QByteArray::number(startAddr + 98 + offset * 2),
QByteArray::number(startAddr + 106 + offset * 2),
startAddr + 114 + offset * 20
};
}
static std::map<int, yh_581_address> generateYh581AddressMap(int startAddr, int cnt) {//INPUT:开始地址/0~3) 数量
std::map<int, yh_581_address> result;
for (auto i = 0; i < cnt; i++) {
result[i] = generateYh581Address(startAddr, i);
}
return result;
}
class detParams {
public:
};
#pragma endregion
//算法回调函数需要包含完整的算法流程以及发送信号,发送ui图表,捕获异常,处理异常等操作
//并且注意 异常可能会导致运行不到发送信号的函数,请在处理异常时发送异常结果
void generalExceptionResume(std::shared_ptr<detData> data, yh_581_address address, QString why = "") {
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode) << why;
cv::Mat Paint;
data->oriImgs[0].copyTo(Paint);
if (Paint.channels() == 1)
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
textPainter.putText(Paint, why.toStdString(), cv::Point(500, 50), cv::Scalar(0, 255, 0));
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
data->resultImgs.push_back(Paint);
if (data->service->_paramSyncManager->get("通用设置", "强制OK", false).toBool())
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
else
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//结果反馈
}
static bool generalAlgoTest(std::shared_ptr <detData> data, detParams* _detParams, yh_581_address address) {
try {
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
std::vector < std::string> defects = {"测试"};
///////////////////取图//处理//////////////////
if (data->oriImgs.size() < 1)
{
qCritical() << "图片数量不满足要求:" << data->oriImgs.size();
return false;
}
if (data->oriImgs[0].rows == 100) {
cv::Mat Paint;
data->oriImgs[0].copyTo(Paint);
cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2);
return false;
}
cv::Mat Paint;
QMutex paintMutex;
clock_t start, finish;
start = clock();
cv::Mat src1 = data->oriImgs[0];
if (src1.channels() != 3)
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
else
src1.copyTo(Paint);
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
textPainter.putText(Paint, "OK", cv::Point(10,10), cv::Scalar(0, 255, 0));
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.123");//发送数据1
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2)+ "_0.456");//发送数据2
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
data->service->_missionResultHandle->toBarChart(data->SNcode, !defects.size() > 0, defects);//发送图标操作
data->resultImgs.push_back(Paint);
return true;
}
CATCH_EXCEPTIONS
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送异常结果
return false;
}
template <typename paramTemplte>
//此类适用于单相机多触发地址需要联合判断的情况的情况 比如顶盖焊,包膜,入壳机台
//例触发地址有4个,输入信号为 1 0 0 1 则触发1和4的地址拍照检测,2和3拍照取图并废弃
class _581_Union_triggerTemplate {
public:
paramTemplte* _detParams;
detCallbackChain<paramTemplte, yh_581_address>* generalDet;
std::string cameraName;
QString viewerName;
std::map<int, yh_581_address>address;
int oneTriggerCaptrueTimes = 1;
/// <summary>
/// 初始化
/// </summary>
/// <param name="cameraNameIn">相机名</param>
/// <param name="viewerNameIN">窗口名</param>
/// <param name="startAddr">开始地址</param>
/// <param name="triggerCount">触发信号数</param>
/// <param name="oneTriggerCaptrueTimes">单次触发调用几次相机模块</param>
/// <param name="detParamsIn">参数输入</param>
/// <param name="_serviceManagerIn">默认</param>
/// <param name="bridgeIn">默认</param>
/// <param name="_processAlgoCallback">算法函数</param>
/// <param name="resultHandlerIn"></param>
void init(std::string cameraNameIn, QString viewerNameIN, int startAddr, int triggerCount,int oneTriggerCaptrueTimesIN,
paramTemplte* detParamsIn, ServiceManager* _serviceManagerIn, bSignalHub* bridgeIn,
typename detCallbackChain<paramTemplte, yh_581_address>::processAlgoCallback _processAlgoCallback,
QString saveObjectNameIN = "") {
viewerName = viewerNameIN;
cameraName = cameraNameIn;
_serviceManager = _serviceManagerIn;
_detParams = detParamsIn;
bridge = bridgeIn;
oneTriggerCaptrueTimes = oneTriggerCaptrueTimesIN;
saveObjectName = saveObjectNameIN;
generalDet = new detCallbackChain<paramTemplte, yh_581_address>(_serviceManager, _detParams, bridge);
generalDet->registerProcessAlgoCallback(_processAlgoCallback);
address = generateYh581AddressMap(startAddr, triggerCount);
//联合触发器条件
std::vector<std::pair<int, int>> conditions;
for (int i = 0; i < triggerCount; i++) {
conditions.push_back(std::make_pair(address[i].triggerAddr, 1));
//注册清除完成信号触发器 任意触发地址归零时触发一次
_serviceManager->_triggerManager->registerCallback(address[i].triggerAddr, 0, [this, i](int triggerPos, int triggerValue, QByteArray& byteArray)
{_serviceManager->_triggerManager->writeShort("D" + address[0].completeAddr + "_0"); }, "D" + address[0].completeAddr.toStdString() + "清零");
}
//注册联合触发器 任意触发地址置1时触发
_serviceManager->_triggerManager->registerUnionCallback(conditions, triggerManager::conditionMode::or ,[this](std::vector<std::pair<int, int>> vals, QByteArray& byteArray){
int cnt = 0;
for (auto& val : vals) {
if (val.second == 1)
evaluate(cnt, byteArray);
else
captrueAndDiscard();
cnt++;
}
}, "");
for (int i = 0; i < address.size(); i++) {
_serviceManager->_triggerManager->registerPlcValueViewer(viewerNameIN + "_" + QString::number(i),
{ {"触发",address[i].triggerAddr,finsShort },
{"反馈",address[i].completeAddr.toInt(),finsShort},
{"结果",address[i].resultAddr.toInt(),finsShort},
{"数值1",address[i].valueOffsetAddr,finsFloat},
{"数值2",address[i].valueOffsetAddr + 2,finsFloat},
{"数值3",address[i].valueOffsetAddr + 4,finsFloat} });
}
}
//获取图片并进行检测
void evaluate(int batteryOffset, QByteArray& byteArray) {
_serviceManager->_triggerManager->writeShort("D" + address[0].completeAddr + "_1");//完成信号 固定只发在第0位
std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, address[batteryOffset].snAddr, false, false, -1);
auto camera = _serviceManager->_cameraManager->getCamera(cameraName);
camera->clearCache();
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包
data->saveObjectName = saveObjectName;
camera->captureImage(data);//拍照
generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法
data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图"));
}
//获取图片然后废弃
void captrueAndDiscard() {
auto camera = _serviceManager->_cameraManager->getCamera(cameraName);
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData();//创建数据包
camera->captureImage(data);//拍照
_serviceManager->_detDataManager->deleteDetData(data->uuid);
}
private:
QString saveObjectName = "";
bSignalHub* bridge;
ServiceManager* _serviceManager = nullptr;
};
template <typename paramTemplte2>
//此类适用于单相机多触发地址单次判断的情况,比如密封钉,三协机台
//例触发地址有4个,输入信号为 1 0 0 1 则按顺序触发1和4的地址拍照检测,2和3不做处理
class _581_Single_triggerTemplate {
public:
paramTemplte2* _detParams;
detCallbackChain<paramTemplte2, yh_581_address>* generalDet;
std::string cameraName;
QString viewerName;
std::map<int, yh_581_address>address;
int oneTriggerCaptrueTimes = 1;
/// <summary>
/// 初始化
/// </summary>
/// <param name="cameraNameIn">相机名</param>
/// <param name="viewerNameIN">窗口名</param>
/// <param name="startAddr">开始地址</param>
/// <param name="triggerCount">触发信号数</param>
/// <param name="oneTriggerCaptrueTimes">单次触发调用几次相机模块</param>
/// <param name="detParamsIn">参数输入</param>
/// <param name="_serviceManagerIn">默认</param>
/// <param name="bridgeIn">默认</param>
/// <param name="_processAlgoCallback">算法函数</param>
/// <param name="resultHandlerIn"></param>
void init(std::string cameraNameIn, QString viewerNameIN, int startAddr, int triggerCount, int oneTriggerCaptrueTimesIN,
paramTemplte2* detParamsIn, ServiceManager* _serviceManagerIn, bSignalHub* bridgeIn,
typename detCallbackChain<paramTemplte2, yh_581_address>::processAlgoCallback _processAlgoCallback,
QString saveObjectNameIN = "") {
viewerName = viewerNameIN;
cameraName = cameraNameIn;
_serviceManager = _serviceManagerIn;
_detParams = detParamsIn;
bridge = bridgeIn;
oneTriggerCaptrueTimes = oneTriggerCaptrueTimesIN;
saveObjectName = saveObjectNameIN;
generalDet = new detCallbackChain<paramTemplte2, yh_581_address>(_serviceManager, _detParams, bridge);
generalDet->registerProcessAlgoCallback(_processAlgoCallback);
address = generateYh581AddressMap(startAddr, triggerCount);
//单次触发器条件
for (int i = 0; i < triggerCount; i++) {
//注册单触发器 触发地址置1时触发
_serviceManager->_triggerManager->registerCallback(address[i].triggerAddr, 1, [this, i](int triggerPos, int triggerValue, QByteArray& byteArray) {
evaluate(i, byteArray);}, "");
//注册清除完成信号触发器 任意触发地址归零时触发一次
_serviceManager->_triggerManager->registerCallback(address[i].triggerAddr, 0, [this, i](int triggerPos, int triggerValue, QByteArray& byteArray) {
_serviceManager->_triggerManager->writeShort("D" + address[i].completeAddr + "_0"); }, "D" + address[0].completeAddr.toStdString() + "清零");
}
for (int i = 0; i < address.size(); i++) {
_serviceManager->_triggerManager->registerPlcValueViewer(viewerNameIN + "_" + QString::number(i),
{ {"触发",address[i].triggerAddr,finsShort },
{"反馈",address[i].completeAddr.toInt(),finsShort},
{"结果",address[i].resultAddr.toInt(),finsShort},
{"数值1",address[i].valueOffsetAddr,finsFloat},
{"数值2",address[i].valueOffsetAddr + 2,finsFloat},
{"数值3",address[i].valueOffsetAddr + 4,finsFloat} });
}
}
//获取图片并进行检测
void evaluate(int batteryOffset, QByteArray& byteArray) {
_serviceManager->_triggerManager->writeShort("D" + address[batteryOffset].completeAddr + "_1");//完成信号 根据偏移发送
std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, address[batteryOffset].snAddr, false, false, -1);
auto camera = _serviceManager->_cameraManager->getCamera(cameraName);
camera->clearCache();
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
QString::fromStdString(cameraName), sn, oneTriggerCaptrueTimes, camera->config.oriSaveFormat);//创建数据包
data->saveObjectName = saveObjectName;
camera->captureImage(data);//拍照
generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法
data->resultImgShowSet.push_back(showImgPack(viewerName, "结果图"));
}
private:
QString saveObjectName = "";
bSignalHub* bridge;
ServiceManager* _serviceManager = nullptr;
};