#include #include #include #include #include #include #include #include #include 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_ptrdata) {correctionResultHandle(data); }); _threadManager.registerCallback([this](std::shared_ptrdata) {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(3000); 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 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 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 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_ptrdata) { lastPointsOffsetStruct_ = data->pointsOffsetStruct_; //写入plc for (auto writeBackStr : data->writeBackData) _triggerManager.sendFinsMsg(writeBackStr); } //检测结果处理 void detectionResultHandle(std::shared_ptrdata) { 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(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); emit _core._qtFunc.uiModuleImageDoubleCheckQdialog_ShowWindows(pack); pack.type = 1; } 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); emit _core._qtFunc.uiModuleImageDoubleCheckQdialog_ShowWindows(pack); pack.type = 0; } 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(data->halconEndTime - data->algoStartTime); auto aiCt = std::chrono::duration_cast(data->handleAiEndTime - data->algoStartTime); auto halconCt = std::chrono::duration_cast(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 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是反面,可以读到 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 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(lastPointsOffsetStruct_.baseOffsetX)))); double pvalueX = lastPointsOffsetStruct_.baseOffsetX - static_cast(lastPointsOffsetStruct_.baseOffsetX); _triggerManager.sendFinsMsg("write_short_312_" + QString::number(static_cast(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(lastPointsOffsetStruct_.baseOffsetY)))); double pvalueY = lastPointsOffsetStruct_.baseOffsetY - static_cast(lastPointsOffsetStruct_.baseOffsetY); _triggerManager.sendFinsMsg("write_short_315_" + QString::number(static_cast(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(lastPointsOffsetStruct_.baseOffsetZ)))); double pvalueZ = lastPointsOffsetStruct_.baseOffsetZ - static_cast(lastPointsOffsetStruct_.baseOffsetZ); _triggerManager.sendFinsMsg("write_short_318_" + QString::number(static_cast(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 <ngCount++; //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(); //detMutex.unlock(); } }; #pragma once