414 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "dialogalgoarg.h"
#include "ui_dialogalgoarg.h"
#include <QMessageBox>
#include <QPushButton>
#include <cstring>
#include <QSettings>
#include <QFileDialog>
#include <QDoubleValidator>
#include <QGroupBox>
#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<QGroupBox*>("groupPlc")) {
group->setTitle(QStringLiteral("TCP端口与Modbus寄存器配置"));
}
const char* hideNames[] = {"labelPlcIp", "editPlcIp", "labelPlcPort", "editPlcPort"};
for (const char* name : hideNames) {
if (QWidget* widget = m_networkConfigWidget->findChild<QWidget*>(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<QLineEdit*>(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;
}