#include "dialogalgoarg.h" #include "ui_dialogalgoarg.h" #include #include #include #include #include #include #include #include "PathManager.h" #include "StyledMessageBox.h" #include "ToolExtrinsicWidget.h" #include "NetworkConfigWidget.h" #include "VrLog.h" DialogAlgoarg::DialogAlgoarg(ConfigManager* configManager, QWidget *parent) : QDialog(parent) , ui(new Ui::DialogAlgoarg) , m_pConfigManager(configManager) , m_toolExtrinsicWidget(nullptr) { try { ui->setupUi(this); ui->lineEdit_modelMinimumScore->setValidator( new QDoubleValidator(0.0, 1.0, 6, ui->lineEdit_modelMinimumScore)); ui->tabWidget->setCurrentIndex(0); InitNetworkConfigTab(); InitToolExtrinsicTab(); // 隐藏标题栏 // setWindowFlags(Qt::FramelessWindowHint); // 获取配置文件路径 m_configFilePath = PathManager::GetInstance().GetConfigFilePath(); // 检查配置文件路径是否有效 if (m_configFilePath.isEmpty()) { StyledMessageBox::critical(this, "错误", "无法获取配置文件路径!"); return; } // 初始化旋转顺序下拉框 InitEulerOrderComboBox(); // 从配置文件加载数据到界面 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); 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); // 加载手眼标定矩阵 LoadCalibMatrixToUI(); } 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); 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); 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::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 (!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)); } 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::on_btn_loadCalibMatrix_clicked() { QString filePath = QFileDialog::getOpenFileName( this, "选择手眼标定文件", QString(), "INI文件 (*.ini);;所有文件 (*.*)" ); if (filePath.isEmpty()) { return; } LoadCalibMatrixFromFile(filePath); StyledMessageBox::information(this, "提示", "已从文件导入标定矩阵"); } QLineEdit* DialogAlgoarg::GetCalibLineEdit(int row, int col) { // 通过名称查找对应的QLineEdit QString name = QString("lineEdit_calib_%1_%2").arg(row).arg(col); return findChild(name); } void DialogAlgoarg::LoadCalibMatrixToUI() { if (!m_pConfigManager) return; ConfigResult configData = m_pConfigManager->GetConfigResult(); for (int i = 0; i < 16; i++) { QLineEdit* edit = GetCalibLineEdit(i / 4, i % 4); if (edit) { edit->setText(QString::number(configData.handEyeCalibMatrix.matrix[i], 'f', 6)); } } // 加载旋转顺序 int eulerOrder = configData.handEyeCalibMatrix.eulerOrder; int index = ui->comboBox_eulerOrder->findData(eulerOrder); if (index >= 0) { ui->comboBox_eulerOrder->setCurrentIndex(index); } } void DialogAlgoarg::LoadCalibMatrixFromFile(const QString& filePath) { QSettings settings(filePath, QSettings::IniFormat); settings.beginGroup("CalibMatrixInfo_0"); for (int i = 0; i < 16; i++) { int row = i / 4; int col = i % 4; QString key = QString("dCalibMatrix_%1").arg(i); double val = settings.value(key, (row == col) ? 1.0 : 0.0).toDouble(); QLineEdit* edit = GetCalibLineEdit(row, col); if (edit) { edit->setText(QString::number(val, 'f', 6)); } } settings.endGroup(); } bool DialogAlgoarg::SaveCalibMatrixToConfig(VrHandEyeCalibMatrix& calibMatrix) { for (int i = 0; i < 16; i++) { QLineEdit* edit = GetCalibLineEdit(i / 4, i % 4); if (!edit) return false; bool ok = false; calibMatrix.matrix[i] = edit->text().toDouble(&ok); if (!ok) return false; } // 保存旋转顺序 calibMatrix.eulerOrder = ui->comboBox_eulerOrder->currentData().toInt(); return true; } void DialogAlgoarg::InitEulerOrderComboBox() { // 添加外旋旋转顺序选项(工业机械臂常用) ui->comboBox_eulerOrder->addItem("RZ-RY-RX (外旋ZYX)", 11); // ABB、KUKA、发那科等常用 ui->comboBox_eulerOrder->addItem("RX-RY-RZ (外旋XYZ)", 10); ui->comboBox_eulerOrder->addItem("RZ-RX-RY (外旋ZXY)", 12); ui->comboBox_eulerOrder->addItem("RY-RX-RZ (外旋YXZ)", 13); ui->comboBox_eulerOrder->addItem("RY-RZ-RX (外旋YZX)", 14); ui->comboBox_eulerOrder->addItem("RX-RZ-RY (外旋XZY)", 15); // 默认选择外旋 ZYX ui->comboBox_eulerOrder->setCurrentIndex(0); } 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; }