Files
2024-09-14 17:13:00 +08:00

577 lines
25 KiB
C++

#include <imgSaveThreadManager.h>
#include <appCore.hpp>
#include <appConfig.h>
#include <lightSource.hpp>
#include <cameraManager.h>
#include <manualDetThread.h>
#include <triggerManager.h>
#include <qthread.h>
#include <simpleSiemensTcp.hpp>
class detProcess : public QThread
{
public:
detProcess()
{
_threadManager.initialization(this);
_manualDetThread.initialization(this);
_cameraManager.initialization();
_triggerManager.initialization(this);
detProcessCallbackRegister();
}
//初始化
void run()
{
_cameraManager.start();
_handleAiModelManager.start();
_lightSourceManager.start();
_triggerManager.start();
QThread::msleep(1000);
bool res1 = waitrForInitResult(&_cameraManager);
bool res2 = waitrForInitResult(&_handleAiModelManager);
bool res3 = waitrForInitResult(&_triggerManager);
if (res3 == false)//连不上就重试一次
{
_triggerManager.start();
res3 = waitrForInitResult(&_triggerManager);
}
std::cout << "_cameraManager-initReuslt-->" << std::to_string(res1) << "\n"
<< "_handleAiModelManager-initReuslt-->" << std::to_string(res2) << "\n"
<< "_triggerManager-initReuslt-->" << std::to_string(res3) << "\n" << std::endl;
if (res1 == true && res2 == true && res3 == true)
emit _core._qtFunc.sendInitFinished(InitOK);
else
emit _core._qtFunc.sendInitFinished(InitFailure);
}
//等待服务返回OK/NG直到超时
bool waitrForInitResult(serviceModule* ptr, int timeout = -1)
{
if (timeout == -1)//不会超时
{
while (1)
{
if (ptr->status == InitFailure)
return false;
else if (ptr->status == InitOK)
return true;
QThread::msleep(100);
}
}
else
{
int timecnt = 0;
while (timecnt <= timeout)
{
if (ptr->status != NotInit)
break;
QThread::msleep(100);
timecnt++;
}
if (timecnt > 100)
return false;
if (ptr->status == InitFailure)
return false;
return true;
}
}
simpleSiemensTcp _simpleSiemensTcp;
detDataManager _detDataManager;//检测中的数据 不需要初始化
imgSaveThreadManager _imgSaveThreadManager;//存图线程 不需要初始化
detThreadManager _threadManager;//异步检测线程 不需要初始化
handleAiModelManager _handleAiModelManager;//模型
cameraManager _cameraManager;//相机
lightSourceManager _lightSourceManager;//光源
triggerManager _triggerManager;//MODBUS触发器
manualDetThread _manualDetThread;//手动触发线程
///////////////////////////////
bool startDet = false;
QMutex detMutex;
std::string currentSn;
void detProcessCallbackRegister()
{
_triggerManager.registerCallback(259, 1, [this](QByteArray& byteArray) {startDetection(byteArray); }, "检测启动");
_triggerManager.registerCallback(261, 1, [this](QByteArray& byteArray) {calibrationFunc(byteArray); }, "激光校准");
_triggerManager.registerCallback(300, 1, [this](QByteArray& byteArray) {captureImageAndDetection(byteArray); }, "拍照并检测");
_triggerManager.registerCallback(361, 1, [this](QByteArray& byteArray) {detectionSwitch1(byteArray); }, "检测开始");
_triggerManager.registerCallback(361, 2, [this](QByteArray& byteArray) {detectionSwitch2(byteArray); }, "检测结束1");
_triggerManager.registerCallback(362, 1, [this](QByteArray& byteArray) {detectionEnd(byteArray); }, "检测结束2");
_triggerManager.registerCallback(364, 1, [this](QByteArray& byteArray) {frontBackDet(); }, "检测正反面");
_triggerManager.registerCallback(369, 1, [this](QByteArray& byteArray) {testFunc(); }, "检测正反面");
_threadManager.registerCallback([this](std::shared_ptr<detData>data) {correctionResultHandle(data); });
_threadManager.registerCallback([this](std::shared_ptr<detData>data) {detectionResultHandle(data); });
}
//检测程序是否在运行
bool armIsRunning = false;
int backArmIndex = -1;
bool currentBack = false;
//激光校准数据缓存 //SN 数据
pointsOffsetStruct lastPointsOffsetStruct_;
correctionStruct laserDataCache;
//总流程开始,机器人发送1至寄存器259
//上位机确认OK之后,清零寄存器259,并发送1至寄存器260
//如产品型号为Product_1且为正面,则上位机发送1至寄存器256,发送0至寄存器257
//之后机器人确认之后需发送测量点位总数具体值至寄存器258
//检测启动 259
void startDetection(QByteArray& byteArray)
{
emit _core._qtFunc.uiModuleHistoryListWidget_reset();
_lightSourceManager.getLightSourcePtr("COM9")->setValue(lightSourceChannel::DChannel, 0);
_triggerManager.sendFinsMsg("write_short_259_0");//触发信号清零
_triggerManager.sendFinsMsg("write_short_260_1");//开始检测信号
emit _core._qtFunc.uiModuleLocationMap_ResetToDefault();
emit _core._qtFunc.uiModuleSummaryDataManager_Reset();
emit _core._qtFunc.uiModuleBackContinueDetDialog_hide();
emit _core._qtFunc.switchStartBtnStatusSignal(false);
backArmIndex = -1;
}
//机器人激光当前点位 264 1...9
//机器人到达激光点位1时,寄存器261至1,264至1,并将机器人在激光点位1坐标XYZ按照定义规则,保存进寄存器265~270
//上位机确认机器人到达点位1(264)时,确认OK后,寄存器262至1,261至0,取点完成后,发送寄存器263至1
//校准函数 261
void calibrationFunc(QByteArray& byteArray)
{
QThread::msleep(500);
int armPos = _triggerManager.getValue(264, byteArray);
int xValue1 = _triggerManager.getValue(265, byteArray);
int xValue2 = _triggerManager.getValue(266, byteArray);
int xValue3 = _triggerManager.getValue(267, byteArray);
int yValue1 = _triggerManager.getValue(268, byteArray);
int yValue2 = _triggerManager.getValue(269, byteArray);
int yValue3 = _triggerManager.getValue(270, byteArray);
int zValue1 = _triggerManager.getValue(271, byteArray);
int zValue2 = _triggerManager.getValue(272, byteArray);
int zValue3 = _triggerManager.getValue(273, byteArray);
double xValue = (xValue1 == 1 ? 1 : -1) * ((double)xValue2 + ((double)xValue3) / (std::pow(10, std::to_string(xValue3).length())));
double yValue = (yValue1 == 1 ? 1 : -1) * ((double)yValue2 + ((double)yValue3) / (std::pow(10, std::to_string(yValue3).length())));
double zValue = (zValue1 == 1 ? 1 : -1) * ((double)zValue2 + ((double)zValue3) / (std::pow(10, std::to_string(zValue3).length())));
auto cameraPtr = _cameraManager.getCamera("181964");
if (cameraPtr == nullptr)
return;
cameraPtr->trigger();
double rangeData = cameraPtr->getCameraValue();
//std::vector<double> values;
//for (int i = 0; i < 10; i++)//弃用
//{
// cameraPtr->trigger();
// double rangeData1 = cameraPtr->getCameraValue();
//}
//for (int i = 0; i < 70; i++)
//{
// cameraPtr->trigger();
// double rangeData1 = cameraPtr->getCameraValue();
// values.push_back(rangeData1);
//}
//double avgData = 0;
//for (auto data : values)
//{
// avgData += data;
//}
//avgData /= values.size();
//double maxData = *std::max_element(values.begin(), values.end());
//double minData = *std::min_element(values.begin(), values.end());
//double rangeData = avgData;
/*qDebug() << " max:" << maxData << " min:" << minData << " avg:" << avgData;
std::cout << " max:" << maxData << " min:" << minData << " avg:" << avgData << std::endl;*/
qDebug() << "jiaozhun xValue:" << xValue << " yValue:" << yValue << " zValue:" << zValue << " rangeData:" << rangeData;
std::cout << "jiaozhun xValue:" << xValue << " yValue:" << yValue << " zValue:" << zValue << " rangeData:" << rangeData << std::endl;
if (rangeData == 0)
{
std::cout << "激光取图错误" << std::endl;
return;
}
if (armPos == 1)//第一次
laserDataCache = correctionStruct();
if (armPos <= 3)
{
laserDataCache.in_X_X0Y.push_back(xValue);
laserDataCache.in_Y_X0Y.push_back(yValue);
laserDataCache.in_Z_X0Y.push_back(zValue);
laserDataCache.in_Z_X0Y_Value.push_back(rangeData);
}
else if (armPos <= 6)
{
laserDataCache.in_X_Y0Z.push_back(xValue);
laserDataCache.in_Y_Y0Z.push_back(yValue);
laserDataCache.in_Z_Y0Z.push_back(zValue);
laserDataCache.in_X_Y0Z_Value.push_back(rangeData);
}
else if (armPos <= 9)
{
laserDataCache.in_X_X0Z.push_back(xValue);
laserDataCache.in_Y_X0Z.push_back(yValue);
laserDataCache.in_Z_X0Z.push_back(zValue);
laserDataCache.in_Y_X0Z_Value.push_back(rangeData);
}
_triggerManager.sendFinsMsg("write_short_261_0");//清零
_triggerManager.sendFinsMsg("write_short_262_1");
_triggerManager.sendFinsMsg("write_short_263_1");
//上位机校正完成,将寄存器274置为1,并将结果按照定义XYZ规则放入310~336中
if (armPos == 9)
{
std::shared_ptr <detData> data = _detDataManager.insertDetData("181964", "TEST", 0, 0);
data->productType = _core._detGlobalData.productType;
data->_productDataStruct = _core._appConfig.productDatas[_core._detGlobalData.productType];
data->imgAmountMin = 0;
data->laserData = laserDataCache;
_threadManager.addTask(data);//添加任务
laserDataCache = correctionStruct();
}
}
//拍照并检测 300
void captureImageAndDetection(QByteArray& byteArray)
{
startDet = true;
//detMutex.lock();
_lightSourceManager.getLightSourcePtr("COM9")->setValue(lightSourceChannel::DChannel, 255);
QThread::msleep(2000);//延时等待机械臂停稳
_triggerManager.sendFinsMsg("write_short_300_0");//触发信号清零
_triggerManager.sendFinsMsg("write_short_301_1");//开始检测信号
int Pos = _triggerManager.getValue(303, byteArray);
emit _core._qtFunc.uiModuleLocationMap_SetProductSignStatus(Pos, 1);
std::cout << "arm @Pos:" << Pos;
std::shared_ptr <detData> data = _detDataManager.insertDetData("Camera1", currentSn, 1, 1);
data->oriShowIndex = 0;
data->resShowIndex = 0;
data->armPos = Pos;
data->productType = _core._detGlobalData.productType;
data->_productDataStruct = _core._appConfig.productDatas[_core._detGlobalData.productType];
auto camera = _cameraManager.getCamera("Camera1");//查找相机
if (camera != nullptr)
camera->captureImage(data);//拍照
data->imgSaveFileParameter.push_back(_core._detGlobalData.productTypeStr);//设置部分文件名
data->imgSaveFileParameter.push_back("Pos" + std::to_string(Pos));//设置部分文件名
_threadManager.addTask(data);//添加任务
QThread::msleep(1000);//延时一秒完成拍照,后续改成拍完直接发送
_triggerManager.sendFinsMsg("write_short_302_1");//开始检测信号
//detMutex.unlock();
}
//机械臂状态切换 361 1 空闲
void detectionSwitch1(QByteArray& byteArray)
{
//if (armIsRunning == false)
{
_lightSourceManager.getLightSourcePtr("COM9")->setValue(lightSourceChannel::DChannel, 0);
armIsRunning = true;
emit _core._qtFunc.switchStartBtnStatusSignal(true);
emit _core._qtFunc.simpleSiemensTcp_Write100False();
}
}
//机械臂状态切换 361 2 运行中
void detectionSwitch2(QByteArray& byteArray)
{
//if(armIsRunning == true)
{
emit _core._qtFunc.uiModuleBackContinueDetDialog_hide();
//armIsRunning = false;
emit _core._qtFunc.switchStartBtnStatusSignal(false);
emit _core._qtFunc.simpleSiemensTcp_Write100True();
}
}
//检测程序结束结束
void detectionEnd(QByteArray& byteArray)
{
_simpleSiemensTcp.writeDM100FALSE();
_lightSourceManager.getLightSourcePtr("COM9")->setValue(lightSourceChannel::DChannel, 0);
bool result = true;
if (armIsRunning == true)
{
armIsRunning = false;
_triggerManager.sendFinsMsg("write_short_362_0");
auto productData = _core._productDataCache.get(currentSn);
productData->writeProductData(currentSn, _core._appConfig.productDatas[_core._detGlobalData.productType]);
QDateTime currentDateTime = QDateTime::currentDateTime();
std::string dateDirStr = currentDateTime.toString("yyyy-MM-dd").toStdString();
productData->saveData("D://CCD//Result//" + dateDirStr + "//result.xlsx");
//先查询数据库
auto sqlData = _core._appConfig._sqlManager.selectRowData(currentSn);
if (sqlData.rowDatas.size() > 1)
for (auto data : sqlData.rowDatas[0])
if (!data.key.compare("detResult"))
if (!data.value.compare("NG"))
result = false;
//数据库结果为false时 不根据当前跑料数据判断
if (result == false)
{
emit _core._qtFunc.uiModuleSummaryDataManager_SetSummaryResultText("NG", Qt::red);
return;
}
//数据库结果为true或者没有查询到数据时时 继续判断
if (productData->ngPinCount > 0 || productData->ngCount > 0)//NG
{
emit _core._qtFunc.uiModuleSummaryDataManager_SetSummaryResultText("NG", Qt::red);
_core._appConfig._sqlManager.updateData(currentSn, { {"detResult","NG"} });
}
else
{
emit _core._qtFunc.uiModuleSummaryDataManager_SetSummaryResultText("OK", Qt::green);
_core._appConfig._sqlManager.updateData(currentSn, { {"detResult","OK"} });
}
std::cout << "detprocess runEnd" << std::endl;
}
//是否继续运行背面检测
int currentProductIndex = _core._appConfig._switchProductWidgetDataPtr.currentProductIndex;
if (currentBack == true)
currentBack = false;
else if (
_core._appConfig.productDatas[currentProductIndex].isBackExist == true
&& result == true
&& startDet == true)
{
backArmIndex = _core._appConfig.productDatas[currentProductIndex].backArmIndex;
emit _core._qtFunc.uiModuleBackContinueDetDialog_show();
emit _core._qtFunc.uiModulestartDetBtn_disable();
}
startDet = false;
}
//校准结果处理
void correctionResultHandle(std::shared_ptr<detData>data)
{
lastPointsOffsetStruct_ = data->pointsOffsetStruct_;
//写入plc
for (auto writeBackStr : data->writeBackData)
_triggerManager.sendFinsMsg(writeBackStr);
}
//检测结果处理
void detectionResultHandle(std::shared_ptr<detData>data)
{
data->sqlVec.push_back({ "SN",data->SNcode });
data->sqlVec.push_back({ "ARMPOS",std::to_string(data->armPos) });
//发送图片
if (data->resultImgs.size() > 0)
{
int cnt = 0;
for (auto showMat : data->resultImgs)
{
//打包发送
QPixmap pixmap = cvMatToQPixMap(showMat);
showImgPack* pack = new showImgPack();
pack->img = pixmap;
pack->type = imgWidgetRes;
pack->index = data->resShowIndex + cnt;
emit _core._qtFunc.sendPixmapImageWidget(pack);
historyPack _historyPack;
_historyPack.img = pixmap;
_historyPack.filePath = std::shared_ptr<std::string>(new std::string);
data->resImgSavePath.push_back(_historyPack.filePath);
auto it = _core._appConfig.productDatas[_core._detGlobalData.productType].productSign.find(data->armPos);
if (it != _core._appConfig.productDatas[_core._detGlobalData.productType].productSign.end())
_historyPack.text.push_back(it->second.sign);
emit _core._qtFunc.addHistoryDataSignal((data->aiDetOK == true && data->halconOK == true), _historyPack);
cnt++;
pixmap = QPixmap();
}
}
//发送检测结果发送到界面
if (data->armPos != -1)
{
//如果为NG,则等到按下按钮时在发送
bool finalOk = (data->halconOK == true && data->aiDetOK == true);
if (data->aiDetOK == true)
emit _core._qtFunc.addDashBoardData(1, data->aiDetOK);
else if (data->resultImgs.size() >= 1)
{
imageDoubleCheckPack pack;
pack.armPos = data->armPos;
cvMatToQPixMap(data->resultImgs[0], pack.img);
pack.type = 1;
emit _core._qtFunc.uiModuleImageDoubleCheckQdialog_ShowWindows(pack);
}
if (data->halconOK == true)
emit _core._qtFunc.addDashBoardData(0, data->halconOK);
else if (data->resultImgs.size() >= 2)
{
imageDoubleCheckPack pack;
pack.armPos = data->armPos;
cvMatToQPixMap(data->resultImgs[1], pack.img);
pack.type = 2;
emit _core._qtFunc.uiModuleImageDoubleCheckQdialog_ShowWindows(pack);
}
if (finalOk == true)
emit _core._qtFunc.uiModuleLocationMap_SetProductSignStatus(data->armPos, 2);
perConnector _perConnectorData;
_perConnectorData.aiOk = data->aiDetOK;
_perConnectorData.halconOk = data->halconOK;
_perConnectorData.maxPinDetValue = data->maxPinDetValue;
auto productData = _core._productDataCache.get(currentSn);
productData->connectorResults.push_back(_perConnectorData);
data->sqlVec.push_back({ "Result",std::to_string(finalOk) });
}
//ct计算以及发送到界面
auto totalCt = std::chrono::duration_cast<std::chrono::milliseconds>(data->halconEndTime - data->algoStartTime);
auto aiCt = std::chrono::duration_cast<std::chrono::milliseconds>(data->handleAiEndTime - data->algoStartTime);
auto halconCt = std::chrono::duration_cast<std::chrono::milliseconds>(data->halconEndTime - data->handleAiEndTime);
if (totalCt.count() > 0)
emit _core._qtFunc.addCtData(0, totalCt.count());
if (aiCt.count() > 0)
emit _core._qtFunc.addCtData(1, aiCt.count());
if (halconCt.count() > 0)
emit _core._qtFunc.addCtData(2, halconCt.count());
data->sqlVec.push_back({ "totalCt",std::to_string(totalCt.count()) });
data->sqlVec.push_back({ "aiCt",std::to_string(aiCt.count()) });
data->sqlVec.push_back({ "halconCt",std::to_string(halconCt.count()) });
//SQL
std::vector<sqlData> sqlDatas;
for (auto sqlData : data->sqlVec)
sqlDatas.push_back({ sqlData.first, sqlData.second });
_core._appConfig._sqlManager.addData(data->SNcode, sqlDatas);
//写入plc
for (auto writeBackStr : data->writeBackData)
_triggerManager.sendFinsMsg(writeBackStr);
//储存结果图
std::async(std::launch::async, &imgSaveThreadManager::saveRes, &_imgSaveThreadManager, data);
//删除 不再持有
detDataManager* dManager = data->dManager;
data->dManager->deleteDetData(data->timeCode);
}
//使用点激光测量检测是否为正面,没数据就是正面
void frontBackDet()
{
QThread::msleep(1000);
_triggerManager.sendFinsMsg("write_short_364_0");
_triggerManager.sendFinsMsg("write_short_365_0");
auto cameraPtr = _cameraManager.getCamera("181964");
if (cameraPtr == nullptr)
return;
//for (int i = 0; i < 10; i++)//弃用
//{
// cameraPtr->trigger();
// cameraPtr->getCameraValue();
//}
//for (int i = 0; i < 100; i++)//检测是否有数据
//{
// cameraPtr->trigger();
// if (cameraPtr->getCameraValue() > -100)//有数据 是反面
// {
// _triggerManager.sendFinsMsg("write_short_365_2");
// break;
// }
//}
//1是正面,读不到,2是反面,可以读到
//edit 1是读不到数据 2是读的到数据
cameraPtr->trigger();
double value = cameraPtr->getCameraValue();
std::cout << "camera value" << value;
if (value > -100)//有数据 是反面
{
_triggerManager.sendFinsMsg("write_short_365_2");
return;
}
_triggerManager.sendFinsMsg("write_short_365_1");//无数据 是正面
//正面反面是否继续检测,在机械臂脚本中决定
}
void testFunc()
{
auto cameraPtr = _cameraManager.getCamera("181964");
if (cameraPtr == nullptr)
return;
std::vector<double> values;
for (int i = 0; i < 1000; i++)
{
cameraPtr->trigger();
double v = cameraPtr->getCameraValue();
std::cout << v << std::endl;
}
}
public slots:
void runBackDet()
{
if (backArmIndex != -1)
{
currentBack = true;
_triggerManager.sendFinsMsg("write_short_350_" + QString::number(backArmIndex));//清零
_triggerManager.sendFinsMsg("write_short_351_1");
qDebug() << "运行背后检测程序";
_triggerManager.sendFinsMsg("write_short_310_" + QString::number(lastPointsOffsetStruct_.baseOffsetX < 0 ? 2 : 1));
_triggerManager.sendFinsMsg("write_short_311_"+QString::number(abs(static_cast<int>(lastPointsOffsetStruct_.baseOffsetX))));
double pvalueX = lastPointsOffsetStruct_.baseOffsetX - static_cast<int>(lastPointsOffsetStruct_.baseOffsetX);
_triggerManager.sendFinsMsg("write_short_312_" + QString::number(static_cast<int>(abs(pvalueX * 100))));
_triggerManager.sendFinsMsg("write_short_313_" + QString::number(lastPointsOffsetStruct_.baseOffsetY < 0 ? 2 : 1));
_triggerManager.sendFinsMsg("write_short_314_" + QString::number(abs(static_cast<int>(lastPointsOffsetStruct_.baseOffsetY))));
double pvalueY = lastPointsOffsetStruct_.baseOffsetY - static_cast<int>(lastPointsOffsetStruct_.baseOffsetY);
_triggerManager.sendFinsMsg("write_short_315_" + QString::number(static_cast<int>(abs(pvalueY * 100))));
_triggerManager.sendFinsMsg("write_short_316_" + QString::number(lastPointsOffsetStruct_.baseOffsetZ < 0 ? 2 : 1));
_triggerManager.sendFinsMsg("write_short_317_" + QString::number(abs(static_cast<int>(lastPointsOffsetStruct_.baseOffsetZ))));
double pvalueZ = lastPointsOffsetStruct_.baseOffsetZ - static_cast<int>(lastPointsOffsetStruct_.baseOffsetZ);
_triggerManager.sendFinsMsg("write_short_318_" + QString::number(static_cast<int>(abs(pvalueZ * 100))));
}
}
void writeArmStartSignal(int productTypeIn, QString SN)
{
_core._appConfig.productDatasMutex.lock();
_core._detGlobalData.productTypeStr = _core._appConfig.productDatas[productTypeIn].name;
_core._appConfig.productDatasMutex.unlock();
_core._detGlobalData.productType = productTypeIn;
if(_core._detGlobalData.currentSn!="")
_core._detGlobalData.currentSn = SN.toStdString();
currentSn = SN.toStdString();
_triggerManager.sendFinsMsg("write_short_350_" + QString::number(_core._appConfig.productDatas[productTypeIn].indexOfArm));
_triggerManager.sendFinsMsg("write_short_351_1");
qDebug() << "SN:" << SN << "开始运行,型号->" << QString::fromStdString(_core._detGlobalData.productTypeStr);
std::cout << "SN:" << SN.toStdString() << "开始运行,型号->" << _core._detGlobalData.productTypeStr <<std::endl;
}
//人工复判按下NG
void uiModuleImageDoubleCheckQdialog_pressNG(int armPos,int type)//1 halcon 2ai
{
if(type == 1)
emit _core._qtFunc.addDashBoardData(0, false);
else if (type == 2)
emit _core._qtFunc.addDashBoardData(1, false);
emit _core._qtFunc.uiModuleLocationMap_SetProductSignStatus(armPos, 3);
emit _core._qtFunc.uiModulestartDetBtn_enable();
_triggerManager.sendFinsMsg("write_short_363_1");
auto productData = _core._productDataCache.get(currentSn);
productData->ngCount++;
std::cout << "TYPE:" << std::to_string(type) << std::endl;
//detMutex.unlock();
}
//人工复判按下OK
void uiModuleImageDoubleCheckQdialog_pressOK(int armPos, int type)//1 halcon 2ai
{
if (type == 1)
emit _core._qtFunc.addDashBoardData(0, true);
else if (type == 2)
emit _core._qtFunc.addDashBoardData(1, true);
emit _core._qtFunc.uiModuleLocationMap_SetProductSignStatus(armPos, 2);
emit _core._qtFunc.uiModulestartDetBtn_enable();
std::cout << "TYPE:" << std::to_string(type) << std::endl;
//detMutex.unlock();
}
};
#pragma once