棒材的工具参数配置更新

This commit is contained in:
杰仔 2026-06-26 14:37:43 +08:00
parent 34e3cceef3
commit 328129906c
11 changed files with 213 additions and 118 deletions

View File

@ -34,8 +34,12 @@ public:
LaserDataLoader& dataLoader, LaserDataLoader& dataLoader,
const double clibMatrix[16], const double clibMatrix[16],
int eulerOrder, int eulerOrder,
int dirVectorInvert, double toolRotX,
int longAxisDir, double toolRotY,
double toolRotZ,
double toolOffsetX,
double toolOffsetY,
double toolOffsetZ,
DetectionResult& detectionResult); DetectionResult& detectionResult);
}; };

View File

@ -2,6 +2,7 @@
#include "rodAndBarDetection_Export.h" #include "rodAndBarDetection_Export.h"
#include "AlgoParamConverter.h" #include "AlgoParamConverter.h"
#include "IHandEyeCalib.h" #include "IHandEyeCalib.h"
#include <cmath>
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <QColor> #include <QColor>
@ -48,8 +49,12 @@ int DetectPresenter::DetectRod(
LaserDataLoader& dataLoader, LaserDataLoader& dataLoader,
const double clibMatrix[16], const double clibMatrix[16],
int eulerOrder, int eulerOrder,
int dirVectorInvert, double toolRotX,
int longAxisDir, double toolRotY,
double toolRotZ,
double toolOffsetX,
double toolOffsetY,
double toolOffsetZ,
DetectionResult& detectionResult) DetectionResult& detectionResult)
{ {
if (laserLines.empty()) { if (laserLines.empty()) {
@ -165,14 +170,32 @@ int DetectPresenter::DetectRod(
HECPoint3D(rod.center.x, rod.center.y, rod.center.z), HECPoint3D(rod.center.x, rod.center.y, rod.center.z),
HECPoint3D(rod.axialDir.x, rod.axialDir.y, rod.axialDir.z), HECPoint3D(rod.axialDir.x, rod.axialDir.y, rod.axialDir.z),
HECPoint3D(rod.normalDir.x, rod.normalDir.y, rod.normalDir.z), HECPoint3D(rod.normalDir.x, rod.normalDir.y, rod.normalDir.z),
dirVectorInvert, 0,
hecEulerOrder, hecEulerOrder,
longAxisDir == 1 ? HECLongAxisDir::AxisY : HECLongAxisDir::AxisX, HECLongAxisDir::AxisX,
poseResult); poseResult);
if (!validPose) { if (!validPose) {
LOG_WARNING("[Algo Thread] Rod %zu has invalid axial/normal direction, use zero pose\n", i); LOG_WARNING("[Algo Thread] Rod %zu has invalid axial/normal direction, use zero pose\n", i);
} }
if (std::abs(toolRotX) > 1e-9 || std::abs(toolRotY) > 1e-9 || std::abs(toolRotZ) > 1e-9) {
HECRotationMatrix poseRotation;
handEyeCalib->EulerToRotationMatrix(poseResult.angles, hecEulerOrder, poseRotation);
HECRotationMatrix toolRotation;
handEyeCalib->EulerToRotationMatrix(
HECEulerAngles::fromDegrees(toolRotX, toolRotY, toolRotZ),
HECEulerOrder::ZYX,
toolRotation);
HECRotationMatrix adjustedRotation = poseRotation * toolRotation;
handEyeCalib->RotationMatrixToEuler(adjustedRotation, hecEulerOrder, poseResult.angles);
}
poseResult.position.x += toolOffsetX;
poseResult.position.y += toolOffsetY;
poseResult.position.z += toolOffsetZ;
double rollDeg = 0.0, pitchDeg = 0.0, yawDeg = 0.0; double rollDeg = 0.0, pitchDeg = 0.0, yawDeg = 0.0;
poseResult.angles.toDegrees(rollDeg, pitchDeg, yawDeg); poseResult.angles.toDegrees(rollDeg, pitchDeg, yawDeg);

View File

@ -229,22 +229,43 @@ int RodAndBarPositionPresenter::ProcessAlgoDetection(std::vector<std::pair<EVzRe
ConfigResult configResult = m_pConfigManager->GetConfigResult(); ConfigResult configResult = m_pConfigManager->GetConfigResult();
VrDebugParam debugParam = configResult.debugParam; VrDebugParam debugParam = configResult.debugParam;
int eulerOrder = configResult.eulerOrder; int eulerOrder = configResult.eulerOrder;
double toolRotX = 0.0;
double toolRotY = 0.0;
double toolRotZ = 0.0;
double toolOffsetX = 0.0;
double toolOffsetY = 0.0;
double toolOffsetZ = 0.0;
const int calibIdx = m_currentCameraIndex - 1; const int calibIdx = m_currentCameraIndex - 1;
if (calibIdx >= 0 && calibIdx < static_cast<int>(configResult.handEyeCalibMatrixList.size())) { if (calibIdx >= 0 && calibIdx < static_cast<int>(configResult.handEyeCalibMatrixList.size())) {
eulerOrder = configResult.handEyeCalibMatrixList[calibIdx].eulerOrder; const auto& toolConfig = configResult.handEyeCalibMatrixList[calibIdx];
eulerOrder = toolConfig.eulerOrder;
toolRotX = toolConfig.rotX;
toolRotY = toolConfig.rotY;
toolRotZ = toolConfig.rotZ;
toolOffsetX = toolConfig.offsetX;
toolOffsetY = toolConfig.offsetY;
toolOffsetZ = toolConfig.offsetZ;
} else if (!configResult.handEyeCalibMatrixList.empty()) { } else if (!configResult.handEyeCalibMatrixList.empty()) {
eulerOrder = configResult.handEyeCalibMatrixList[0].eulerOrder; const auto& toolConfig = configResult.handEyeCalibMatrixList[0];
eulerOrder = toolConfig.eulerOrder;
toolRotX = toolConfig.rotX;
toolRotY = toolConfig.rotY;
toolRotZ = toolConfig.rotZ;
toolOffsetX = toolConfig.offsetX;
toolOffsetY = toolConfig.offsetY;
toolOffsetZ = toolConfig.offsetZ;
} }
const int dirVectorInvert = configResult.dirVectorInvert; LOG_INFO("[Algo Thread] Using tool params: euler=%d, rot=(%.3f, %.3f, %.3f), offset=(%.3f, %.3f, %.3f)\n",
const int longAxisDir = configResult.longAxisDir; eulerOrder, toolRotX, toolRotY, toolRotZ, toolOffsetX, toolOffsetY, toolOffsetZ);
LOG_INFO("[Algo Thread] Using euler order: %d, dir vector invert: %d, long axis dir: %d\n", eulerOrder, dirVectorInvert, longAxisDir);
DetectionResult detectionResult; DetectionResult detectionResult;
int nRet = m_pDetectPresenter->DetectRod(m_currentCameraIndex, detectionDataCache, int nRet = m_pDetectPresenter->DetectRod(m_currentCameraIndex, detectionDataCache,
algorithmParams, debugParam, m_dataLoader, algorithmParams, debugParam, m_dataLoader,
currentClibMatrix.clibMatrix, eulerOrder, dirVectorInvert, currentClibMatrix.clibMatrix, eulerOrder,
longAxisDir, detectionResult); toolRotX, toolRotY, toolRotZ,
toolOffsetX, toolOffsetY, toolOffsetZ,
detectionResult);
// 算法返回 SX_ERR_ZERO_OBJECTS(-1010) 表示料框为空:单独提示并写专用协议状态码 4 // 算法返回 SX_ERR_ZERO_OBJECTS(-1010) 表示料框为空:单独提示并写专用协议状态码 4
if (nRet == ERR_CODE(SX_ERR_ZERO_OBJECTS)) { if (nRet == ERR_CODE(SX_ERR_ZERO_OBJECTS)) {

View File

@ -5,7 +5,7 @@
// 应用名称 // 应用名称
#define RODANDBARPOSITION_APP_NAME "棒材定位" #define RODANDBARPOSITION_APP_NAME "棒材定位"
#define RODANDBARPOSITION_VERSION_STRING "1.1.3" #define RODANDBARPOSITION_VERSION_STRING "1.1.4"
#define RODANDBARPOSITION_BUILD_STRING "1" #define RODANDBARPOSITION_BUILD_STRING "1"
#define RODANDBARPOSITION_FULL_VERSION_STRING "V" RODANDBARPOSITION_VERSION_STRING "_" RODANDBARPOSITION_BUILD_STRING #define RODANDBARPOSITION_FULL_VERSION_STRING "V" RODANDBARPOSITION_VERSION_STRING "_" RODANDBARPOSITION_BUILD_STRING

View File

@ -1,3 +1,7 @@
# 1.1.4 2026-06-26
## build_1
1. 修改工具的参数配置
# 1.1.3 2026-06-24 # 1.1.3 2026-06-24
## build_1 ## build_1
1. 更新算法 1. 更新算法

View File

@ -4,40 +4,38 @@
#include "StyledMessageBox.h" #include "StyledMessageBox.h"
#include "HandEyeCalibWidget.h" #include "HandEyeCalibWidget.h"
#include "NetworkConfigWidget.h" #include "NetworkConfigWidget.h"
#include "ToolExtrinsicWidget.h"
#include "PathManager.h" #include "PathManager.h"
#include "VrLog.h" #include "VrLog.h"
#include <algorithm>
#include <cstring> #include <cstring>
#include <QFormLayout>
#include <QGroupBox>
namespace namespace
{ {
/// 姿态输入/输出顺序 → 欧拉角旋转顺序 映射
int PoseOutputOrderToEulerOrder(int poseOrder) int PoseOutputOrderToEulerOrder(int poseOrder)
{ {
switch (poseOrder) { switch (poseOrder) {
case 0: return 10; // RX-RY-RZ XYZ case 0: return 10; // RX-RY-RZ -> XYZ
case 1: return 15; // RX-RZ-RY XZY case 1: return 15; // RX-RZ-RY -> XZY
case 2: return 13; // RY-RX-RZ YXZ case 2: return 13; // RY-RX-RZ -> YXZ
case 3: return 14; // RY-RZ-RX YZX case 3: return 14; // RY-RZ-RX -> YZX
case 4: return 12; // RZ-RX-RY ZXY case 4: return 12; // RZ-RX-RY -> ZXY
case 5: return 11; // RZ-RY-RX ZYX case 5: return 11; // RZ-RY-RX -> ZYX
default: return 11; // 默认 ZYX default: return 11;
} }
} }
/// 欧拉角旋转顺序 → 姿态输入/输出顺序 映射UI 显示用)
int EulerOrderToPoseOutputOrder(int eulerOrder) int EulerOrderToPoseOutputOrder(int eulerOrder)
{ {
switch (eulerOrder) { switch (eulerOrder) {
case 10: return 0; // XYZ RX-RY-RZ case 10: return 0; // XYZ -> RX-RY-RZ
case 15: return 1; // XZY RX-RZ-RY case 15: return 1; // XZY -> RX-RZ-RY
case 13: return 2; // YXZ RY-RX-RZ case 13: return 2; // YXZ -> RY-RX-RZ
case 14: return 3; // YZX RY-RZ-RX case 14: return 3; // YZX -> RY-RZ-RX
case 12: return 4; // ZXY RZ-RX-RY case 12: return 4; // ZXY -> RZ-RX-RY
case 11: return 5; // ZYX RZ-RY-RX case 11: return 5; // ZYX -> RZ-RY-RX
default: return 5; // 默认 RZ-RY-RX default: return 5;
} }
} }
@ -49,6 +47,7 @@ DialogAlgoArg::DialogAlgoArg(QWidget *parent)
, m_presenter(nullptr) , m_presenter(nullptr)
, m_handEyeCalibWidget(nullptr) , m_handEyeCalibWidget(nullptr)
, m_networkConfigWidget(nullptr) , m_networkConfigWidget(nullptr)
, m_toolExtrinsicWidget(nullptr)
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowTitle("算法参数设置"); setWindowTitle("算法参数设置");
@ -67,6 +66,9 @@ void DialogAlgoArg::SetPresenter(RodAndBarPositionPresenter* presenter)
// 初始化手眼标定 tab // 初始化手眼标定 tab
InitHandEyeCalibTab(); InitHandEyeCalibTab();
// 初始化工具参数 tab
InitToolExtrinsicTab();
// 初始化网络配置 tab // 初始化网络配置 tab
InitNetworkConfigTab(); InitNetworkConfigTab();
} }
@ -138,27 +140,41 @@ void DialogAlgoArg::saveParams()
m_presenter->SetAlgoParams(params); m_presenter->SetAlgoParams(params);
// 保存手眼标定矩阵 + 网络配置到配置文件(统一获取一次配置,避免互相覆盖) // 保存手眼标定矩阵 + 工具参数 + 网络配置到配置文件(统一获取一次配置,避免互相覆盖)
if (m_presenter->GetConfigManager()) { if (m_presenter->GetConfigManager()) {
ConfigManager* configManager = m_presenter->GetConfigManager(); ConfigManager* configManager = m_presenter->GetConfigManager();
SystemConfig systemConfig = configManager->GetConfig(); SystemConfig systemConfig = configManager->GetConfig();
NetworkConfigData netConfig;
bool hasNetworkConfig = false;
int toolEulerOrder = systemConfig.configResult.eulerOrder;
double toolRotX = 0.0;
double toolRotY = 0.0;
double toolRotZ = 0.0;
double toolOffsetX = 0.0;
double toolOffsetY = 0.0;
double toolOffsetZ = 0.0;
if (!systemConfig.configResult.handEyeCalibMatrixList.empty()) {
const auto& toolConfig = systemConfig.configResult.handEyeCalibMatrixList.front();
toolEulerOrder = toolConfig.eulerOrder;
toolRotX = toolConfig.rotX;
toolRotY = toolConfig.rotY;
toolRotZ = toolConfig.rotZ;
toolOffsetX = toolConfig.offsetX;
toolOffsetY = toolConfig.offsetY;
toolOffsetZ = toolConfig.offsetZ;
}
if (m_toolExtrinsicWidget) {
m_toolExtrinsicWidget->getData(toolEulerOrder,
toolRotX, toolRotY, toolRotZ,
toolOffsetX, toolOffsetY, toolOffsetZ);
}
systemConfig.configResult.eulerOrder = toolEulerOrder;
// 网络配置保存通信字节序和姿态输入/输出顺序;方向向量/长轴不再提供配置。
if (m_networkConfigWidget) { if (m_networkConfigWidget) {
netConfig = m_networkConfigWidget->getConfig(); NetworkConfigData netConfig = m_networkConfigWidget->getConfig();
// 欧拉角旋转顺序由姿态输入/输出顺序决定 toolEulerOrder = PoseOutputOrderToEulerOrder(netConfig.poseOutputOrder);
netConfig.eulerOrder = PoseOutputOrderToEulerOrder(netConfig.poseOutputOrder); systemConfig.configResult.eulerOrder = toolEulerOrder;
hasNetworkConfig = true;
systemConfig.configResult.eulerOrder = netConfig.eulerOrder;
systemConfig.configResult.dirVectorInvert = netConfig.dirVectorInvert;
systemConfig.configResult.byteOrder = netConfig.byteOrder; systemConfig.configResult.byteOrder = netConfig.byteOrder;
systemConfig.configResult.longAxisDir = netConfig.longAxisDir;
}
if (hasNetworkConfig) {
for (auto& calibMatrix : systemConfig.configResult.handEyeCalibMatrixList) {
calibMatrix.eulerOrder = netConfig.eulerOrder;
}
} }
// 保存手眼标定矩阵 // 保存手眼标定矩阵
@ -174,14 +190,26 @@ void DialogAlgoArg::saveParams()
// 先从已有配置中获取该相机的矩阵作为基础 // 先从已有配置中获取该相机的矩阵作为基础
VrHandEyeCalibMatrix calibMatrix; VrHandEyeCalibMatrix calibMatrix;
calibMatrix.cameraIndex = camIdx; calibMatrix.cameraIndex = camIdx;
calibMatrix.eulerOrder = systemConfig.configResult.eulerOrder; calibMatrix.eulerOrder = toolEulerOrder;
calibMatrix.rotX = toolRotX;
calibMatrix.rotY = toolRotY;
calibMatrix.rotZ = toolRotZ;
calibMatrix.offsetX = toolOffsetX;
calibMatrix.offsetY = toolOffsetY;
calibMatrix.offsetZ = toolOffsetZ;
for (const auto& old : oldMatrixList) { for (const auto& old : oldMatrixList) {
if (old.cameraIndex == camIdx) { if (old.cameraIndex == camIdx) {
calibMatrix = old; calibMatrix = old;
break; break;
} }
} }
calibMatrix.eulerOrder = systemConfig.configResult.eulerOrder; calibMatrix.eulerOrder = toolEulerOrder;
calibMatrix.rotX = toolRotX;
calibMatrix.rotY = toolRotY;
calibMatrix.rotZ = toolRotZ;
calibMatrix.offsetX = toolOffsetX;
calibMatrix.offsetY = toolOffsetY;
calibMatrix.offsetZ = toolOffsetZ;
// 如果控件中有更新的数据则覆盖 // 如果控件中有更新的数据则覆盖
bool isCalibrated = false; bool isCalibrated = false;
@ -195,16 +223,6 @@ void DialogAlgoArg::saveParams()
systemConfig.configResult.handEyeCalibMatrixList = newMatrixList; systemConfig.configResult.handEyeCalibMatrixList = newMatrixList;
} }
// 保存网络配置
if (m_networkConfigWidget) {
NetworkConfigData netConfig = m_networkConfigWidget->getConfig();
// 欧拉角旋转顺序由姿态输入/输出顺序决定
netConfig.eulerOrder = PoseOutputOrderToEulerOrder(netConfig.poseOutputOrder);
systemConfig.configResult.eulerOrder = netConfig.eulerOrder;
systemConfig.configResult.dirVectorInvert = netConfig.dirVectorInvert;
systemConfig.configResult.byteOrder = netConfig.byteOrder;
}
// 统一更新并保存到文件 // 统一更新并保存到文件
configManager->UpdateFullConfig(systemConfig); configManager->UpdateFullConfig(systemConfig);
QString configPath = PathManager::GetInstance().GetConfigFilePath(); QString configPath = PathManager::GetInstance().GetConfigFilePath();
@ -330,44 +348,60 @@ void DialogAlgoArg::onSaveCalibRequested(int cameraIndex, const double* matrix)
StyledMessageBox::information(this, "成功", "手眼标定参数已保存!"); StyledMessageBox::information(this, "成功", "手眼标定参数已保存!");
} }
// ========== 工具参数相关实现 ==========
void DialogAlgoArg::InitToolExtrinsicTab()
{
if (!ui || !m_presenter) return;
m_toolExtrinsicWidget = new ToolExtrinsicWidget(this);
m_toolExtrinsicWidget->setTargetOffsetVisible(true);
ui->verticalLayout_toolExtrinsicHost->addWidget(m_toolExtrinsicWidget);
loadToolExtrinsicConfig();
}
void DialogAlgoArg::loadToolExtrinsicConfig()
{
if (!m_presenter || !m_toolExtrinsicWidget) return;
ConfigManager* configManager = m_presenter->GetConfigManager();
if (!configManager) return;
ConfigResult configResult = configManager->GetConfigResult();
int eulerOrder = configResult.eulerOrder;
double rotX = 0.0;
double rotY = 0.0;
double rotZ = 0.0;
double offsetX = 0.0;
double offsetY = 0.0;
double offsetZ = 0.0;
if (!configResult.handEyeCalibMatrixList.empty()) {
const auto& toolConfig = configResult.handEyeCalibMatrixList.front();
eulerOrder = toolConfig.eulerOrder;
rotX = toolConfig.rotX;
rotY = toolConfig.rotY;
rotZ = toolConfig.rotZ;
offsetX = toolConfig.offsetX;
offsetY = toolConfig.offsetY;
offsetZ = toolConfig.offsetZ;
}
m_toolExtrinsicWidget->setData(eulerOrder, rotX, rotY, rotZ, offsetX, offsetY, offsetZ);
}
// ========== 网络配置相关实现 ========== // ========== 网络配置相关实现 ==========
void DialogAlgoArg::InitNetworkConfigTab() void DialogAlgoArg::InitNetworkConfigTab()
{ {
if (!ui || !m_presenter) return; if (!ui || !m_presenter) return;
// 创建网络配置控件不显示PLC配置不显示TCP配置
m_networkConfigWidget = new NetworkConfigWidget(false, false, this); m_networkConfigWidget = new NetworkConfigWidget(false, false, this);
ui->verticalLayout_networkConfigHost->addWidget(m_networkConfigWidget); ui->verticalLayout_networkConfigHost->addWidget(m_networkConfigWidget);
m_networkConfigWidget->setExtrinsicControlsVisible(false);
m_networkConfigWidget->setPoseOutputOrderVisible(true);
// 隐藏"欧拉角旋转顺序"和"输出欧拉角顺序"控件(本项目由姿态输入/输出顺序统一控制)
{
QList<QGroupBox*> groups = m_networkConfigWidget->findChildren<QGroupBox*>();
for (QGroupBox* group : groups) {
if (group->title() == QStringLiteral("通信参数")) {
QFormLayout* form = qobject_cast<QFormLayout*>(group->layout());
if (form) {
for (int i = 0; i < form->rowCount(); ++i) {
QLayoutItem* labelItem = form->itemAt(i, QFormLayout::LabelRole);
if (labelItem && labelItem->widget()) {
QLabel* label = qobject_cast<QLabel*>(labelItem->widget());
if (label && (label->text().contains(QStringLiteral("欧拉角旋转顺序"))
|| label->text().contains(QStringLiteral("输出欧拉角顺序")))) {
label->hide();
QLayoutItem* fieldItem = form->itemAt(i, QFormLayout::FieldRole);
if (fieldItem && fieldItem->widget()) {
fieldItem->widget()->hide();
}
}
}
}
}
break;
}
}
}
// 加载当前配置
loadNetworkConfig(); loadNetworkConfig();
} }
@ -381,16 +415,12 @@ void DialogAlgoArg::loadNetworkConfig()
ConfigResult configResult = configManager->GetConfigResult(); ConfigResult configResult = configManager->GetConfigResult();
NetworkConfigData netConfig; NetworkConfigData netConfig;
// 欧拉角旋转顺序由姿态输入/输出顺序统一控制
// 从存储的 eulerOrder 反推 poseOutputOrder 用于UI显示
netConfig.eulerOrder = configResult.eulerOrder; netConfig.eulerOrder = configResult.eulerOrder;
if (!configResult.handEyeCalibMatrixList.empty()) { if (!configResult.handEyeCalibMatrixList.empty()) {
netConfig.eulerOrder = configResult.handEyeCalibMatrixList[0].eulerOrder; netConfig.eulerOrder = configResult.handEyeCalibMatrixList.front().eulerOrder;
} }
netConfig.poseOutputOrder = EulerOrderToPoseOutputOrder(netConfig.eulerOrder); netConfig.poseOutputOrder = EulerOrderToPoseOutputOrder(netConfig.eulerOrder);
netConfig.dirVectorInvert = configResult.dirVectorInvert;
netConfig.byteOrder = configResult.byteOrder; netConfig.byteOrder = configResult.byteOrder;
netConfig.longAxisDir = configResult.longAxisDir;
m_networkConfigWidget->setConfig(netConfig); m_networkConfigWidget->setConfig(netConfig);
} }
@ -402,18 +432,14 @@ void DialogAlgoArg::saveNetworkConfig()
ConfigManager* configManager = m_presenter->GetConfigManager(); ConfigManager* configManager = m_presenter->GetConfigManager();
if (!configManager) return; if (!configManager) return;
NetworkConfigData netConfig = m_networkConfigWidget->getConfig();
// 欧拉角旋转顺序由姿态输入/输出顺序决定
netConfig.eulerOrder = PoseOutputOrderToEulerOrder(netConfig.poseOutputOrder);
// 获取当前完整配置并更新网络参数 // 获取当前完整配置并更新网络参数
NetworkConfigData netConfig = m_networkConfigWidget->getConfig();
SystemConfig systemConfig = configManager->GetConfig(); SystemConfig systemConfig = configManager->GetConfig();
systemConfig.configResult.eulerOrder = netConfig.eulerOrder; const int eulerOrder = PoseOutputOrderToEulerOrder(netConfig.poseOutputOrder);
systemConfig.configResult.dirVectorInvert = netConfig.dirVectorInvert; systemConfig.configResult.eulerOrder = eulerOrder;
systemConfig.configResult.byteOrder = netConfig.byteOrder; systemConfig.configResult.byteOrder = netConfig.byteOrder;
systemConfig.configResult.longAxisDir = netConfig.longAxisDir;
for (auto& calibMatrix : systemConfig.configResult.handEyeCalibMatrixList) { for (auto& calibMatrix : systemConfig.configResult.handEyeCalibMatrixList) {
calibMatrix.eulerOrder = netConfig.eulerOrder; calibMatrix.eulerOrder = eulerOrder;
} }
// 更新并保存 // 更新并保存

View File

@ -10,6 +10,7 @@ class DialogAlgoArg;
class RodAndBarPositionPresenter; class RodAndBarPositionPresenter;
class HandEyeCalibWidget; class HandEyeCalibWidget;
class NetworkConfigWidget; class NetworkConfigWidget;
class ToolExtrinsicWidget;
/** /**
* @brief * @brief
@ -42,6 +43,10 @@ private:
// 手眼标定 // 手眼标定
void InitHandEyeCalibTab(); void InitHandEyeCalibTab();
// 工具参数
void InitToolExtrinsicTab();
void loadToolExtrinsicConfig();
// 网络配置 // 网络配置
void InitNetworkConfigTab(); void InitNetworkConfigTab();
void loadNetworkConfig(); void loadNetworkConfig();
@ -56,6 +61,9 @@ private:
// 网络配置共享控件 // 网络配置共享控件
NetworkConfigWidget* m_networkConfigWidget; NetworkConfigWidget* m_networkConfigWidget;
// 工具参数共享控件
ToolExtrinsicWidget* m_toolExtrinsicWidget;
}; };
#endif // DIALOGALGOARG_H #endif // DIALOGALGOARG_H

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>761</width> <width>864</width>
<height>547</height> <height>547</height>
</rect> </rect>
</property> </property>
@ -699,6 +699,25 @@ QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;
</property> </property>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tabToolExtrinsic">
<attribute name="title">
<string>工具参数</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_toolExtrinsicHost">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
</layout>
</widget>
<widget class="QWidget" name="tabNetworkConfig"> <widget class="QWidget" name="tabNetworkConfig">
<attribute name="title"> <attribute name="title">
<string>网络配置</string> <string>网络配置</string>

View File

@ -76,9 +76,7 @@ struct ConfigResult
VrAlgorithmParams algorithmParams; // 算法参数 VrAlgorithmParams algorithmParams; // 算法参数
std::vector<VrHandEyeCalibMatrix> handEyeCalibMatrixList; // 多相机手眼标定矩阵列表 std::vector<VrHandEyeCalibMatrix> handEyeCalibMatrixList; // 多相机手眼标定矩阵列表
int eulerOrder = 11; // 欧拉角旋转顺序默认11=外旋ZYX int eulerOrder = 11; // 欧拉角旋转顺序默认11=外旋ZYX
int dirVectorInvert = 0; // 方向向量反向默认0=不反向
int byteOrder = 0; // 数据字节序默认0=大端序 int byteOrder = 0; // 数据字节序默认0=大端序
int longAxisDir = 0; // 目标物长边对应轴0=X轴, 1=Y轴
// 显式赋值构造函数,确保正确的深拷贝 // 显式赋值构造函数,确保正确的深拷贝
ConfigResult& operator=(const ConfigResult& other) { ConfigResult& operator=(const ConfigResult& other) {
@ -89,9 +87,7 @@ struct ConfigResult
algorithmParams = other.algorithmParams; algorithmParams = other.algorithmParams;
handEyeCalibMatrixList = other.handEyeCalibMatrixList; handEyeCalibMatrixList = other.handEyeCalibMatrixList;
eulerOrder = other.eulerOrder; eulerOrder = other.eulerOrder;
dirVectorInvert = other.dirVectorInvert;
byteOrder = other.byteOrder; byteOrder = other.byteOrder;
longAxisDir = other.longAxisDir;
} }
return *this; return *this;
} }
@ -104,9 +100,7 @@ struct ConfigResult
, algorithmParams(other.algorithmParams) , algorithmParams(other.algorithmParams)
, handEyeCalibMatrixList(other.handEyeCalibMatrixList) , handEyeCalibMatrixList(other.handEyeCalibMatrixList)
, eulerOrder(other.eulerOrder) , eulerOrder(other.eulerOrder)
, dirVectorInvert(other.dirVectorInvert) , byteOrder(other.byteOrder) {
, byteOrder(other.byteOrder)
, longAxisDir(other.longAxisDir) {
} }
// 默认构造函数 // 默认构造函数

View File

@ -115,12 +115,10 @@ int CVrConfig::LoadConfig(const std::string& filePath, ConfigResult& configResul
if (networkElement) if (networkElement)
{ {
networkElement->QueryIntAttribute("eulerOrder", &configResult.eulerOrder); networkElement->QueryIntAttribute("eulerOrder", &configResult.eulerOrder);
networkElement->QueryIntAttribute("dirVectorInvert", &configResult.dirVectorInvert);
networkElement->QueryIntAttribute("byteOrder", &configResult.byteOrder); networkElement->QueryIntAttribute("byteOrder", &configResult.byteOrder);
networkElement->QueryIntAttribute("longAxisDir", &configResult.longAxisDir);
LOG_INFO("Network config: eulerOrder=%d, dirVectorInvert=%d, byteOrder=%d, longAxisDir=%d\n", LOG_INFO("Network config: eulerOrder=%d, byteOrder=%d\n",
configResult.eulerOrder, configResult.dirVectorInvert, configResult.byteOrder, configResult.longAxisDir); configResult.eulerOrder, configResult.byteOrder);
} }
// 6. 解析手眼标定矩阵列表(支持多相机) // 6. 解析手眼标定矩阵列表(支持多相机)
@ -194,9 +192,7 @@ bool CVrConfig::SaveConfig(const std::string& filePath, ConfigResult& configResu
// 5. 保存网络参数 // 5. 保存网络参数
XMLElement* networkElement = doc.NewElement("NetworkConfig"); XMLElement* networkElement = doc.NewElement("NetworkConfig");
networkElement->SetAttribute("eulerOrder", configResult.eulerOrder); networkElement->SetAttribute("eulerOrder", configResult.eulerOrder);
networkElement->SetAttribute("dirVectorInvert", configResult.dirVectorInvert);
networkElement->SetAttribute("byteOrder", configResult.byteOrder); networkElement->SetAttribute("byteOrder", configResult.byteOrder);
networkElement->SetAttribute("longAxisDir", configResult.longAxisDir);
root->InsertEndChild(networkElement); root->InsertEndChild(networkElement);
// 6. 保存手眼标定矩阵列表(支持多相机) // 6. 保存手眼标定矩阵列表(支持多相机)

View File

@ -42,9 +42,9 @@
<!-- 串口配置 --> <!-- 串口配置 -->
<SerialConfig portName="COM6" baudRate="115200" dataBits="8" stopBits="1" parity="0" flowControl="0" enabled="false" /> <SerialConfig portName="COM6" baudRate="115200" dataBits="8" stopBits="1" parity="0" flowControl="0" enabled="false" />
<!-- 网络参数 --> <!-- 网络参数 -->
<NetworkConfig eulerOrder="11" dirVectorInvert="0" byteOrder="0" longAxisDir="0" /> <NetworkConfig eulerOrder="11" byteOrder="0" />
<!-- 手眼标定矩阵 --> <!-- 手眼标定矩阵 -->
<HandEyeCalibMatrixs> <HandEyeCalibMatrixs>
<HandEyeCalibMatrix cameraIndex="1" m0="1" m1="0" m2="0" m3="0" m4="0" m5="1" m6="0" m7="0" m8="0" m9="0" m10="1" m11="0" m12="0" m13="0" m14="0" m15="1" eulerOrder="11"/> <HandEyeCalibMatrix cameraIndex="1" m0="1" m1="0" m2="0" m3="0" m4="0" m5="1" m6="0" m7="0" m8="0" m9="0" m10="1" m11="0" m12="0" m13="0" m14="0" m15="1" eulerOrder="11" rotX="0" rotY="0" rotZ="0" offsetX="0" offsetY="0" offsetZ="0"/>
</HandEyeCalibMatrixs> </HandEyeCalibMatrixs>
</RodAndBarPositionConfig> </RodAndBarPositionConfig>