706 lines
25 KiB
C++
706 lines
25 KiB
C++
#include "dialogcameralevel.h"
|
|
#include "ui_dialogcameralevel.h"
|
|
#include "WheelMeasurePresenter.h"
|
|
#include "PathManager.h"
|
|
#include "VrLog.h"
|
|
#include "wheelArchHeigthMeasure_Export.h"
|
|
|
|
#include <QThread>
|
|
#include <QApplication>
|
|
#include <QListView>
|
|
#include <cmath>
|
|
#include <mutex>
|
|
#include <vector>
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846
|
|
#endif
|
|
|
|
DialogCameraLevel::DialogCameraLevel(QWidget *parent)
|
|
: QDialog(parent)
|
|
, ui(new Ui::DialogCameraLevel)
|
|
, m_pConfig(nullptr)
|
|
, m_pConfigResult(nullptr)
|
|
, m_currentCameraIndex(-1)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
// 初始化结果显示区域
|
|
ui->label_level_result->setText("请选择相机,然后点击调平按钮\n开始相机调平操作");
|
|
ui->label_level_result->setAlignment(Qt::AlignCenter);
|
|
}
|
|
|
|
DialogCameraLevel::~DialogCameraLevel()
|
|
{
|
|
// 清理扫描数据缓存
|
|
clearScanDataCache();
|
|
|
|
// 确保恢复Presenter的状态回调
|
|
restorePresenterStatusCallback();
|
|
|
|
delete ui;
|
|
}
|
|
|
|
void DialogCameraLevel::setCameraList(const std::vector<std::pair<std::string, IVrEyeDevice*>>& cameraList,
|
|
WheelMeasurePresenter* presenter)
|
|
{
|
|
m_cameraList = cameraList;
|
|
m_presenter = presenter;
|
|
|
|
LOG_INFO("setCameraList called with %zu cameras\n", cameraList.size());
|
|
|
|
// 详细记录每个相机的信息
|
|
for (size_t i = 0; i < cameraList.size(); ++i) {
|
|
const auto& camera = cameraList[i];
|
|
LOG_INFO(" Camera %zu: name='%s', device=%s\n",
|
|
i + 1,
|
|
camera.first.c_str(),
|
|
(camera.second != nullptr ? "connected" : "not connected"));
|
|
}
|
|
|
|
// 初始化/重新初始化相机选择框
|
|
initializeCameraCombo();
|
|
}
|
|
|
|
void DialogCameraLevel::setConfig(IVrWheelMeasureConfig* config, WheelMeasureConfigResult* configResult)
|
|
{
|
|
m_pConfig = config;
|
|
m_pConfigResult = configResult;
|
|
|
|
// 如果相机已经选择,重新加载当前相机的标定状态
|
|
// 修复:打开页面时配置可能在相机列表之后设置,导致初始加载失败
|
|
if (m_currentCameraIndex >= 0 && m_currentCameraIndex < static_cast<int>(m_cameraList.size())) {
|
|
checkAndDisplayCalibrationStatus(m_currentCameraIndex);
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::initializeCameraCombo()
|
|
{
|
|
LOG_INFO("initializeCameraCombo called, camera list size: %zu\n", m_cameraList.size());
|
|
|
|
ui->combo_camera->clear();
|
|
|
|
if (m_cameraList.empty()) {
|
|
ui->combo_camera->setEnabled(false);
|
|
|
|
if (!m_presenter) {
|
|
ui->label_level_result->setText("Presenter未初始化\n无法获取相机列表");
|
|
LOG_ERROR("Presenter is null in initializeCameraCombo\n");
|
|
} else {
|
|
ui->label_level_result->setText("相机列表为空\n\n可能原因:\n1. 配置文件中未配置相机\n2. 系统正在初始化中\n3. 所有相机连接失败");
|
|
LOG_WARNING("Camera list is empty in initializeCameraCombo\n");
|
|
}
|
|
|
|
ui->label_level_result->setAlignment(Qt::AlignCenter);
|
|
} else {
|
|
LOG_INFO("Adding %zu cameras to combo box\n", m_cameraList.size());
|
|
|
|
// 添加所有相机到下拉列表
|
|
for (size_t i = 0; i < m_cameraList.size(); ++i) {
|
|
const auto& camera = m_cameraList[i];
|
|
QString cameraName = QString::fromStdString(camera.first);
|
|
|
|
// 如果相机没有连接,在名称后添加标记
|
|
if (camera.second == nullptr) {
|
|
cameraName += " [未连接]";
|
|
}
|
|
|
|
ui->combo_camera->addItem(cameraName);
|
|
LOG_INFO(" Added camera %zu: %s (device=%s)\n",
|
|
i + 1,
|
|
camera.first.c_str(),
|
|
(camera.second != nullptr ? "OK" : "NULL"));
|
|
}
|
|
ui->combo_camera->setEnabled(true);
|
|
|
|
// 获取默认相机索引
|
|
int defaultCameraIndex = 0;
|
|
if (m_presenter) {
|
|
int presenterDefaultIndex = m_presenter->GetDefaultCameraIndex();
|
|
LOG_INFO("Presenter default camera index (1-based): %d\n", presenterDefaultIndex);
|
|
|
|
if (presenterDefaultIndex > 0 && presenterDefaultIndex <= static_cast<int>(m_cameraList.size())) {
|
|
defaultCameraIndex = presenterDefaultIndex - 1;
|
|
}
|
|
}
|
|
|
|
// 设置默认选中的相机
|
|
if (defaultCameraIndex >= 0 && defaultCameraIndex < static_cast<int>(m_cameraList.size())) {
|
|
ui->combo_camera->setCurrentIndex(defaultCameraIndex);
|
|
m_currentCameraIndex = defaultCameraIndex;
|
|
}
|
|
|
|
// 检查并显示当前选中相机的标定状态
|
|
if (m_currentCameraIndex >= 0) {
|
|
checkAndDisplayCalibrationStatus(m_currentCameraIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::on_btn_apply_clicked()
|
|
{
|
|
ui->label_level_result->setAlignment(Qt::AlignLeft);
|
|
|
|
// 检查是否有可用的相机
|
|
if (m_cameraList.empty()) {
|
|
QMessageBox::warning(this, "错误", "无可用相机设备!");
|
|
return;
|
|
}
|
|
|
|
// 获取选中的相机
|
|
int selectedIndex = ui->combo_camera->currentIndex();
|
|
if (selectedIndex < 0 || selectedIndex >= static_cast<int>(m_cameraList.size())) {
|
|
QMessageBox::warning(this, "错误", "请选择有效的相机!");
|
|
return;
|
|
}
|
|
|
|
// 清空之前的结果显示
|
|
ui->label_level_result->setText("调平计算中,请稍候...");
|
|
|
|
// 显示进度提示
|
|
ui->btn_apply->setEnabled(false);
|
|
QApplication::processEvents();
|
|
|
|
try {
|
|
// 执行相机调平
|
|
if (performCameraLeveling()) {
|
|
// 调平成功
|
|
} else {
|
|
ui->label_level_result->setText("调平失败!\n\n请检查:\n1. 相机连接是否正常\n2. 地面扫描数据是否充足\n3. 扫描区域是否有足够的地面");
|
|
}
|
|
} catch (const std::exception& e) {
|
|
LOG_ERROR("Camera leveling failed with exception: %s\n", e.what());
|
|
QMessageBox::critical(this, "错误", QString("调平过程发生异常:%1").arg(e.what()));
|
|
}
|
|
|
|
// 恢复按钮状态
|
|
ui->btn_apply->setEnabled(true);
|
|
}
|
|
|
|
void DialogCameraLevel::on_btn_cancel_clicked()
|
|
{
|
|
reject();
|
|
}
|
|
|
|
bool DialogCameraLevel::performCameraLeveling()
|
|
{
|
|
try {
|
|
// 获取选中的相机索引
|
|
int selectedIndex = ui->combo_camera->currentIndex();
|
|
|
|
// 先检查索引有效性,再设置回调
|
|
if (selectedIndex < 0 || selectedIndex >= static_cast<int>(m_cameraList.size())) {
|
|
LOG_ERROR("Invalid camera index: %d\n", selectedIndex);
|
|
return false;
|
|
}
|
|
|
|
LOG_INFO("Performing camera leveling with camera %d (index %d)\n", selectedIndex + 1, selectedIndex);
|
|
|
|
// 1. 设置调平状态回调(在索引检查之后)
|
|
setLevelingStatusCallback();
|
|
|
|
// 2. 清空之前的扫描数据
|
|
clearScanDataCache();
|
|
|
|
// 3. 启动相机扫描地面数据
|
|
if (!startCameraScan(selectedIndex)) {
|
|
LOG_ERROR("Failed to start camera scan for leveling\n");
|
|
restorePresenterStatusCallback(); // 恢复回调
|
|
return false;
|
|
}
|
|
|
|
// 4. 等待扫描完成
|
|
LOG_INFO("Collecting ground scan data, waiting for swing finish signal...\n");
|
|
int waitTime = 0;
|
|
const int maxWaitTime = 10000; // 最大等待10秒
|
|
const int checkInterval = 100;
|
|
|
|
while (!m_swingFinished && waitTime < maxWaitTime) {
|
|
QThread::msleep(checkInterval);
|
|
QApplication::processEvents();
|
|
waitTime += checkInterval;
|
|
}
|
|
|
|
// 5. 停止扫描
|
|
stopCameraScan(selectedIndex);
|
|
|
|
if (m_swingFinished) {
|
|
LOG_INFO("Camera swing finished signal received, scan completed\n");
|
|
} else if (waitTime >= maxWaitTime) {
|
|
LOG_WARNING("Timeout waiting for camera swing finish signal\n");
|
|
}
|
|
|
|
// 6. 调用调平算法计算
|
|
double planeCalib[9];
|
|
double planeHeight;
|
|
double invRMatrix[9];
|
|
|
|
if (!calculatePlaneCalibration(planeCalib, planeHeight, invRMatrix)) {
|
|
LOG_ERROR("Failed to calculate plane calibration\n");
|
|
restorePresenterStatusCallback(); // 恢复回调
|
|
return false;
|
|
}
|
|
|
|
LOG_INFO("Camera leveling calculation completed\n");
|
|
|
|
// 7. 更新界面显示
|
|
updateLevelingResults(planeCalib, planeHeight, invRMatrix);
|
|
|
|
// 8. 保存结果到配置
|
|
int cameraIndex = m_currentCameraIndex + 1; // 转换为1-based索引
|
|
QString cameraName;
|
|
|
|
if (m_currentCameraIndex >= 0 && m_currentCameraIndex < static_cast<int>(m_cameraList.size())) {
|
|
cameraName = QString::fromStdString(m_cameraList[m_currentCameraIndex].first);
|
|
} else {
|
|
cameraName = QString("Camera_%1").arg(cameraIndex);
|
|
}
|
|
|
|
if (!saveLevelingResults(planeCalib, planeHeight, invRMatrix, cameraIndex, cameraName)) {
|
|
LOG_ERROR("Failed to save leveling results\n");
|
|
restorePresenterStatusCallback(); // 恢复回调
|
|
return false;
|
|
}
|
|
|
|
clearScanDataCache();
|
|
|
|
// 9. 调平完成后恢复回调
|
|
restorePresenterStatusCallback();
|
|
|
|
LOG_INFO("Camera leveling completed successfully\n");
|
|
|
|
return true;
|
|
|
|
} catch (const std::exception& e) {
|
|
LOG_ERROR("Exception in performCameraLeveling: %s\n", e.what());
|
|
restorePresenterStatusCallback(); // 异常时也恢复回调
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::updateLevelingResults(double planeCalib[9], double planeHeight, double invRMatrix[9])
|
|
{
|
|
// 构建显示文本
|
|
QString resultText;
|
|
|
|
resultText += QString("地面高度: %1 mm\n").arg(QString::number(planeHeight, 'f', 2));
|
|
|
|
// 调平矩阵
|
|
resultText += QString("调平矩阵:\n");
|
|
for (int i = 0; i < 3; i++) {
|
|
resultText += QString("[%1, %2, %3]\n")
|
|
.arg(QString::number(planeCalib[i*3], 'f', 4))
|
|
.arg(QString::number(planeCalib[i*3+1], 'f', 4))
|
|
.arg(QString::number(planeCalib[i*3+2], 'f', 4));
|
|
}
|
|
|
|
resultText += QString("逆旋转矩阵:\n");
|
|
for (int i = 0; i < 3; i++) {
|
|
resultText += QString("[%1, %2, %3]\n")
|
|
.arg(QString::number(invRMatrix[i*3], 'f', 4))
|
|
.arg(QString::number(invRMatrix[i*3+1], 'f', 4))
|
|
.arg(QString::number(invRMatrix[i*3+2], 'f', 4));
|
|
}
|
|
|
|
ui->label_level_result->setText(resultText);
|
|
ui->label_level_result->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
|
}
|
|
|
|
bool DialogCameraLevel::startCameraScan(int cameraIndex)
|
|
{
|
|
if (cameraIndex < 0 || cameraIndex >= static_cast<int>(m_cameraList.size())) {
|
|
LOG_ERROR("Invalid camera index for scan: %d\n", cameraIndex);
|
|
return false;
|
|
}
|
|
|
|
IVrEyeDevice* camera = m_cameraList[cameraIndex].second;
|
|
if (!camera) {
|
|
LOG_ERROR("Camera device is null at index: %d\n", cameraIndex);
|
|
return false;
|
|
}
|
|
|
|
// 启动相机检测
|
|
int result = camera->StartDetect(&DialogCameraLevel::StaticDetectionCallback, keResultDataType_Position, this);
|
|
if (result != 0) {
|
|
LOG_ERROR("Failed to start camera detection: %d\n", result);
|
|
return false;
|
|
}
|
|
|
|
LOG_INFO("Camera scan started successfully for camera index: %d\n", cameraIndex);
|
|
return true;
|
|
}
|
|
|
|
bool DialogCameraLevel::stopCameraScan(int cameraIndex)
|
|
{
|
|
if (cameraIndex < 0 || cameraIndex >= static_cast<int>(m_cameraList.size())) {
|
|
LOG_ERROR("Invalid camera index for stop scan: %d\n", cameraIndex);
|
|
return false;
|
|
}
|
|
|
|
IVrEyeDevice* camera = m_cameraList[cameraIndex].second;
|
|
if (!camera) {
|
|
LOG_ERROR("Camera device is null at index: %d\n", cameraIndex);
|
|
return false;
|
|
}
|
|
|
|
int result = camera->StopDetect();
|
|
if (result != 0) {
|
|
LOG_WARNING("Failed to stop camera detection, error: %d\n", result);
|
|
return false;
|
|
}
|
|
|
|
LOG_INFO("Camera scan stopped successfully for camera index: %d\n", cameraIndex);
|
|
return true;
|
|
}
|
|
|
|
void DialogCameraLevel::StaticDetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint, void* pUserData)
|
|
{
|
|
DialogCameraLevel* pThis = reinterpret_cast<DialogCameraLevel*>(pUserData);
|
|
if (pThis && pLaserLinePoint) {
|
|
pThis->DetectionCallback(eDataType, pLaserLinePoint);
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::StaticStatusCallback(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam)
|
|
{
|
|
DialogCameraLevel* pThis = reinterpret_cast<DialogCameraLevel*>(pInfoParam);
|
|
if (pThis) {
|
|
pThis->StatusCallback(eStatus, pExtData, nDataLength, pInfoParam);
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::StatusCallback(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam)
|
|
{
|
|
LOG_DEBUG("[Leveling Status Callback] received: status=%d\n", (int)eStatus);
|
|
|
|
switch (eStatus) {
|
|
case EVzDeviceWorkStatus::keDeviceWorkStatus_Device_Swing_Finish:
|
|
{
|
|
LOG_INFO("[Leveling Status Callback] Camera swing finished, scan completed\n");
|
|
m_swingFinished = true;
|
|
break;
|
|
}
|
|
default:
|
|
LOG_DEBUG("[Leveling Status Callback] Other status: %d\n", (int)eStatus);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::DetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint)
|
|
{
|
|
if (!pLaserLinePoint) {
|
|
LOG_WARNING("[Leveling Callback] pLaserLinePoint is null\n");
|
|
return;
|
|
}
|
|
|
|
if (pLaserLinePoint->nPointCount <= 0) {
|
|
LOG_WARNING("[Leveling Callback] Point count is zero or negative: %d\n", pLaserLinePoint->nPointCount);
|
|
return;
|
|
}
|
|
|
|
if (!pLaserLinePoint->p3DPoint) {
|
|
LOG_WARNING("[Leveling Callback] p3DPoint is null\n");
|
|
return;
|
|
}
|
|
|
|
// 将数据添加到缓存
|
|
std::vector<SVzNL3DPosition> lineData;
|
|
lineData.reserve(pLaserLinePoint->nPointCount);
|
|
|
|
// p3DPoint 是 void*,需要转换为 SVzNL3DPosition*
|
|
SVzNL3DPosition* p3DPoints = reinterpret_cast<SVzNL3DPosition*>(pLaserLinePoint->p3DPoint);
|
|
for (int i = 0; i < pLaserLinePoint->nPointCount; ++i) {
|
|
lineData.push_back(p3DPoints[i]);
|
|
}
|
|
|
|
std::lock_guard<std::mutex> lock(m_scanDataMutex);
|
|
m_scanDataCache.push_back(std::move(lineData));
|
|
}
|
|
|
|
bool DialogCameraLevel::calculatePlaneCalibration(double planeCalib[9], double& planeHeight, double invRMatrix[9])
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_scanDataMutex);
|
|
|
|
if (m_scanDataCache.empty()) {
|
|
LOG_ERROR("No scan data available for plane calibration\n");
|
|
return false;
|
|
}
|
|
|
|
LOG_INFO("Calculating plane calibration from %zu scan lines\n", m_scanDataCache.size());
|
|
|
|
try {
|
|
// 调用 wheelArchHeigthMeasure SDK 的调平算法
|
|
SSG_planeCalibPara calibResult = wd_horizonCamera_getGroundCalibPara(m_scanDataCache);
|
|
|
|
// 复制调平矩阵
|
|
for (int i = 0; i < 9; i++) {
|
|
planeCalib[i] = calibResult.planeCalib[i];
|
|
invRMatrix[i] = calibResult.invRMatrix[i];
|
|
}
|
|
planeHeight = calibResult.planeHeight;
|
|
|
|
LOG_INFO("Plane calibration calculated successfully\n");
|
|
LOG_INFO(" planeHeight: %.3f\n", planeHeight);
|
|
LOG_INFO(" planeCalib: [%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f]\n",
|
|
planeCalib[0], planeCalib[1], planeCalib[2],
|
|
planeCalib[3], planeCalib[4], planeCalib[5],
|
|
planeCalib[6], planeCalib[7], planeCalib[8]);
|
|
LOG_INFO(" invRMatrix: [%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f]\n",
|
|
invRMatrix[0], invRMatrix[1], invRMatrix[2],
|
|
invRMatrix[3], invRMatrix[4], invRMatrix[5],
|
|
invRMatrix[6], invRMatrix[7], invRMatrix[8]);
|
|
|
|
return true;
|
|
|
|
} catch (const std::exception& e) {
|
|
LOG_ERROR("Exception in calculatePlaneCalibration: %s\n", e.what());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::clearScanDataCache()
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_scanDataMutex);
|
|
|
|
LOG_DEBUG("Clearing scan data cache, current size: %zu\n", m_scanDataCache.size());
|
|
m_scanDataCache.clear();
|
|
LOG_DEBUG("Scan data cache cleared successfully\n");
|
|
}
|
|
|
|
bool DialogCameraLevel::saveLevelingResults(double planeCalib[9], double planeHeight, double invRMatrix[9],
|
|
int cameraIndex, const QString& cameraName)
|
|
{
|
|
try {
|
|
if (!m_pConfig || !m_pConfigResult) {
|
|
LOG_ERROR("Config is null, cannot save leveling results\n");
|
|
return false;
|
|
}
|
|
|
|
if (cameraIndex <= 0) {
|
|
LOG_ERROR("Invalid camera index: %d\n", cameraIndex);
|
|
return false;
|
|
}
|
|
|
|
if (cameraName.isEmpty()) {
|
|
LOG_ERROR("Camera name is empty\n");
|
|
return false;
|
|
}
|
|
|
|
// 获取UI中的误差补偿值
|
|
double errorCompensation = ui->edit_error_compensation->text().toDouble();
|
|
|
|
// 创建或更新相机调平参数
|
|
WheelCameraPlaneCalibParam cameraParam;
|
|
cameraParam.cameraIndex = cameraIndex;
|
|
cameraParam.cameraName = cameraName.toStdString();
|
|
cameraParam.planeHeight = planeHeight;
|
|
cameraParam.isCalibrated = true;
|
|
cameraParam.errorCompensation = errorCompensation;
|
|
|
|
// 复制校准矩阵
|
|
for (int i = 0; i < 9; i++) {
|
|
cameraParam.planeCalib[i] = planeCalib[i];
|
|
cameraParam.invRMatrix[i] = invRMatrix[i];
|
|
}
|
|
|
|
// 查找是否已有该相机的调平参数
|
|
bool found = false;
|
|
for (auto& param : m_pConfigResult->planeCalibParams) {
|
|
if (param.cameraIndex == cameraIndex) {
|
|
param = cameraParam;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
m_pConfigResult->planeCalibParams.push_back(cameraParam);
|
|
}
|
|
|
|
// 保存配置
|
|
QString configPath = PathManager::GetInstance().GetConfigFilePath();
|
|
bool saveResult = m_pConfig->SaveConfig(configPath.toStdString(), *m_pConfigResult);
|
|
if (!saveResult) {
|
|
LOG_ERROR("Failed to save config with leveling results\n");
|
|
return false;
|
|
}
|
|
|
|
LOG_INFO("Leveling results saved successfully for camera %d (%s)\n",
|
|
cameraIndex, cameraName.toUtf8().constData());
|
|
LOG_INFO("Plane height: %.3f, Error compensation: %.2f\n", planeHeight, errorCompensation);
|
|
|
|
return true;
|
|
|
|
} catch (const std::exception& e) {
|
|
LOG_ERROR("Exception in saveLevelingResults: %s\n", e.what());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool DialogCameraLevel::loadCameraCalibrationData(int cameraIndex, const QString& cameraName,
|
|
double planeCalib[9], double& planeHeight, double invRMatrix[9])
|
|
{
|
|
try {
|
|
if (!m_pConfigResult) {
|
|
LOG_ERROR("Config result is null, cannot load calibration data\n");
|
|
return false;
|
|
}
|
|
|
|
// 查找对应相机的调平参数
|
|
for (const auto& param : m_pConfigResult->planeCalibParams) {
|
|
if (param.cameraIndex == cameraIndex && param.isCalibrated) {
|
|
for (int i = 0; i < 9; i++) {
|
|
planeCalib[i] = param.planeCalib[i];
|
|
invRMatrix[i] = param.invRMatrix[i];
|
|
}
|
|
planeHeight = param.planeHeight;
|
|
|
|
// 加载该相机的误差补偿值到UI
|
|
ui->edit_error_compensation->setText(QString::number(param.errorCompensation, 'f', 1));
|
|
|
|
LOG_INFO("Calibration data loaded successfully for camera %d (%s)\n",
|
|
cameraIndex, cameraName.toUtf8().constData());
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// 没有找到标定数据时,设置默认误差补偿值
|
|
ui->edit_error_compensation->setText(QString::number(-5.0, 'f', 1));
|
|
|
|
LOG_INFO("No calibration data found for camera %d (%s)\n",
|
|
cameraIndex, cameraName.toUtf8().constData());
|
|
return false;
|
|
|
|
} catch (const std::exception& e) {
|
|
LOG_ERROR("Exception in loadCameraCalibrationData: %s\n", e.what());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::checkAndDisplayCalibrationStatus(int cameraIndex)
|
|
{
|
|
if (cameraIndex < 0 || cameraIndex >= static_cast<int>(m_cameraList.size())) {
|
|
LOG_WARNING("Invalid camera index for status check: %d\n", cameraIndex);
|
|
ui->label_level_result->setText("无效的相机索引");
|
|
ui->label_level_result->setAlignment(Qt::AlignCenter);
|
|
return;
|
|
}
|
|
|
|
QString cameraName = QString::fromStdString(m_cameraList[cameraIndex].first);
|
|
int configCameraIndex = cameraIndex + 1;
|
|
|
|
double planeCalib[9];
|
|
double planeHeight;
|
|
double invRMatrix[9];
|
|
|
|
if (loadCameraCalibrationData(configCameraIndex, cameraName, planeCalib, planeHeight, invRMatrix)) {
|
|
// 有标定数据,显示
|
|
LOG_INFO("Displaying existing calibration data for camera %s\n", cameraName.toUtf8().constData());
|
|
updateLevelingResults(planeCalib, planeHeight, invRMatrix);
|
|
} else {
|
|
// 没有标定数据
|
|
LOG_INFO("No calibration data found for camera %s\n", cameraName.toUtf8().constData());
|
|
ui->label_level_result->setText(QString("相机: %1\n\n请点击调平按钮开始调平操作").arg(cameraName));
|
|
ui->label_level_result->setAlignment(Qt::AlignCenter);
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::on_combo_camera_currentIndexChanged(int index)
|
|
{
|
|
m_currentCameraIndex = index;
|
|
|
|
if (index >= 0 && index < static_cast<int>(m_cameraList.size())) {
|
|
LOG_INFO("Camera selection changed to index: %d (%s)\n", index,
|
|
QString::fromStdString(m_cameraList[index].first).toUtf8().constData());
|
|
|
|
checkAndDisplayCalibrationStatus(m_currentCameraIndex);
|
|
} else {
|
|
LOG_WARNING("Invalid camera index selected: %d\n", index);
|
|
ui->label_level_result->setText("无效的相机选择");
|
|
ui->label_level_result->setAlignment(Qt::AlignCenter);
|
|
}
|
|
}
|
|
|
|
void DialogCameraLevel::setLevelingStatusCallback()
|
|
{
|
|
if (!m_presenter) {
|
|
LOG_ERROR("Presenter is null, cannot set leveling status callback\n");
|
|
return;
|
|
}
|
|
|
|
m_presenter->SetCameraStatusCallback(&DialogCameraLevel::StaticStatusCallback, this);
|
|
|
|
m_swingFinished = false;
|
|
m_callbackRestored = false;
|
|
|
|
LOG_INFO("Leveling status callback set for all cameras\n");
|
|
}
|
|
|
|
void DialogCameraLevel::restorePresenterStatusCallback()
|
|
{
|
|
if (m_callbackRestored.exchange(true)) {
|
|
LOG_DEBUG("Presenter status callback already restored, skipping\n");
|
|
return;
|
|
}
|
|
|
|
if (!m_presenter) {
|
|
LOG_ERROR("Presenter is null, cannot restore status callback\n");
|
|
return;
|
|
}
|
|
|
|
m_presenter->SetCameraStatusCallback(&WheelMeasurePresenter::_StaticCameraNotify, m_presenter);
|
|
|
|
LOG_INFO("Presenter status callback restored for all cameras\n");
|
|
}
|
|
|
|
void DialogCameraLevel::on_btn_save_compensation_clicked()
|
|
{
|
|
// 保存误差补偿值到当前相机的调平参数
|
|
if (!m_pConfig || !m_pConfigResult) {
|
|
LOG_ERROR("Config is null, cannot save error compensation\n");
|
|
return;
|
|
}
|
|
|
|
if (m_currentCameraIndex < 0 || m_currentCameraIndex >= static_cast<int>(m_cameraList.size())) {
|
|
LOG_WARNING("Invalid camera index: %d\n", m_currentCameraIndex);
|
|
return;
|
|
}
|
|
|
|
// 获取UI中的误差补偿值
|
|
double errorCompensation = ui->edit_error_compensation->text().toDouble();
|
|
int cameraIndex = m_currentCameraIndex + 1; // 转换为1-based索引
|
|
QString cameraName = QString::fromStdString(m_cameraList[m_currentCameraIndex].first);
|
|
|
|
LOG_INFO("Saving error compensation for camera %d (%s): %.2f\n",
|
|
cameraIndex, cameraName.toUtf8().constData(), errorCompensation);
|
|
|
|
// 查找或创建相机调平参数
|
|
bool found = false;
|
|
for (auto& param : m_pConfigResult->planeCalibParams) {
|
|
if (param.cameraIndex == cameraIndex) {
|
|
param.errorCompensation = errorCompensation;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 如果没有找到现有记录,创建一个新的(仅包含误差补偿,其他值为默认)
|
|
if (!found) {
|
|
WheelCameraPlaneCalibParam newParam;
|
|
newParam.cameraIndex = cameraIndex;
|
|
newParam.cameraName = cameraName.toStdString();
|
|
newParam.errorCompensation = errorCompensation;
|
|
newParam.isCalibrated = false; // 尚未标定
|
|
m_pConfigResult->planeCalibParams.push_back(newParam);
|
|
}
|
|
|
|
// 保存配置到文件
|
|
QString configPath = PathManager::GetInstance().GetConfigFilePath();
|
|
bool saveResult = m_pConfig->SaveConfig(configPath.toStdString(), *m_pConfigResult);
|
|
if (saveResult) {
|
|
LOG_INFO("Error compensation saved successfully for camera %d: %.2f\n", cameraIndex, errorCompensation);
|
|
} else {
|
|
LOG_ERROR("Failed to save error compensation\n");
|
|
}
|
|
}
|