GrabBag/App/Workpiece/WorkpieceApp/dialogalgoarg.cpp

371 lines
12 KiB
C++

#include "dialogalgoarg.h"
#include "ui_dialogalgoarg.h"
#include <QMessageBox>
#include <QPushButton>
#include <QFileDialog>
#include <QComboBox>
#include <QtCore/QCoreApplication>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtCore/QStandardPaths>
#include <QtCore/QFile>
#include <cstring>
#include "PathManager.h"
#include "StyledMessageBox.h"
#include "HandEyeCalibWidget.h"
#include "VrLog.h"
DialogAlgoarg::DialogAlgoarg(ConfigManager* configManager, QWidget *parent)
: QDialog(parent)
, ui(new Ui::DialogAlgoarg)
, m_pConfigManager(configManager)
, m_handEyeCalibWidget(nullptr)
{
try {
ui->setupUi(this);
// 获取配置文件路径
m_configFilePath = PathManager::GetInstance().GetConfigFilePath();
// 检查配置文件路径是否有效
if (m_configFilePath.isEmpty()) {
StyledMessageBox::critical(this, "错误", "无法获取配置文件路径!");
return;
}
// 从配置文件加载数据到界面
LoadConfigToUI();
// 初始化手眼标定 tab
InitHandEyeCalibTab();
} 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");
}
// 加载算法参数到UI
const VrAlgorithmParams& algoParams = configData.algorithmParams;
// 加载各个参数组
LoadWorkpieceParamToUI(algoParams.workpieceParam);
LoadFilterParamToUI(algoParams.filterParam);
LoadCornerParamToUI(algoParams.cornerParam);
LoadGrowParamToUI(algoParams.growParam);
} 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;
const VrAlgorithmParams& algoParams = configData.algorithmParams;
LoadWorkpieceParamToUI(algoParams.workpieceParam);
LoadFilterParamToUI(algoParams.filterParam);
LoadCornerParamToUI(algoParams.cornerParam);
LoadGrowParamToUI(algoParams.growParam);
} catch (...) {
LOG_ERROR("Unknown exception in LoadConfigToUI\n");
StyledMessageBox::warning(this, "警告", "加载配置文件失败(未知错误),将使用默认参数显示");
// 发生未知异常时使用默认参数
ConfigResult configData;
const VrAlgorithmParams& algoParams = configData.algorithmParams;
LoadWorkpieceParamToUI(algoParams.workpieceParam);
LoadFilterParamToUI(algoParams.filterParam);
LoadCornerParamToUI(algoParams.cornerParam);
LoadGrowParamToUI(algoParams.growParam);
}
}
void DialogAlgoarg::LoadWorkpieceParamToUI(const VrWorkpieceParam& param)
{
if (!ui) return;
ui->lineEdit_lineLen->setText(QString::number(param.lineLen));
ui->lineEdit_dirAngleScale->setText(QString::number(param.dirAngleScale));
ui->lineEdit_lineDeviation->setText(QString::number(param.lineDeviation));
ui->lineEdit_minCutAngleTh->setText(QString::number(param.minCutAngleTh));
}
void DialogAlgoarg::LoadFilterParamToUI(const VrOutlierFilterParam& param)
{
if (!ui) return;
ui->lineEdit_continuityTh->setText(QString::number(param.continuityTh));
ui->lineEdit_outlierTh->setText(QString::number(param.outlierTh));
}
void DialogAlgoarg::LoadCornerParamToUI(const VrCornerParam& param)
{
if (!ui) return;
ui->lineEdit_cornerTh->setText(QString::number(param.cornerTh));
ui->lineEdit_scale->setText(QString::number(param.scale));
ui->lineEdit_minEndingGap->setText(QString::number(param.minEndingGap));
ui->lineEdit_minEndingGap_z->setText(QString::number(param.minEndingGap_z));
ui->lineEdit_jumpCornerTh_1->setText(QString::number(param.jumpCornerTh_1));
ui->lineEdit_jumpCornerTh_2->setText(QString::number(param.jumpCornerTh_2));
}
void DialogAlgoarg::LoadGrowParamToUI(const VrTreeGrowParam& param)
{
if (!ui) return;
ui->lineEdit_maxLineSkipNum->setText(QString::number(param.maxLineSkipNum));
ui->lineEdit_yDeviation_max->setText(QString::number(param.yDeviation_max));
ui->lineEdit_maxSkipDistance->setText(QString::number(param.maxSkipDistance));
ui->lineEdit_zDeviation_max->setText(QString::number(param.zDeviation_max));
ui->lineEdit_minLTypeTreeLen->setText(QString::number(param.minLTypeTreeLen));
ui->lineEdit_minVTypeTreeLen->setText(QString::number(param.minVTypeTreeLen));
}
bool DialogAlgoarg::SaveConfigFromUI()
{
if (!m_pConfigManager) {
return false;
}
try {
// 获取当前配置
SystemConfig systemConfig = m_pConfigManager->GetConfig();
VrAlgorithmParams& algoParams = systemConfig.configResult.algorithmParams;
// 保存各个参数组
if (!SaveWorkpieceParamFromUI(algoParams.workpieceParam)) {
StyledMessageBox::warning(this, "错误", "工件参数输入有误,请检查!");
return false;
}
if (!SaveFilterParamFromUI(algoParams.filterParam)) {
StyledMessageBox::warning(this, "错误", "滤波参数输入有误,请检查!");
return false;
}
if (!SaveCornerParamFromUI(algoParams.cornerParam)) {
StyledMessageBox::warning(this, "错误", "拐角参数输入有误,请检查!");
return false;
}
if (!SaveGrowParamFromUI(algoParams.growParam)) {
StyledMessageBox::warning(this, "错误", "生长参数输入有误,请检查!");
return false;
}
// 保存手眼标定参数(从临时缓存更新到配置)
algoParams.handEyeCalibParam = m_handEyeCalibParams;
// 更新并保存配置到文件
if (!m_pConfigManager->UpdateFullConfig(systemConfig)) {
return false;
}
return m_pConfigManager->SaveConfigToFile(m_configFilePath.toStdString());
} catch (const std::exception& e) {
return false;
}
}
bool DialogAlgoarg::SaveWorkpieceParamFromUI(VrWorkpieceParam& param)
{
bool ok = true;
param.lineLen = ui->lineEdit_lineLen->text().toDouble(&ok);
if (!ok) return false;
param.dirAngleScale = ui->lineEdit_dirAngleScale->text().toDouble(&ok);
if (!ok) return false;
param.lineDeviation = ui->lineEdit_lineDeviation->text().toDouble(&ok);
if (!ok) return false;
param.minCutAngleTh = ui->lineEdit_minCutAngleTh->text().toDouble(&ok);
if (!ok) return false;
return true;
}
bool DialogAlgoarg::SaveFilterParamFromUI(VrOutlierFilterParam& param)
{
bool ok = true;
param.continuityTh = ui->lineEdit_continuityTh->text().toDouble(&ok);
if (!ok) return false;
param.outlierTh = ui->lineEdit_outlierTh->text().toDouble(&ok);
if (!ok) return false;
return true;
}
bool DialogAlgoarg::SaveCornerParamFromUI(VrCornerParam& param)
{
bool ok = true;
param.cornerTh = ui->lineEdit_cornerTh->text().toDouble(&ok);
if (!ok) return false;
param.scale = ui->lineEdit_scale->text().toDouble(&ok);
if (!ok) return false;
param.minEndingGap = ui->lineEdit_minEndingGap->text().toDouble(&ok);
if (!ok) return false;
param.minEndingGap_z = ui->lineEdit_minEndingGap_z->text().toDouble(&ok);
if (!ok) return false;
param.jumpCornerTh_1 = ui->lineEdit_jumpCornerTh_1->text().toDouble(&ok);
if (!ok) return false;
param.jumpCornerTh_2 = ui->lineEdit_jumpCornerTh_2->text().toDouble(&ok);
if (!ok) return false;
return true;
}
bool DialogAlgoarg::SaveGrowParamFromUI(VrTreeGrowParam& param)
{
bool ok = true;
param.maxLineSkipNum = ui->lineEdit_maxLineSkipNum->text().toInt(&ok);
if (!ok) return false;
param.yDeviation_max = ui->lineEdit_yDeviation_max->text().toDouble(&ok);
if (!ok) return false;
param.maxSkipDistance = ui->lineEdit_maxSkipDistance->text().toDouble(&ok);
if (!ok) return false;
param.zDeviation_max = ui->lineEdit_zDeviation_max->text().toDouble(&ok);
if (!ok) return false;
param.minLTypeTreeLen = ui->lineEdit_minLTypeTreeLen->text().toDouble(&ok);
if (!ok) return false;
param.minVTypeTreeLen = ui->lineEdit_minVTypeTreeLen->text().toDouble(&ok);
if (!ok) return false;
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::InitHandEyeCalibTab()
{
if (!ui || !m_pConfigManager) return;
// 创建共享控件并嵌入 tab 的 layout
m_handEyeCalibWidget = new HandEyeCalibWidget(this);
ui->verticalLayout_handeyecalib->addWidget(m_handEyeCalibWidget);
// 设置默认文件路径
m_handEyeCalibWidget->setDefaultFilePath(
PathManager::GetInstance().GetAppConfigDirectory());
// 从配置中获取相机列表填充控件
ConfigResult configData = m_pConfigManager->GetConfigResult();
QVector<HandEyeCalibCameraInfo> cameraList;
for (size_t i = 0; i < configData.cameraList.size(); ++i) {
const DeviceInfo& camera = configData.cameraList[i];
HandEyeCalibCameraInfo info;
info.cameraIndex = static_cast<int>(i + 1); // 1-based
info.displayName = QString::fromStdString(camera.name);
cameraList.append(info);
}
m_handEyeCalibWidget->setCameraList(cameraList);
// 加载已有的手眼标定数据到缓存和控件
m_handEyeCalibParams = configData.algorithmParams.handEyeCalibParam;
for (const VrHandEyeCalibParam& param : m_handEyeCalibParams.cameraHandEyeParams) {
m_handEyeCalibWidget->setCalibData(
param.cameraIndex, param.transformMatrix, param.isCalibrated);
}
// 连接信号
connect(m_handEyeCalibWidget, &HandEyeCalibWidget::calibMatrixLoaded,
this, &DialogAlgoarg::onCalibMatrixLoaded);
connect(m_handEyeCalibWidget, &HandEyeCalibWidget::saveCalibRequested,
this, &DialogAlgoarg::onSaveCalibRequested);
}
void DialogAlgoarg::onCalibMatrixLoaded(int cameraIndex, const double* matrix)
{
// 更新临时缓存
VrHandEyeCalibParam param;
param.cameraIndex = cameraIndex;
param.isCalibrated = true;
memcpy(param.transformMatrix, matrix, sizeof(double) * 16);
m_handEyeCalibParams.SetCameraHandEyeParam(param);
StyledMessageBox::information(this, "成功", "标定矩阵加载成功!");
}
void DialogAlgoarg::onSaveCalibRequested(int cameraIndex, const double* matrix)
{
const VrHandEyeCalibParam* param = m_handEyeCalibParams.GetCameraHandEyeParam(cameraIndex);
if (!param || !param->isCalibrated) {
StyledMessageBox::warning(this, "提示", "当前相机尚未加载标定矩阵!请先加载标定矩阵文件。");
return;
}
// 将手眼标定数据保存到配置
try {
SystemConfig systemConfig = m_pConfigManager->GetConfig();
systemConfig.configResult.algorithmParams.handEyeCalibParam = m_handEyeCalibParams;
if (m_pConfigManager->UpdateFullConfig(systemConfig) &&
m_pConfigManager->SaveConfigToFile(m_configFilePath.toStdString())) {
StyledMessageBox::information(this, "成功", "手眼标定参数已保存到配置文件!");
} else {
StyledMessageBox::warning(this, "失败", "保存手眼标定参数失败!");
}
} catch (const std::exception& e) {
StyledMessageBox::warning(this, "错误",
QString("保存手眼标定参数异常: %1").arg(e.what()));
}
}