505 lines
19 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 <QPushButton>
#include <QDoubleValidator>
#include <QGroupBox>
#include <QtMath>
#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<HandEyeCalibCameraInfo> 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<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 (!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;
}