手眼标定

This commit is contained in:
yiyi 2026-03-23 09:17:04 +08:00
parent 78d860a2e6
commit 98d1efa5ef
3 changed files with 74 additions and 18 deletions

View File

@ -1,7 +1,7 @@
# CalibView - 手眼标定工具
QT += core gui widgets
CONFIG += c++17 console
CONFIG += c++17 #console
CONFIG -= app_bundle
# Windows平台UTF-8编码支持

View File

@ -36,10 +36,20 @@ signals:
private slots:
/**
* @brief Eye-To-Hand
* @brief Eye-To-Hand
*/
void onEyeToHandCalib();
/**
* @brief Eye-To-Hand -
*/
void onEyeToHandCalibSimple();
/**
* @brief Eye-To-Hand 姿 - Park算法
*/
void onEyeToHandCalibWithPose();
/**
* @brief Eye-In-Hand
*/

View File

@ -48,7 +48,7 @@ CalibViewMainWindow::CalibViewMainWindow(QWidget* parent)
createMenuBar();
SpinBoxPasteHelper::install(this);
setWindowTitle("CalibView - 手眼标定工具");
setWindowTitle("CalibView - 手眼标定工具 - 1.0.0");
resize(1400, 700);
updateStatusBar("就绪");
@ -303,10 +303,61 @@ void CalibViewMainWindow::onEyeToHandCalib()
return;
}
// 使用完整位姿方法Park 方法)
QMessageBox msgBox(this);
msgBox.setWindowTitle("选择标定方法");
msgBox.setText("请选择 Eye-To-Hand 标定方法:");
QPushButton* simpleBtn = msgBox.addButton("简单方法 (仅位置)", QMessageBox::ActionRole);
QPushButton* poseBtn = msgBox.addButton("完整位姿方法 (Park算法)", QMessageBox::ActionRole);
QPushButton* cancelBtn = msgBox.addButton("取消", QMessageBox::RejectRole);
msgBox.exec();
if (msgBox.clickedButton() == cancelBtn) {
return;
}
if (msgBox.clickedButton() == simpleBtn) {
onEyeToHandCalibSimple();
} else if (msgBox.clickedButton() == poseBtn) {
onEyeToHandCalibWithPose();
}
}
void CalibViewMainWindow::onEyeToHandCalibSimple()
{
appendLog("开始 Eye-To-Hand 标定(简单方法 - 仅位置)...");
std::vector<HECPoint3D> eyePoints;
std::vector<HECPoint3D> robotPoints;
m_dataWidget->getEyeToHandData(eyePoints, robotPoints);
if (eyePoints.size() < 3) {
QMessageBox::warning(this, "警告", "至少需要3组数据进行标定");
return;
}
appendLog(QString("输入数据组数: %1").arg(eyePoints.size()));
appendLog("使用 SVD 分解方法,仅利用位置信息");
int ret = m_calib->CalculateRT(eyePoints, robotPoints, m_currentResult);
if (ret == 0) {
m_hasResult = true;
m_resultWidget->showCalibResult(m_currentResult);
appendLog(QString("标定成功,误差: %1 mm")
.arg(m_currentResult.error, 0, 'f', 4));
updateStatusBar("Eye-To-Hand 标定完成(简单方法)");
emit calibrationCompleted(m_currentResult);
} else {
appendLog(QString("标定失败,错误码: %1").arg(ret));
QMessageBox::critical(this, "错误", QString("标定失败,错误码: %1").arg(ret));
}
}
void CalibViewMainWindow::onEyeToHandCalibWithPose()
{
appendLog("开始 Eye-To-Hand 标定(完整位姿方法 - Park 算法)...");
// 从 CalibDataWidget 获取完整位姿数据
std::vector<HECEyeToHandData> calibData;
m_dataWidget->getEyeToHandPoseData(calibData);
@ -317,7 +368,6 @@ void CalibViewMainWindow::onEyeToHandCalib()
return;
}
// 获取欧拉角顺序
HECEulerOrder eulerOrder = m_dataWidget->getEulerOrder();
QString eulerOrderStr;
switch (eulerOrder) {
@ -572,12 +622,18 @@ void CalibViewMainWindow::onSaveResult()
// [CommInfo]
ini.beginGroup("CommInfo");
ini.setValue("sCalibTime", QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));
ini.setValue("dError", m_currentResult.error);
ini.setValue("nMaxMaxMatrixNum", 8);
ini.setValue("nExistMatrixNum", 1);
ini.endGroup();
// [CalibMatrixInfo_0] - 4x4 齐次矩阵
ini.beginGroup("CalibMatrixInfo_0");
ini.setValue("sCalibTime", QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));
ini.setValue("nCalibPosIdx", 0);
ini.setValue("nCalibType", 0);
ini.setValue("nCalibMode", 0);
ini.setValue("sCalibPosName", 0);
ini.setValue("dError", m_currentResult.error);
// 第0行: R[0,0] R[0,1] R[0,2] Tx
ini.setValue("dCalibMatrix_0", m_currentResult.R.data[0]);
ini.setValue("dCalibMatrix_1", m_currentResult.R.data[1]);
@ -600,16 +656,6 @@ void CalibViewMainWindow::onSaveResult()
ini.setValue("dCalibMatrix_15", 1.0);
ini.endGroup();
// [CenterInfo] - 质心
ini.beginGroup("CenterInfo");
ini.setValue("dCenterEyeX", m_currentResult.centerEye.x);
ini.setValue("dCenterEyeY", m_currentResult.centerEye.y);
ini.setValue("dCenterEyeZ", m_currentResult.centerEye.z);
ini.setValue("dCenterRobotX", m_currentResult.centerRobot.x);
ini.setValue("dCenterRobotY", m_currentResult.centerRobot.y);
ini.setValue("dCenterRobotZ", m_currentResult.centerRobot.z);
ini.endGroup();
appendLog(QString("结果已保存到: %1").arg(fileName));
updateStatusBar("结果已保存");
}