#include "dialogalgoarg.h" #include "ui_dialogalgoarg.h" #include #include #include #include #include "HandEyeCalibWidget.h" #include "PathManager.h" #include "StyledMessageBox.h" #include "ToolExtrinsicWidget.h" #include "NetworkConfigWidget.h" #include "VrLog.h" namespace { const int kHandEyeConfigIndex = 1; bool isIdentityMatrix(const double matrix[16]) { for (int index = 0; index < 16; ++index) { const double expected = (index / 4 == index % 4) ? 1.0 : 0.0; if (qAbs(matrix[index] - expected) > 1e-9) { return false; } } return true; } } DialogAlgoarg::DialogAlgoarg(ConfigManager* configManager, QWidget *parent) : QDialog(parent) , ui(new Ui::DialogAlgoarg) , m_pConfigManager(configManager) , m_handEyeCalibWidget(nullptr) , m_toolExtrinsicWidget(nullptr) { try { ui->setupUi(this); ui->lineEdit_modelMinimumScore->setValidator( new QDoubleValidator(0.0, 1.0, 6, ui->lineEdit_modelMinimumScore)); if (ui->lineEdit_fullImageExposure) ui->lineEdit_fullImageExposure->setValidator(new QDoubleValidator(0.0, 1e9, 0, ui->lineEdit_fullImageExposure)); if (ui->lineEdit_fullImageGain) ui->lineEdit_fullImageGain->setValidator(new QDoubleValidator(0.0, 1e3, 0, ui->lineEdit_fullImageGain)); if (ui->lineEdit_rotorRadius) ui->lineEdit_rotorRadius->setValidator(new QDoubleValidator(0.0, 1e6, 6, ui->lineEdit_rotorRadius)); if (ui->lineEdit_rotorHeight) ui->lineEdit_rotorHeight->setValidator(new QDoubleValidator(0.0, 1e6, 6, ui->lineEdit_rotorHeight)); if (ui->lineEdit_spacerLength) { ui->lineEdit_spacerLength->setValidator( new QDoubleValidator(0.0, 1e6, 6, ui->lineEdit_spacerLength)); } if (ui->lineEdit_spacerWidth) { ui->lineEdit_spacerWidth->setValidator( new QDoubleValidator(0.0, 1e6, 6, ui->lineEdit_spacerWidth)); } if (ui->lineEdit_layerRatio) ui->lineEdit_layerRatio->setValidator(new QDoubleValidator(0.0, 10.0, 6, ui->lineEdit_layerRatio)); if (ui->lineEdit_distToSideRatio) ui->lineEdit_distToSideRatio->setValidator(new QDoubleValidator(0.0, 10.0, 6, ui->lineEdit_distToSideRatio)); if (ui->lineEdit_groundRemoveOffset) ui->lineEdit_groundRemoveOffset->setValidator(new QDoubleValidator(-1e6, 1e6, 6, ui->lineEdit_groundRemoveOffset)); ui->tabWidget->setCurrentIndex(0); InitHandEyeCalibTab(); InitNetworkConfigTab(); InitToolExtrinsicTab(); // 隐藏标题栏 // setWindowFlags(Qt::FramelessWindowHint); // 获取配置文件路径 m_configFilePath = PathManager::GetInstance().GetConfigFilePath(); // 检查配置文件路径是否有效 if (m_configFilePath.isEmpty()) { StyledMessageBox::critical(this, "错误", "无法获取配置文件路径!"); return; } // 从配置文件加载数据到界面 LoadConfigToUI(); } catch (const std::exception& e) { StyledMessageBox::critical(this, "初始化错误", QString("对话框初始化失败: %1").arg(e.what())); } catch (...) { StyledMessageBox::critical(this, "初始化错误", "对话框初始化失败!(未知错误)"); } } DialogAlgoarg::~DialogAlgoarg() { delete ui; } void DialogAlgoarg::LoadConfigToUI() { if (!m_pConfigManager) { StyledMessageBox::critical(this, "错误", "配置对象未初始化!"); return; } try { // 从ConfigManager获取配置数据 ConfigResult configData = m_pConfigManager->GetConfigResult(); // 检查配置文件路径是否有效 if (m_configFilePath.isEmpty()) { LOG_WARNING("Config file path is empty\n"); } const VrToolParam& toolParam = configData.algorithmParams.toolParam; LoadModelDetectionParamsToUI(configData.algorithmParams.modelParam); LoadBinDetectionParamsToUI(configData.algorithmParams.binParam); LoadRotorCoreParamsToUI(configData.algorithmParams.rotorCoreParam); LoadFullImageCaptureParamsToUI(configData.algorithmParams.fullImageCaptureParam); if (m_toolExtrinsicWidget) { m_toolExtrinsicWidget->setData( toolParam.eulerOrder, toolParam.rotX, toolParam.rotY, toolParam.rotZ, toolParam.offsetX, toolParam.offsetY, toolParam.offsetZ); } // 加载网络配置(JSON TCP 端口 + Modbus 寄存器地址) LoadPlcRobotServerConfigToUI(configData.plcRobotServerConfig); LoadHandEyeCalibConfig(); } catch (const std::exception& e) { LOG_ERROR("Exception in LoadConfigToUI: %s\n", e.what()); StyledMessageBox::warning(this, "警告", QString("加载配置时发生异常: %1\n将使用默认参数显示").arg(e.what())); ConfigResult configData; LoadModelDetectionParamsToUI(configData.algorithmParams.modelParam); LoadBinDetectionParamsToUI(configData.algorithmParams.binParam); LoadRotorCoreParamsToUI(configData.algorithmParams.rotorCoreParam); LoadFullImageCaptureParamsToUI(configData.algorithmParams.fullImageCaptureParam); const VrToolParam& toolParam = configData.algorithmParams.toolParam; if (m_toolExtrinsicWidget) { m_toolExtrinsicWidget->setData( toolParam.eulerOrder, toolParam.rotX, toolParam.rotY, toolParam.rotZ, toolParam.offsetX, toolParam.offsetY, toolParam.offsetZ); } } catch (...) { LOG_ERROR("Unknown exception in LoadConfigToUI\n"); StyledMessageBox::warning(this, "警告", "加载配置文件失败(未知错误),将使用默认参数显示"); ConfigResult configData; LoadModelDetectionParamsToUI(configData.algorithmParams.modelParam); LoadBinDetectionParamsToUI(configData.algorithmParams.binParam); LoadRotorCoreParamsToUI(configData.algorithmParams.rotorCoreParam); LoadFullImageCaptureParamsToUI(configData.algorithmParams.fullImageCaptureParam); const VrToolParam& toolParam = configData.algorithmParams.toolParam; if (m_toolExtrinsicWidget) { m_toolExtrinsicWidget->setData( toolParam.eulerOrder, toolParam.rotX, toolParam.rotY, toolParam.rotZ, toolParam.offsetX, toolParam.offsetY, toolParam.offsetZ); } } } void DialogAlgoarg::InitToolExtrinsicTab() { if (!ui || !ui->verticalLayout_toolExtrinsicHost || m_toolExtrinsicWidget) { return; } m_toolExtrinsicWidget = new ToolExtrinsicWidget(this); m_toolExtrinsicWidget->setCameraSelectorVisible(false); m_toolExtrinsicWidget->setTargetOffsetVisible(true); m_toolExtrinsicWidget->setAxialAngleRangeVisible(false); ui->verticalLayout_toolExtrinsicHost->addWidget(m_toolExtrinsicWidget); } void DialogAlgoarg::InitHandEyeCalibTab() { if (!ui || !ui->verticalLayout_handEyeCalibHost || m_handEyeCalibWidget) { return; } m_handEyeCalibWidget = new HandEyeCalibWidget(this); m_handEyeCalibWidget->setMatrixEditable(true); m_handEyeCalibWidget->setDefaultCalibType(0); m_handEyeCalibWidget->setDefaultFilePath( PathManager::GetInstance().GetAppConfigDirectory()); ui->verticalLayout_handEyeCalibHost->addWidget(m_handEyeCalibWidget); QVector cameraList; HandEyeCalibCameraInfo cameraInfo; cameraInfo.cameraIndex = kHandEyeConfigIndex; cameraInfo.displayName = QStringLiteral("手眼标定"); cameraList.append(cameraInfo); m_handEyeCalibWidget->setCameraList(cameraList); m_handEyeCalibWidget->setCalibType(kHandEyeConfigIndex, 0); connect(m_handEyeCalibWidget, &HandEyeCalibWidget::calibMatrixLoaded, this, &DialogAlgoarg::onCalibMatrixLoaded); connect(m_handEyeCalibWidget, &HandEyeCalibWidget::saveCalibRequested, this, &DialogAlgoarg::onSaveCalibRequested); } void DialogAlgoarg::InitNetworkConfigTab() { if (!ui || !ui->tabWidget || m_networkConfigWidget) { return; } m_networkConfigWidget = new NetworkConfigWidget(true, true, ui->tabWidget); m_networkConfigWidget->setExtrinsicControlsVisible(false); m_networkConfigWidget->setPoseOutputOrderVisible(true); if (QGroupBox* group = m_networkConfigWidget->findChild("groupPlc")) { group->setTitle(QStringLiteral("TCP端口与Modbus寄存器配置")); } const char* hideNames[] = {"labelPlcIp", "editPlcIp", "labelPlcPort", "editPlcPort"}; for (const char* name : hideNames) { if (QWidget* widget = m_networkConfigWidget->findChild(name)) { widget->hide(); } } ui->tabWidget->addTab(m_networkConfigWidget, QStringLiteral("网络配置")); } bool DialogAlgoarg::SaveConfigFromUI() { if (!m_pConfigManager) { return false; } try { // 获取当前配置 SystemConfig systemConfig = m_pConfigManager->GetConfig(); VrToolParam& toolParam = systemConfig.configResult.algorithmParams.toolParam; if (!SaveModelDetectionParamsFromUI( systemConfig.configResult.algorithmParams.modelParam)) { StyledMessageBox::warning(this, "错误", "模型检测参数输入有误,请检查!"); return false; } if (!SaveBinDetectionParamsFromUI(systemConfig.configResult.algorithmParams.binParam)) { StyledMessageBox::warning(this, "错误", "料框检测参数输入有误,请检查!"); return false; } if (!SaveRotorCoreParamsFromUI(systemConfig.configResult.algorithmParams.rotorCoreParam)) { StyledMessageBox::warning(this, "错误", "转子钢芯算法参数输入有误,请检查!"); return false; } if (!SaveFullImageCaptureParamsFromUI( systemConfig.configResult.algorithmParams.fullImageCaptureParam)) { StyledMessageBox::warning(this, "错误", "二维全图采集参数输入有误,请检查!"); return false; } if (!m_toolExtrinsicWidget || !m_toolExtrinsicWidget->hasAcceptableInput()) { StyledMessageBox::warning(this, "错误", "工具参数输入有误,请检查!"); return false; } m_toolExtrinsicWidget->getData( toolParam.eulerOrder, toolParam.rotX, toolParam.rotY, toolParam.rotZ, toolParam.offsetX, toolParam.offsetY, toolParam.offsetZ); // 保存网络配置(JSON TCP 端口 + Modbus 寄存器地址) if (!SavePlcRobotServerConfigFromUI(systemConfig.configResult.plcRobotServerConfig)) { StyledMessageBox::warning(this, "错误", "网络配置输入有误,请检查!"); return false; } // 保存手眼标定矩阵到配置 if (!SaveCalibMatrixToConfig(systemConfig.configResult.handEyeCalibMatrix)) { StyledMessageBox::warning(this, "错误", "手眼标定矩阵输入有误,请检查!"); return false; } // 更新并保存配置到文件 if (!m_pConfigManager->UpdateFullConfig(systemConfig)) { return false; } return m_pConfigManager->SaveConfigToFile(m_configFilePath.toStdString()); } catch (const std::exception&) { return false; } } void DialogAlgoarg::LoadModelDetectionParamsToUI(const VrWorkpieceModelParam& modelParam) { if (!ui || !ui->lineEdit_modelMinimumScore) { return; } ui->lineEdit_modelMinimumScore->setText(QString::number(modelParam.minimumScore, 'f', 6)); } void DialogAlgoarg::LoadBinDetectionParamsToUI(const VrBinParam& binParam) { Q_UNUSED(binParam); } bool DialogAlgoarg::SaveBinDetectionParamsFromUI(VrBinParam& binParam) { Q_UNUSED(binParam); return true; } void DialogAlgoarg::LoadRotorCoreParamsToUI(const VrRotorCoreParam& rotorParam) { if (!ui || !ui->lineEdit_rotorRadius || !ui->lineEdit_rotorHeight || !ui->lineEdit_spacerLength || !ui->lineEdit_spacerWidth || !ui->lineEdit_layerRatio || !ui->lineEdit_distToSideRatio || !ui->lineEdit_groundRemoveOffset) { return; } ui->lineEdit_rotorRadius->setText(QString::number(rotorParam.radius, 'f', 6)); ui->lineEdit_rotorHeight->setText(QString::number(rotorParam.height, 'f', 6)); ui->lineEdit_spacerLength->setText(QString::number(rotorParam.spacerLength, 'f', 6)); ui->lineEdit_spacerWidth->setText(QString::number(rotorParam.spacerWidth, 'f', 6)); ui->lineEdit_layerRatio->setText(QString::number(rotorParam.layerRatio, 'f', 6)); ui->lineEdit_distToSideRatio->setText(QString::number(rotorParam.distToSideRatio, 'f', 6)); ui->lineEdit_groundRemoveOffset->setText(QString::number(rotorParam.groundRemoveOffset, 'f', 6)); } bool DialogAlgoarg::SaveRotorCoreParamsFromUI(VrRotorCoreParam& rotorParam) { if (!ui || !ui->lineEdit_rotorRadius || !ui->lineEdit_rotorHeight || !ui->lineEdit_spacerLength || !ui->lineEdit_spacerWidth || !ui->lineEdit_layerRatio || !ui->lineEdit_distToSideRatio || !ui->lineEdit_groundRemoveOffset) { return false; } bool ok = false; rotorParam.radius = ui->lineEdit_rotorRadius->text().toDouble(&ok); if (!ok || rotorParam.radius <= 0.0) return false; rotorParam.height = ui->lineEdit_rotorHeight->text().toDouble(&ok); if (!ok || rotorParam.height <= 0.0) return false; rotorParam.spacerLength = ui->lineEdit_spacerLength->text().toDouble(&ok); if (!ok || rotorParam.spacerLength <= 0.0) { return false; } rotorParam.spacerWidth = ui->lineEdit_spacerWidth->text().toDouble(&ok); if (!ok || rotorParam.spacerWidth <= 0.0) { return false; } rotorParam.layerRatio = ui->lineEdit_layerRatio->text().toDouble(&ok); if (!ok || rotorParam.layerRatio <= 0.0) return false; rotorParam.distToSideRatio = ui->lineEdit_distToSideRatio->text().toDouble(&ok); if (!ok || rotorParam.distToSideRatio <= 0.0) return false; rotorParam.groundRemoveOffset = ui->lineEdit_groundRemoveOffset->text().toDouble(&ok); if (!ok) return false; return true; } bool DialogAlgoarg::SaveModelDetectionParamsFromUI(VrWorkpieceModelParam& modelParam) { if (!ui || !ui->lineEdit_modelMinimumScore) { return false; } bool scoreOk = false; const double minimumScore = ui->lineEdit_modelMinimumScore->text().toDouble(&scoreOk); if (!scoreOk || minimumScore < 0.0 || minimumScore > 1.0) { return false; } modelParam.minimumScore = minimumScore; return true; } void DialogAlgoarg::LoadFullImageCaptureParamsToUI(const VrFullImageCaptureParam& captureParam) { if (!ui || !ui->lineEdit_fullImageExposure || !ui->lineEdit_fullImageGain) { return; } ui->lineEdit_fullImageExposure->setText(QString::number(captureParam.exposure)); ui->lineEdit_fullImageGain->setText(QString::number(captureParam.gain)); } bool DialogAlgoarg::SaveFullImageCaptureParamsFromUI(VrFullImageCaptureParam& captureParam) { if (!ui || !ui->lineEdit_fullImageExposure || !ui->lineEdit_fullImageGain) { return false; } bool exposureOk = false; bool gainOk = false; const unsigned int exposure = ui->lineEdit_fullImageExposure->text().toUInt(&exposureOk); const unsigned int gain = ui->lineEdit_fullImageGain->text().toUInt(&gainOk); if (!exposureOk || exposure == 0 || !gainOk) { return false; } captureParam.exposure = exposure; captureParam.gain = gain; return true; } void DialogAlgoarg::on_btn_camer_ok_clicked() { if (SaveConfigFromUI()) { StyledMessageBox::information(this, "成功", "配置保存成功!"); accept(); } else { StyledMessageBox::warning(this, "失败", "配置保存失败,请检查文件权限或参数输入!"); } } void DialogAlgoarg::on_btn_camer_cancel_clicked() { reject(); } void DialogAlgoarg::onCalibMatrixLoaded(int cameraIndex, const double* matrix) { Q_UNUSED(cameraIndex); Q_UNUSED(matrix); StyledMessageBox::information(this, "提示", "已从文件导入标定矩阵"); } void DialogAlgoarg::onSaveCalibRequested(int cameraIndex, const double* matrix) { Q_UNUSED(cameraIndex); Q_UNUSED(matrix); if (SaveConfigFromUI()) { StyledMessageBox::information(this, "成功", "手眼标定参数已保存!"); } else { StyledMessageBox::warning(this, "失败", "保存手眼标定参数失败!"); } } void DialogAlgoarg::LoadHandEyeCalibConfig() { if (!m_pConfigManager || !m_handEyeCalibWidget) { return; } const ConfigResult configData = m_pConfigManager->GetConfigResult(); const VrHandEyeCalibMatrix& calibMatrix = configData.handEyeCalibMatrix; m_handEyeCalibWidget->setCalibData( kHandEyeConfigIndex, calibMatrix.matrix, !isIdentityMatrix(calibMatrix.matrix)); } bool DialogAlgoarg::SaveCalibMatrixToConfig(VrHandEyeCalibMatrix& calibMatrix) { if (!m_handEyeCalibWidget) { return false; } bool isCalibrated = false; return m_handEyeCalibWidget->getCalibData( kHandEyeConfigIndex, calibMatrix.matrix, isCalibrated); } void DialogAlgoarg::LoadPlcRobotServerConfigToUI(const VrPlcRobotServerConfig& config) { if (!m_networkConfigWidget) return; NetworkConfigData data; data.poseOutputOrder = config.poseOutputOrder; data.byteOrder = config.byteOrder; data.dirVectorInvert = config.dirVectorInvert; data.addrPhotoRequest = config.registerConfig.addrTrigger; data.addrDataComplete = config.registerConfig.addrWorkStatus; data.addrCoordDataStart = config.registerConfig.addrCoordDataStart; data.tcpServerPort = config.robotServerPort; m_networkConfigWidget->setConfig(data); } bool DialogAlgoarg::SavePlcRobotServerConfigFromUI(VrPlcRobotServerConfig& config) { if (!m_networkConfigWidget) return false; const NetworkConfigData data = m_networkConfigWidget->getConfig(); if (data.tcpServerPort <= 0 || data.tcpServerPort > 65535 || data.addrPhotoRequest < 0 || data.addrDataComplete < 0 || data.addrCoordDataStart < 0) { return false; } config.robotServerPort = data.tcpServerPort; config.registerConfig.addrTrigger = data.addrPhotoRequest; config.registerConfig.addrWorkStatus = data.addrDataComplete; config.registerConfig.addrCoordDataStart = data.addrCoordDataStart; config.poseOutputOrder = data.poseOutputOrder; config.dirVectorInvert = data.dirVectorInvert; config.byteOrder = data.byteOrder; return true; }