292 lines
14 KiB
C++
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;
|
|
}; |