手眼标定完善

This commit is contained in:
yiyi 2026-02-22 00:10:46 +08:00
parent 11c615d0c9
commit ce4bd9348a
8 changed files with 2073 additions and 1741 deletions

46
GrabBagPrj/CalibView.iss Normal file
View File

@ -0,0 +1,46 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "手眼标定工具"
#define MyAppVersion "1.0.0"
#define MyAppPublisher ""
#define MyAppURL ""
#define MyAppExeName "CalibView.exe"
#define MyProgramPath ".\buildwin\CalibView"
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{F8A7B6C5-D4E3-4F2A-9B1C-0D8E7F6A5B4C}}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppVerName={#MyAppName}_V{#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DisableProgramGroupPage=yes
OutputBaseFilename={#MyAppName}V{#MyAppVersion}
OutputDir=..\Publish
Compression=lzma
SolidCompression=yes
[Languages]
Name: "default"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "{#MyProgramPath}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
[Icons]
Name: "{commonprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent runascurrentuser
[Code]

View File

@ -0,0 +1,34 @@
@echo off
setlocal
set PRJ_PATH=c:\project\QT\GrabBag\GrabBagPrj
if not exist "%PRJ_PATH%\buildwin\CalibView" mkdir "%PRJ_PATH%\buildwin\CalibView"
cd /d "%PRJ_PATH%\buildwin\CalibView"
powershell -Command "Remove-Item * -Recurse -Force"
copy "..\..\build\Tools\CalibView\release\CalibView.exe" .\
:: VzNLSDK DLL
copy "..\..\SDK\Device\VzNLSDK\Windows\x64\Release\VzKernel.dll" .\
copy "..\..\SDK\Device\VzNLSDK\Windows\x64\Release\VzNLDetect.dll" .\
copy "..\..\SDK\Device\VzNLSDK\Windows\x64\Release\VzNLGraphics.dll" .\
copy "..\..\SDK\Device\VzNLSDK\Windows\x64\Release\VzLog.dll" .\
copy "..\..\SDK\Device\VzNLSDK\Windows\x64\Release\libViEyeApi.dll" .\
:: OpenCV DLL
copy "..\..\SDK\OpenCV320\Windows\vc14\Release\opencv_world320.dll" .\
"C:\tools\Qt\5.15.2\msvc2019_64\bin\windeployqt.exe" "CalibView.exe"
cd ..\..
set ISCC_PATH=C:\Program Files (x86)\Inno Setup 6\ISCC.exe
"%ISCC_PATH%" "CalibView.iss"
echo "finish"
endlocal

View File

@ -9,7 +9,7 @@ cd /d "%PRJ_PATH%\buildwin\CloudView"
powershell -Command "Remove-Item * -Recurse -Force" powershell -Command "Remove-Item * -Recurse -Force"
copy "..\..\build\Tools\CloudView\release\CloudView.exe" .\ copy "..\..\build\Utils\CloudView\release\CloudView.exe" .\
"C:\tools\Qt\5.15.2\msvc2019_64\bin\windeployqt.exe" "CloudView.exe" "C:\tools\Qt\5.15.2\msvc2019_64\bin\windeployqt.exe" "CloudView.exe"

View File

@ -1,200 +1,215 @@
#ifndef CALIBDATAWIDGET_H #ifndef CALIBDATAWIDGET_H
#define CALIBDATAWIDGET_H #define CALIBDATAWIDGET_H
#include <QWidget> #include <QWidget>
#include <QTableWidget> #include <QTableWidget>
#include <QPushButton> #include <QPushButton>
#include <QComboBox> #include <QComboBox>
#include <QGroupBox> #include <QGroupBox>
#include <QSpinBox> #include <QSpinBox>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QLabel> #include <QLabel>
#include <vector> #include <vector>
#include "HandEyeCalibTypes.h" #include "HandEyeCalibTypes.h"
/** /**
* @brief * @brief
* Eye-To-HandEye-In-Hand TCP * Eye-To-HandEye-In-Hand TCP
*/ */
class CalibDataWidget : public QWidget class CalibDataWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CalibDataWidget(QWidget* parent = nullptr); explicit CalibDataWidget(QWidget* parent = nullptr);
~CalibDataWidget() override; ~CalibDataWidget() override;
/** /**
* @brief Eye-To-Hand * @brief Eye-To-Hand
*/ */
void getEyeToHandData(std::vector<HECPoint3D>& eyePoints, void getEyeToHandData(std::vector<HECPoint3D>& eyePoints,
std::vector<HECPoint3D>& robotPoints) const; std::vector<HECPoint3D>& robotPoints) const;
/** /**
* @brief Eye-In-Hand * @brief Eye-In-Hand
*/ */
void getEyeInHandData(std::vector<HECEyeInHandData>& calibData) const; void getEyeInHandData(std::vector<HECEyeInHandData>& calibData) const;
/** /**
* @brief * @brief
*/ */
HECCalibrationType getCalibType() const; HECCalibrationType getCalibType() const;
/** /**
* @brief * @brief (0=EyeToHand, 1=EyeInHand, 2=TCP)
*/ */
void clearAll(); int getCalibTypeIndex() const;
/** /**
* @brief * @brief
*/ */
void setRobotInput(double x, double y, double z, double rx, double ry, double rz); void clearAll();
/** /**
* @brief Eye-To-Hand * @brief
*/ */
void setCameraInput(double x, double y, double z, double rx, double ry, double rz); void setRobotInput(double x, double y, double z, double rx, double ry, double rz);
/** /**
* @brief TCP * @brief Eye-To-Hand
*/ */
HECTCPCalibData getTCPCalibData() const; void setCameraInput(double x, double y, double z, double rx, double ry, double rz);
signals: /**
/** * @brief TCP
* @brief */
*/ HECTCPCalibData getTCPCalibData() const;
void calibTypeChanged(HECCalibrationType type);
/**
/** * @brief INI
* @brief Eye-To-Hand */
*/ void saveCalibData(const QString& filePath) const;
void requestEyeToHandCalib();
/**
/** * @brief INI
* @brief Eye-In-Hand */
*/ void loadCalibData(const QString& filePath);
void requestEyeInHandCalib();
signals:
/** /**
* @brief TCP * @brief
*/ */
void requestTCPCalib(); void calibTypeChanged(HECCalibrationType type);
/**
private slots: * @brief Eye-To-Hand
/** */
* @brief void requestEyeToHandCalib();
*/
void onCalibTypeChanged(int index); /**
* @brief Eye-In-Hand
/** */
* @brief TCP 3-DOF / 6-DOF void requestEyeInHandCalib();
*/
void onTCPModeChanged(int index); /**
* @brief TCP
/** */
* @brief TCP void requestTCPCalib();
*/
void onTCPAddRow();
private slots:
/** /**
* @brief TCP * @brief
*/ */
void onTCPRemoveRow(); void onCalibTypeChanged(int index);
private: /**
/** * @brief TCP 3-DOF / 6-DOF
* @brief */
*/ void onTCPModeChanged(int index);
void setupUI();
/**
/** * @brief TCP
* @brief Eye-To-Hand */
*/ void onTCPAddRow();
QWidget* createEyeToHandGroup();
/**
/** * @brief TCP
* @brief Eye-In-Hand */
*/ void onTCPRemoveRow();
QWidget* createEyeInHandGroup();
private:
/** /**
* @brief TCP * @brief
*/ */
QWidget* createTCPCalibGroup(); void setupUI();
/**
/** * @brief Eye-To-Hand
* @brief */
*/ QWidget* createEyeToHandGroup();
void updateTableVisibility();
/**
// 标定模式选择 * @brief Eye-In-Hand
QComboBox* m_cbCalibType; */
QWidget* createEyeInHandGroup();
// Eye-To-Hand 数据表格
QTableWidget* m_tableEyeToHand; /**
QWidget* m_groupEyeToHand; * @brief TCP
*/
// Eye-In-Hand 数据表格 QWidget* createTCPCalibGroup();
QTableWidget* m_tableEyeInHand;
QWidget* m_groupEyeInHand;
/**
// Eye-To-Hand 内联按钮 * @brief
QPushButton* m_btnEyeToHandAddRow; */
QPushButton* m_btnEyeToHandDeleteRow; void updateTableVisibility();
QPushButton* m_btnEyeToHandCalib;
// 标定模式选择
// Eye-In-Hand 内联按钮 QComboBox* m_cbCalibType;
QPushButton* m_btnEyeInHandAddRow;
QPushButton* m_btnEyeInHandDeleteRow; // Eye-To-Hand 数据表格
QPushButton* m_btnEyeInHandCalib; QTableWidget* m_tableEyeToHand;
QWidget* m_groupEyeToHand;
// TCP 标定相关
QWidget* m_groupTCPCalib; // Eye-In-Hand 数据表格
QTableWidget* m_tableTCP; QTableWidget* m_tableEyeInHand;
QComboBox* m_tcpModeCombo; QWidget* m_groupEyeInHand;
QComboBox* m_tcpEulerOrderCombo;
QSpinBox* m_tcpRefPoseIndex; // Eye-To-Hand 内联按钮
QDoubleSpinBox* m_tcpWorldRx; QPushButton* m_btnEyeToHandAddRow;
QDoubleSpinBox* m_tcpWorldRy; QPushButton* m_btnEyeToHandDeleteRow;
QDoubleSpinBox* m_tcpWorldRz; QPushButton* m_btnEyeToHandCalib;
QGroupBox* m_tcpOrientationGroup;
QPushButton* m_tcpAddRowBtn; // Eye-In-Hand 内联按钮
QPushButton* m_tcpRemoveRowBtn; QPushButton* m_btnEyeInHandAddRow;
QPushButton* m_btnTCPCalib; QPushButton* m_btnEyeInHandDeleteRow;
QPushButton* m_btnEyeInHandCalib;
// Eye-To-Hand 输入框
QDoubleSpinBox* m_inputEyeX; // TCP 标定相关
QDoubleSpinBox* m_inputEyeY; QWidget* m_groupTCPCalib;
QDoubleSpinBox* m_inputEyeZ; QTableWidget* m_tableTCP;
QDoubleSpinBox* m_inputRobotX; QComboBox* m_tcpModeCombo;
QDoubleSpinBox* m_inputRobotY; QComboBox* m_tcpEulerOrderCombo;
QDoubleSpinBox* m_inputRobotZ; QSpinBox* m_tcpRefPoseIndex;
QPushButton* m_btnEyeToHandAddInput; QDoubleSpinBox* m_tcpWorldRx;
QDoubleSpinBox* m_tcpWorldRy;
// Eye-In-Hand 输入框 QDoubleSpinBox* m_tcpWorldRz;
QDoubleSpinBox* m_inputEndX; QGroupBox* m_tcpOrientationGroup;
QDoubleSpinBox* m_inputEndY; QPushButton* m_tcpAddRowBtn;
QDoubleSpinBox* m_inputEndZ; QPushButton* m_tcpRemoveRowBtn;
QDoubleSpinBox* m_inputEndRoll; QPushButton* m_btnTCPCalib;
QDoubleSpinBox* m_inputEndPitch;
QDoubleSpinBox* m_inputEndYaw; // Eye-To-Hand 输入框
QDoubleSpinBox* m_inputCamX; QDoubleSpinBox* m_inputEyeX;
QDoubleSpinBox* m_inputCamY; QDoubleSpinBox* m_inputEyeY;
QDoubleSpinBox* m_inputCamZ; QDoubleSpinBox* m_inputEyeZ;
QPushButton* m_btnEyeInHandAddInput; QDoubleSpinBox* m_inputRobotX;
QDoubleSpinBox* m_inputRobotY;
// TCP 输入框 QDoubleSpinBox* m_inputRobotZ;
QDoubleSpinBox* m_inputTcpX; QPushButton* m_btnEyeToHandAddInput;
QDoubleSpinBox* m_inputTcpY;
QDoubleSpinBox* m_inputTcpZ; // Eye-In-Hand 输入框
QDoubleSpinBox* m_inputTcpRx; QDoubleSpinBox* m_inputEndX;
QDoubleSpinBox* m_inputTcpRy; QDoubleSpinBox* m_inputEndY;
QDoubleSpinBox* m_inputTcpRz; QDoubleSpinBox* m_inputEndZ;
QPushButton* m_btnTcpAddInput; QDoubleSpinBox* m_inputEndRoll;
}; QDoubleSpinBox* m_inputEndPitch;
QDoubleSpinBox* m_inputEndYaw;
#endif // CALIBDATAWIDGET_H QDoubleSpinBox* m_inputCamX;
QDoubleSpinBox* m_inputCamY;
QDoubleSpinBox* m_inputCamZ;
QPushButton* m_btnEyeInHandAddInput;
// TCP 输入框
QDoubleSpinBox* m_inputTcpX;
QDoubleSpinBox* m_inputTcpY;
QDoubleSpinBox* m_inputTcpZ;
QDoubleSpinBox* m_inputTcpRx;
QDoubleSpinBox* m_inputTcpRy;
QDoubleSpinBox* m_inputTcpRz;
QPushButton* m_btnTcpAddInput;
};
#endif // CALIBDATAWIDGET_H

View File

@ -1,162 +1,172 @@
#ifndef CALIBVIEWMAINWINDOW_H #ifndef CALIBVIEWMAINWINDOW_H
#define CALIBVIEWMAINWINDOW_H #define CALIBVIEWMAINWINDOW_H
#include <QMainWindow> #include <QMainWindow>
#include <QStatusBar> #include <QStatusBar>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QComboBox> #include <QComboBox>
#include <QPushButton> #include <QPushButton>
#include <QTextEdit> #include <QTextEdit>
#include <memory> #include <memory>
#include "IHandEyeCalib.h" #include "IHandEyeCalib.h"
class CalibDataWidget; class CalibDataWidget;
class CalibResultWidget; class CalibResultWidget;
class MainWindow; // RobotView::MainWindow class MainWindow; // RobotView::MainWindow
class VrEyeViewWidget; class VrEyeViewWidget;
/** /**
* @brief * @brief
* HandEyeCalib * HandEyeCalib
*/ */
class CalibViewMainWindow : public QMainWindow class CalibViewMainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CalibViewMainWindow(QWidget* parent = nullptr); explicit CalibViewMainWindow(QWidget* parent = nullptr);
~CalibViewMainWindow() override; ~CalibViewMainWindow() override;
signals: signals:
/** /**
* @brief * @brief
*/ */
void calibrationCompleted(const HECCalibResult& result); void calibrationCompleted(const HECCalibResult& result);
private slots: private slots:
/** /**
* @brief Eye-To-Hand * @brief Eye-To-Hand
*/ */
void onEyeToHandCalib(); void onEyeToHandCalib();
/** /**
* @brief Eye-In-Hand * @brief Eye-In-Hand
*/ */
void onEyeInHandCalib(); void onEyeInHandCalib();
/** /**
* @brief * @brief
*/ */
void onTransformTest(); void onTransformTest();
/** /**
* @brief * @brief
*/ */
void onEulerTest(); void onEulerTest();
/** /**
* @brief TCP * @brief TCP
*/ */
void onTCPCalib(); void onTCPCalib();
/** /**
* @brief * @brief
*/ */
void onClearAll(); void onClearAll();
/** /**
* @brief * @brief
*/ */
void onSaveResult(); void onSaveResult();
/** /**
* @brief * @brief
*/ */
void onLoadResult(); void onLoadResult();
/** /**
* @brief RobotView * @brief
*/ */
void onOpenRobotView(); void onSaveCalibData();
/** /**
* @brief RobotView TCP 姿 * @brief
*/ */
void onRobotTcpPoseReceived(double x, double y, double z, void onLoadCalibData();
double rx, double ry, double rz);
/**
/** * @brief RobotView
* @brief VrEyeView */
*/ void onOpenRobotView();
void onOpenVrEyeView();
/**
/** * @brief RobotView TCP 姿
* @brief VrEyeView */
*/ void onRobotTcpPoseReceived(double x, double y, double z,
void onChessboardDetected(double x, double y, double z, double rx, double ry, double rz);
double rx, double ry, double rz);
/**
private: * @brief VrEyeView
/** */
* @brief void onOpenVrEyeView();
*/
void setupUI(); /**
* @brief VrEyeView
/** */
* @brief void onChessboardDetected(double x, double y, double z,
*/ double rx, double ry, double rz);
void createMenuBar();
private:
/** /**
* @brief * @brief
*/ */
QWidget* createRightPanel(); void setupUI();
/** /**
* @brief * @brief
*/ */
void updateStatusBar(const QString& message); void createMenuBar();
/** /**
* @brief * @brief
*/ */
void appendLog(const QString& message); QWidget* createRightPanel();
// 标定实例 /**
IHandEyeCalib* m_calib; * @brief
*/
// 数据输入控件 void updateStatusBar(const QString& message);
CalibDataWidget* m_dataWidget;
/**
// 结果显示控件 * @brief
CalibResultWidget* m_resultWidget; */
void appendLog(const QString& message);
// 右侧面板 - 坐标变换测试
QDoubleSpinBox* m_sbTransformX; // 标定实例
QDoubleSpinBox* m_sbTransformY; IHandEyeCalib* m_calib;
QDoubleSpinBox* m_sbTransformZ;
QPushButton* m_btnTransform; // 数据输入控件
CalibDataWidget* m_dataWidget;
// 右侧面板 - 欧拉角转换测试
QDoubleSpinBox* m_sbRoll; // 结果显示控件
QDoubleSpinBox* m_sbPitch; CalibResultWidget* m_resultWidget;
QDoubleSpinBox* m_sbYaw;
QComboBox* m_cbEulerOrder; // 右侧面板 - 坐标变换测试
QPushButton* m_btnEulerConvert; QDoubleSpinBox* m_sbTransformX;
QDoubleSpinBox* m_sbTransformY;
// 右侧面板 - 日志 QDoubleSpinBox* m_sbTransformZ;
QTextEdit* m_logEdit; QPushButton* m_btnTransform;
// 当前标定结果 // 右侧面板 - 欧拉角转换测试
HECCalibResult m_currentResult; QDoubleSpinBox* m_sbRoll;
bool m_hasResult; QDoubleSpinBox* m_sbPitch;
QDoubleSpinBox* m_sbYaw;
// RobotView 窗口实例 QComboBox* m_cbEulerOrder;
MainWindow* m_robotView; QPushButton* m_btnEulerConvert;
// VrEyeView 窗口实例 // 右侧面板 - 日志
VrEyeViewWidget* m_vrEyeView; QTextEdit* m_logEdit;
};
// 当前标定结果
#endif // CALIBVIEWMAINWINDOW_H HECCalibResult m_currentResult;
bool m_hasResult;
// RobotView 窗口实例
MainWindow* m_robotView;
// VrEyeView 窗口实例
VrEyeViewWidget* m_vrEyeView;
};
#endif // CALIBVIEWMAINWINDOW_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2
Utils

@ -1 +1 @@
Subproject commit 7071da62403ea703981ffe77fff948266b66fdf3 Subproject commit 8c8dd5a5a26a316dbcd523eddfb8bd56727c62d2