重构相机调平逻辑,增加状态回调功能以优化扫描完成检测,调整UI元素布局。
This commit is contained in:
parent
c9b7ad4642
commit
e4d42c5a72
@ -44,12 +44,18 @@ public:
|
|||||||
void GetCameraListWithNames(std::vector<IVrEyeDevice*>& cameraList, std::vector<QString>& cameraNames);
|
void GetCameraListWithNames(std::vector<IVrEyeDevice*>& cameraList, std::vector<QString>& cameraNames);
|
||||||
bool IsCameraConnected(int index);
|
bool IsCameraConnected(int index);
|
||||||
|
|
||||||
|
// 为所有相机设置状态回调
|
||||||
|
void SetCameraStatusCallback(VzNL_OnNotifyStatusCBEx fNotify, void* param);
|
||||||
|
|
||||||
// 获取配置对象
|
// 获取配置对象
|
||||||
IVrConfig* GetConfig() { return m_vrConfig; }
|
IVrConfig* GetConfig() { return m_vrConfig; }
|
||||||
|
|
||||||
// 实现IVrConfigChangeNotify接口
|
// 实现IVrConfigChangeNotify接口
|
||||||
virtual void OnConfigChanged(const ConfigResult& configResult) override;
|
virtual void OnConfigChanged(const ConfigResult& configResult) override;
|
||||||
|
|
||||||
|
// 静态回调函数,供外部使用
|
||||||
|
static void _StaticCameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 机械臂协议相关方法
|
// 机械臂协议相关方法
|
||||||
int InitRobotProtocol();
|
int InitRobotProtocol();
|
||||||
@ -64,9 +70,6 @@ private:
|
|||||||
// 连接状态检查和更新
|
// 连接状态检查和更新
|
||||||
void CheckAndUpdateWorkStatus();
|
void CheckAndUpdateWorkStatus();
|
||||||
|
|
||||||
// 静态回调函数,用于传递给SDK
|
|
||||||
static void _StaticCameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam);
|
|
||||||
|
|
||||||
// 实例方法,处理回调
|
// 实例方法,处理回调
|
||||||
void _CameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam);
|
void _CameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam);
|
||||||
|
|
||||||
|
|||||||
@ -120,7 +120,12 @@ int GrabBagPresenter::Init()
|
|||||||
nRet = pDevice->InitDevice();
|
nRet = pDevice->InitDevice();
|
||||||
ERR_CODE_RETURN(nRet);
|
ERR_CODE_RETURN(nRet);
|
||||||
|
|
||||||
nRet = pDevice->OpenDevice(configResult.cameraList[0].ip.c_str(), &GrabBagPresenter::_StaticCameraNotify, this);
|
// 先设置状态回调
|
||||||
|
nRet = pDevice->SetStatusCallback(&GrabBagPresenter::_StaticCameraNotify, this);
|
||||||
|
ERR_CODE_RETURN(nRet);
|
||||||
|
|
||||||
|
// 再打开设备
|
||||||
|
nRet = pDevice->OpenDevice(configResult.cameraList[0].ip.c_str());
|
||||||
// 通过回调更新相机1状态
|
// 通过回调更新相机1状态
|
||||||
bool camera1Connected = (SUCCESS == nRet);
|
bool camera1Connected = (SUCCESS == nRet);
|
||||||
if(camera1Connected){
|
if(camera1Connected){
|
||||||
@ -141,15 +146,19 @@ int GrabBagPresenter::Init()
|
|||||||
m_pStatus->OnCamera1StatusChanged(false);
|
m_pStatus->OnCamera1StatusChanged(false);
|
||||||
m_bCameraConnected = false;
|
m_bCameraConnected = false;
|
||||||
}
|
}
|
||||||
ERR_CODE_RETURN(nRet);
|
|
||||||
|
|
||||||
if (cameraCount >= 2) {
|
if (cameraCount >= 2) {
|
||||||
IVrEyeDevice* pDevice = nullptr;
|
IVrEyeDevice* pDevice = nullptr;
|
||||||
IVrEyeDevice::CreateObject(&pDevice);
|
IVrEyeDevice::CreateObject(&pDevice);
|
||||||
nRet = pDevice->InitDevice();
|
nRet = pDevice->InitDevice();
|
||||||
ERR_CODE_RETURN(nRet);
|
ERR_CODE_RETURN(nRet);
|
||||||
|
|
||||||
|
// 先设置状态回调
|
||||||
|
nRet = pDevice->SetStatusCallback(&GrabBagPresenter::_StaticCameraNotify, this);
|
||||||
|
ERR_CODE_RETURN(nRet);
|
||||||
|
|
||||||
// 尝试打开相机2
|
// 尝试打开相机2
|
||||||
nRet = pDevice->OpenDevice(configResult.cameraList[1].ip.c_str(), &GrabBagPresenter::_StaticCameraNotify, this);
|
nRet = pDevice->OpenDevice(configResult.cameraList[1].ip.c_str());
|
||||||
// 通过回调更新相机2状态
|
// 通过回调更新相机2状态
|
||||||
bool camera2Connected = (SUCCESS == nRet);
|
bool camera2Connected = (SUCCESS == nRet);
|
||||||
if(camera2Connected)
|
if(camera2Connected)
|
||||||
@ -167,14 +176,18 @@ int GrabBagPresenter::Init()
|
|||||||
// 如果只有一个相机,则将相机2状态设为未连接
|
// 如果只有一个相机,则将相机2状态设为未连接
|
||||||
m_pStatus->OnCamera2StatusChanged(false);
|
m_pStatus->OnCamera2StatusChanged(false);
|
||||||
}
|
}
|
||||||
ERR_CODE_RETURN(nRet);
|
|
||||||
} else {
|
} else {
|
||||||
IVrEyeDevice* pDevice = nullptr;
|
IVrEyeDevice* pDevice = nullptr;
|
||||||
IVrEyeDevice::CreateObject(&pDevice);
|
IVrEyeDevice::CreateObject(&pDevice);
|
||||||
nRet = pDevice->InitDevice();
|
nRet = pDevice->InitDevice();
|
||||||
ERR_CODE_RETURN(nRet);
|
ERR_CODE_RETURN(nRet);
|
||||||
|
|
||||||
|
// 先设置状态回调
|
||||||
|
nRet = pDevice->SetStatusCallback(&GrabBagPresenter::_StaticCameraNotify, this);
|
||||||
|
ERR_CODE_RETURN(nRet);
|
||||||
|
|
||||||
// 尝试打开相机1
|
// 尝试打开相机1
|
||||||
nRet = pDevice->OpenDevice(nullptr, &GrabBagPresenter::_StaticCameraNotify, this);
|
nRet = pDevice->OpenDevice(nullptr);
|
||||||
// 通过回调更新相机1状态
|
// 通过回调更新相机1状态
|
||||||
bool camera1Connected = (SUCCESS == nRet);
|
bool camera1Connected = (SUCCESS == nRet);
|
||||||
if(camera1Connected)
|
if(camera1Connected)
|
||||||
@ -572,6 +585,18 @@ bool GrabBagPresenter::IsCameraConnected(int index)
|
|||||||
return (pDevice != nullptr);
|
return (pDevice != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 为所有相机设置状态回调
|
||||||
|
void GrabBagPresenter::SetCameraStatusCallback(VzNL_OnNotifyStatusCBEx fNotify, void* param)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_vrEyeDeviceList.size(); i++) {
|
||||||
|
IVrEyeDevice* pDevice = m_vrEyeDeviceList[i];
|
||||||
|
if (pDevice) {
|
||||||
|
pDevice->SetStatusCallback(fNotify, param);
|
||||||
|
LOG_DEBUG("Status callback set for camera %zu\n", i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 静态回调函数实现
|
// 静态回调函数实现
|
||||||
void GrabBagPresenter::_StaticCameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam)
|
void GrabBagPresenter::_StaticCameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam)
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#define GRABBAG_VERSION_STRING "1.0.0"
|
#define GRABBAG_VERSION_STRING "1.0.0"
|
||||||
#define GRABBAG_BUILD_STRING "6"
|
#define GRABBAG_BUILD_STRING "7"
|
||||||
#define GRABBAG_FULL_VERSION_STRING "V1.0.0_6"
|
#define GRABBAG_FULL_VERSION_STRING "V1.0.0_7"
|
||||||
|
|
||||||
// 获取版本信息的便捷函数
|
// 获取版本信息的便捷函数
|
||||||
inline const char* GetGrabBagVersion() {
|
inline const char* GetGrabBagVersion() {
|
||||||
@ -20,3 +20,4 @@ inline const char* GetGrabBagFullVersion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // VERSION_H
|
#endif // VERSION_H
|
||||||
|
|
||||||
|
|||||||
@ -11,14 +11,12 @@
|
|||||||
#include "StyledMessageBox.h"
|
#include "StyledMessageBox.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef LEVEL_DEBUG_MODE
|
|
||||||
#include "LaserDataLoader.h"
|
#include "LaserDataLoader.h"
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#endif
|
|
||||||
|
|
||||||
DialogCameraLevel::DialogCameraLevel(QWidget *parent)
|
DialogCameraLevel::DialogCameraLevel(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
@ -42,6 +40,9 @@ DialogCameraLevel::~DialogCameraLevel()
|
|||||||
// 清理扫描数据缓存
|
// 清理扫描数据缓存
|
||||||
clearScanDataCache();
|
clearScanDataCache();
|
||||||
|
|
||||||
|
// 确保恢复Presenter的状态回调
|
||||||
|
restorePresenterStatusCallback();
|
||||||
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,14 +106,11 @@ void DialogCameraLevel::on_btn_apply_clicked()
|
|||||||
try {
|
try {
|
||||||
// 执行相机调平
|
// 执行相机调平
|
||||||
if (performCameraLeveling()) {
|
if (performCameraLeveling()) {
|
||||||
// StyledMessageBox::information(this, "成功", "相机调平完成!标定结果已保存。");
|
// 调平成功,关闭对话框(这会触发析构函数中的回调恢复)
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
// accept();
|
// accept();
|
||||||
} else {
|
} else {
|
||||||
// 显示失败信息到界面
|
// 显示失败信息到界面
|
||||||
ui->label_level_result->setText("调平失败!\n\n请检查:\n1. 相机连接是否正常\n2. 地面扫描数据是否充足\n3. 扫描区域是否有足够的地面");
|
ui->label_level_result->setText("调平失败!\n\n请检查:\n1. 相机连接是否正常\n2. 地面扫描数据是否充足\n3. 扫描区域是否有足够的地面");
|
||||||
// StyledMessageBox::critical(this, "失败", "相机调平失败!请检查相机连接和地面扫描数据。");
|
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
LOG_ERROR("Camera leveling failed with exception: %s\n", e.what());
|
LOG_ERROR("Camera leveling failed with exception: %s\n", e.what());
|
||||||
@ -135,6 +133,9 @@ bool DialogCameraLevel::performCameraLeveling()
|
|||||||
// 获取选中的相机索引
|
// 获取选中的相机索引
|
||||||
int selectedIndex = ui->combo_camera->currentIndex();
|
int selectedIndex = ui->combo_camera->currentIndex();
|
||||||
|
|
||||||
|
// 1. 设置调平状态回调
|
||||||
|
setLevelingStatusCallback();
|
||||||
|
|
||||||
#ifdef LEVEL_DEBUG_MODE
|
#ifdef LEVEL_DEBUG_MODE
|
||||||
// Debug模式:使用文件对话框选择测试数据
|
// Debug模式:使用文件对话框选择测试数据
|
||||||
LOG_INFO("=== DEBUG MODE ENABLED ===\n");
|
LOG_INFO("=== DEBUG MODE ENABLED ===\n");
|
||||||
@ -160,30 +161,36 @@ bool DialogCameraLevel::performCameraLeveling()
|
|||||||
|
|
||||||
LOG_INFO("Performing camera leveling with camera %d (index %d)\n", selectedIndex + 1, selectedIndex);
|
LOG_INFO("Performing camera leveling with camera %d (index %d)\n", selectedIndex + 1, selectedIndex);
|
||||||
|
|
||||||
// 1. 清空之前的扫描数据
|
// 2. 清空之前的扫描数据
|
||||||
clearScanDataCache();
|
clearScanDataCache();
|
||||||
m_scanCompleted = false;
|
|
||||||
|
|
||||||
// 2. 启动相机扫描地面数据
|
// 3. 启动相机扫描地面数据
|
||||||
if (!startCameraScan(selectedIndex)) {
|
if (!startCameraScan(selectedIndex)) {
|
||||||
LOG_ERROR("Failed to start camera scan for leveling\n");
|
LOG_ERROR("Failed to start camera scan for leveling\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 等待数据收集完成
|
// 4. 等待扫描完成(使用状态回调判断)
|
||||||
LOG_INFO("Collecting ground scan data...\n");
|
LOG_INFO("Collecting ground scan data, waiting for swing finish signal...\n");
|
||||||
int waitTime = 0;
|
int waitTime = 0;
|
||||||
const int maxWaitTime = 5000; // 最大等待5秒
|
const int maxWaitTime = 10000; // 最大等待10秒
|
||||||
const int checkInterval = 100; // 每100ms检查一次
|
const int checkInterval = 100; // 每100ms检查一次
|
||||||
|
|
||||||
while (!m_scanCompleted && waitTime < maxWaitTime) {
|
while (!m_swingFinished && waitTime < maxWaitTime) {
|
||||||
QThread::msleep(checkInterval);
|
QThread::msleep(checkInterval);
|
||||||
QApplication::processEvents(); // 处理UI事件
|
QApplication::processEvents(); // 处理UI事件
|
||||||
waitTime += checkInterval;
|
waitTime += checkInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 停止扫描
|
// 5. 停止扫描
|
||||||
stopCameraScan(selectedIndex);
|
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");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 5. 检查是否收集到足够的数据
|
// 5. 检查是否收集到足够的数据
|
||||||
@ -225,11 +232,14 @@ bool DialogCameraLevel::performCameraLeveling()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearScanDataCache();
|
||||||
LOG_INFO("Camera leveling completed successfully\n");
|
LOG_INFO("Camera leveling completed successfully\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
LOG_ERROR("Exception in performCameraLeveling: %s\n", e.what());
|
LOG_ERROR("Exception in performCameraLeveling: %s\n", e.what());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,6 +340,33 @@ void DialogCameraLevel::StaticDetectionCallback(EVzResultDataType eDataType, SVz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 静态状态回调函数
|
||||||
|
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)
|
void DialogCameraLevel::DetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint)
|
||||||
{
|
{
|
||||||
@ -363,12 +400,6 @@ void DialogCameraLevel::DetectionCallback(EVzResultDataType eDataType, SVzLaserL
|
|||||||
// 将转换后的数据保存到缓存中
|
// 将转换后的数据保存到缓存中
|
||||||
std::lock_guard<std::mutex> lock(m_scanDataMutex);
|
std::lock_guard<std::mutex> lock(m_scanDataMutex);
|
||||||
m_scanDataCache.push_back(laser3DLine);
|
m_scanDataCache.push_back(laser3DLine);
|
||||||
|
|
||||||
// 当收集到足够的数据时,标记扫描完成
|
|
||||||
if (m_scanDataCache.size() >= 50) { // 假设需要至少50条扫描线
|
|
||||||
m_scanCompleted = true;
|
|
||||||
LOG_INFO("Scan completed with %zu lines collected\n", m_scanDataCache.size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调平算法计算
|
// 调平算法计算
|
||||||
@ -571,7 +602,6 @@ bool DialogCameraLevel::loadDebugDataAndSimulateScan(const QString& filePath)
|
|||||||
try {
|
try {
|
||||||
// 清空之前的扫描数据
|
// 清空之前的扫描数据
|
||||||
clearScanDataCache();
|
clearScanDataCache();
|
||||||
m_scanCompleted = false;
|
|
||||||
|
|
||||||
// 使用LaserDataLoader加载测试数据
|
// 使用LaserDataLoader加载测试数据
|
||||||
LaserDataLoader dataLoader;
|
LaserDataLoader dataLoader;
|
||||||
@ -650,7 +680,7 @@ void DialogCameraLevel::simulateScanProcess()
|
|||||||
// 连接定时器信号
|
// 连接定时器信号
|
||||||
connect(simulationTimer, &QTimer::timeout, [this, simulationTimer]() {
|
connect(simulationTimer, &QTimer::timeout, [this, simulationTimer]() {
|
||||||
LOG_INFO("Scan simulation completed\n");
|
LOG_INFO("Scan simulation completed\n");
|
||||||
m_scanCompleted = true;
|
m_swingFinished = true; // Debug模式下模拟摆动完成
|
||||||
|
|
||||||
// 显示调试信息
|
// 显示调试信息
|
||||||
{
|
{
|
||||||
@ -765,3 +795,41 @@ void DialogCameraLevel::checkAndDisplayCalibrationStatus(int cameraIndex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置调平时的状态回调
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复Presenter的状态回调
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复Presenter的状态回调 - 使用GrabBagPresenter的静态回调
|
||||||
|
m_presenter->SetCameraStatusCallback(&GrabBagPresenter::_StaticCameraNotify, m_presenter);
|
||||||
|
|
||||||
|
LOG_INFO("Presenter status callback restored for all cameras\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
#include "VZNL_Types.h"
|
#include "VZNL_Types.h"
|
||||||
|
|
||||||
|
|
||||||
#define LEVEL_DEBUG_MODE
|
// #define LEVEL_DEBUG_MODE
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class DialogCameraLevel;
|
class DialogCameraLevel;
|
||||||
@ -29,8 +29,7 @@ public:
|
|||||||
~DialogCameraLevel();
|
~DialogCameraLevel();
|
||||||
|
|
||||||
// 设置相机列表和presenter
|
// 设置相机列表和presenter
|
||||||
void setCameraList(const std::vector<IVrEyeDevice*>& cameraList,
|
void setCameraList(const std::vector<IVrEyeDevice*>& cameraList, const std::vector<QString>& cameraNames,
|
||||||
const std::vector<QString>& cameraNames,
|
|
||||||
GrabBagPresenter* presenter);
|
GrabBagPresenter* presenter);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@ -49,7 +48,10 @@ private:
|
|||||||
// 扫描数据缓存
|
// 扫描数据缓存
|
||||||
std::vector<SVzNL3DLaserLine> m_scanDataCache;
|
std::vector<SVzNL3DLaserLine> m_scanDataCache;
|
||||||
std::mutex m_scanDataMutex;
|
std::mutex m_scanDataMutex;
|
||||||
bool m_scanCompleted = false;
|
|
||||||
|
// 状态回调相关
|
||||||
|
std::atomic<bool> m_swingFinished = false; // 摆动完成标志,同时表示扫描完成
|
||||||
|
std::atomic<bool> m_callbackRestored = false;
|
||||||
|
|
||||||
// 初始化相机选择框
|
// 初始化相机选择框
|
||||||
void initializeCameraCombo();
|
void initializeCameraCombo();
|
||||||
@ -65,18 +67,24 @@ private:
|
|||||||
static void StaticDetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint, void* pUserData);
|
static void StaticDetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint, void* pUserData);
|
||||||
void DetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint);
|
void DetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint);
|
||||||
|
|
||||||
|
// 状态回调函数
|
||||||
|
static void StaticStatusCallback(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam);
|
||||||
|
void StatusCallback(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam);
|
||||||
|
|
||||||
|
// 设置和恢复状态回调
|
||||||
|
void setLevelingStatusCallback();
|
||||||
|
void restorePresenterStatusCallback();
|
||||||
|
|
||||||
// 处理扫描到的地面数据进行调平计算
|
// 处理扫描到的地面数据进行调平计算
|
||||||
bool calculatePlaneCalibration(double planeCalib[9], double& planeHeight, double invRMatrix[9]);
|
bool calculatePlaneCalibration(double planeCalib[9], double& planeHeight, double invRMatrix[9]);
|
||||||
|
|
||||||
// 清空扫描数据缓存
|
// 清空扫描数据缓存
|
||||||
void clearScanDataCache();
|
void clearScanDataCache();
|
||||||
|
|
||||||
#ifdef LEVEL_DEBUG_MODE
|
|
||||||
// Debug模式方法
|
// Debug模式方法
|
||||||
QString selectDebugDataFile();
|
QString selectDebugDataFile();
|
||||||
bool loadDebugDataAndSimulateScan(const QString& filePath);
|
bool loadDebugDataAndSimulateScan(const QString& filePath);
|
||||||
void simulateScanProcess();
|
void simulateScanProcess();
|
||||||
#endif
|
|
||||||
|
|
||||||
// 更新调平结果显示
|
// 更新调平结果显示
|
||||||
void updateLevelingResults(double planeCalib[9], double planeHeight, double invRMatrix[9]);
|
void updateLevelingResults(double planeCalib[9], double planeHeight, double invRMatrix[9]);
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include <QSystemSemaphore>
|
#include <QSystemSemaphore>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -14,7 +15,52 @@ int main(int argc, char *argv[])
|
|||||||
// 设置应用程序图标
|
// 设置应用程序图标
|
||||||
a.setWindowIcon(QIcon(":/resource/logo.png"));
|
a.setWindowIcon(QIcon(":/resource/logo.png"));
|
||||||
|
|
||||||
|
// 使用应用程序名称作为唯一标识符
|
||||||
|
const QString appKey = "GrabBagApp_SingleInstance_Key";
|
||||||
|
|
||||||
|
// 创建系统信号量,用于同步访问共享内存
|
||||||
|
QSystemSemaphore semaphore(appKey + "_semaphore", 1);
|
||||||
|
semaphore.acquire(); // 获取信号量
|
||||||
|
|
||||||
|
// 创建共享内存对象
|
||||||
|
QSharedMemory sharedMemory(appKey + "_memory");
|
||||||
|
|
||||||
|
bool isRunning = false;
|
||||||
|
|
||||||
|
// 尝试附加到现有的共享内存
|
||||||
|
if (sharedMemory.attach()) {
|
||||||
|
// 如果能够附加,说明已有实例在运行
|
||||||
|
isRunning = true;
|
||||||
|
} else {
|
||||||
|
// 尝试创建新的共享内存
|
||||||
|
if (!sharedMemory.create(1)) {
|
||||||
|
// 创建失败,可能是因为已经存在
|
||||||
|
qDebug() << "Unable to create shared memory segment:" << sharedMemory.errorString();
|
||||||
|
isRunning = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
semaphore.release(); // 释放信号量
|
||||||
|
|
||||||
|
if (isRunning) {
|
||||||
|
// 已有实例在运行,显示提示信息并退出
|
||||||
|
QMessageBox::information(nullptr,
|
||||||
|
QObject::tr("应用程序已运行"),
|
||||||
|
QObject::tr("编织袋拆垛应用程序已经在运行中,请勿重复启动!"),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 没有其他实例运行,正常启动应用程序
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
w.show();
|
w.show();
|
||||||
return a.exec();
|
|
||||||
|
int result = a.exec();
|
||||||
|
|
||||||
|
// 应用程序退出时,清理共享内存
|
||||||
|
if (sharedMemory.isAttached()) {
|
||||||
|
sharedMemory.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
@ -770,7 +770,7 @@ void MainWindow::setupSingleCameraLayout()
|
|||||||
|
|
||||||
|
|
||||||
// 日志: 位于右下方
|
// 日志: 位于右下方
|
||||||
ui->detect_log->setGeometry(1344, 852, 556, 178);
|
ui->detect_log->setGeometry(1344, 850, 556, 176);
|
||||||
|
|
||||||
updateStatusLog(tr("页面布局已调整为单相机模式"));
|
updateStatusLog(tr("页面布局已调整为单相机模式"));
|
||||||
}
|
}
|
||||||
@ -787,16 +787,11 @@ void MainWindow::setupMultiCameraLayout()
|
|||||||
ui->detect_image_2->setGeometry(964, 140, 934, 660);
|
ui->detect_image_2->setGeometry(964, 140, 934, 660);
|
||||||
|
|
||||||
// 设备状态框架: 移动到下方左侧,调整为更高的尺寸以适应纵向排布
|
// 设备状态框架: 移动到下方左侧,调整为更高的尺寸以适应纵向排布
|
||||||
ui->frame_dev->setGeometry(20, 806, 180, 198);
|
ui->frame_dev->setGeometry(20, 806, 180, 200);
|
||||||
|
|
||||||
// 检测结果列表: 移动到下方中间
|
// 检测结果列表: 移动到下方中间
|
||||||
ui->detect_result_list->setGeometry(206, 806, 1380, 220);
|
ui->detect_result_list->setGeometry(206, 806, 1380, 200);
|
||||||
|
|
||||||
// 多相机模式下设置detect_result_list为横向滚动
|
|
||||||
ui->detect_result_list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
ui->detect_result_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
|
||||||
ui->detect_result_list->setFlow(QListView::LeftToRight); // 改为从上到下排列
|
|
||||||
ui->detect_result_list->setWrapping(false); // 禁用换行,实现横向滚动
|
|
||||||
|
|
||||||
// 多相机模式:设置gridSize,gridHeight = 200
|
// 多相机模式:设置gridSize,gridHeight = 200
|
||||||
int gridWidth = 230;
|
int gridWidth = 230;
|
||||||
@ -806,7 +801,7 @@ void MainWindow::setupMultiCameraLayout()
|
|||||||
m_deviceStatusWidget->setCameraCount(2);
|
m_deviceStatusWidget->setCameraCount(2);
|
||||||
|
|
||||||
// 日志: 移动到下方右侧
|
// 日志: 移动到下方右侧
|
||||||
ui->detect_log->setGeometry(1592, 806, 308, 198);
|
ui->detect_log->setGeometry(1592, 806, 308, 200);
|
||||||
|
|
||||||
updateStatusLog(tr("页面布局已调整为多相机模式"));
|
updateStatusLog(tr("页面布局已调整为多相机模式"));
|
||||||
}
|
}
|
||||||
|
|||||||
33
GrabBagPrj/Version/Version.md
Normal file
33
GrabBagPrj/Version/Version.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# 1.0.0.7 2025-06-29
|
||||||
|
1. 增加双相机界面: 通过配置文件config.xml 配置双相机参数,如果没有没有配置,搜索相机进行打开
|
||||||
|
|
||||||
|
配置示例
|
||||||
|
```
|
||||||
|
<Cameras>
|
||||||
|
<Camera name="摄像头1" ip="192.168.1.100" />
|
||||||
|
<Camera name="摄像头2" ip="192.168.1.101" />
|
||||||
|
</Cameras>
|
||||||
|
```
|
||||||
|
2. 相机调平功能, config.xml 有修改。主要涉及到双相机的调平
|
||||||
|
3. 修改log, config的目录。 存储在用户目录下->应用名下
|
||||||
|
4. 增加应用只能启动一个
|
||||||
|
5. 手眼标定矩阵
|
||||||
|
```
|
||||||
|
[clib]
|
||||||
|
clib_0=1
|
||||||
|
clib_1=0
|
||||||
|
clib_2=0
|
||||||
|
clib_3=0
|
||||||
|
clib_4=0
|
||||||
|
clib_5=1
|
||||||
|
clib_6=0
|
||||||
|
clib_7=0
|
||||||
|
clib_8=0
|
||||||
|
clib_9=0
|
||||||
|
clib_10=1
|
||||||
|
clib_11=0
|
||||||
|
clib_12=0
|
||||||
|
clib_13=0
|
||||||
|
clib_14=0
|
||||||
|
clib_15=1
|
||||||
|
```
|
||||||
17
VrConfig/config/clib.ini
Normal file
17
VrConfig/config/clib.ini
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[clib]
|
||||||
|
clib_0=1
|
||||||
|
clib_1=0
|
||||||
|
clib_2=0
|
||||||
|
clib_3=1
|
||||||
|
clib_4=0
|
||||||
|
clib_5=1
|
||||||
|
clib_6=0
|
||||||
|
clib_7=1
|
||||||
|
clib_8=0
|
||||||
|
clib_9=0
|
||||||
|
clib_10=1
|
||||||
|
clib_11=1
|
||||||
|
clib_12=0
|
||||||
|
clib_13=0
|
||||||
|
clib_14=0
|
||||||
|
clib_15=1
|
||||||
@ -18,10 +18,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual int InitDevice() = 0;
|
virtual int InitDevice() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置状态回调函数
|
||||||
|
*/
|
||||||
|
virtual int SetStatusCallback(VzNL_OnNotifyStatusCBEx fNotify, void *param) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open设备
|
* Open设备
|
||||||
*/
|
*/
|
||||||
virtual int OpenDevice(const char* sIP, VzNL_OnNotifyStatusCBEx fNotify, void *param) = 0;
|
virtual int OpenDevice(const char* sIP) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取版本信息
|
* 获取版本信息
|
||||||
|
|||||||
@ -18,7 +18,20 @@ int CVrEyeDevice::InitDevice()
|
|||||||
return CVrEyeCommon::GetInstance()->InitDevice();
|
return CVrEyeCommon::GetInstance()->InitDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CVrEyeDevice::OpenDevice(const char* sIP, VzNL_OnNotifyStatusCBEx fNotify, void *param)
|
int CVrEyeDevice::SetStatusCallback(VzNL_OnNotifyStatusCBEx fNotify, void *param)
|
||||||
|
{
|
||||||
|
// 如果设备已经打开,立即设置回调
|
||||||
|
if (m_pHandle) {
|
||||||
|
VzNL_SetDeviceStatusNotifyEx(m_pHandle, fNotify, param);
|
||||||
|
LOG_DEBUG("Status callback set for opened device\n");
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("Status callback stored, will be set when device opens\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CVrEyeDevice::OpenDevice(const char* sIP)
|
||||||
{
|
{
|
||||||
int nErrCode = SUCCESS;
|
int nErrCode = SUCCESS;
|
||||||
// 搜索设备
|
// 搜索设备
|
||||||
@ -116,8 +129,6 @@ int CVrEyeDevice::OpenDevice(const char* sIP, VzNL_OnNotifyStatusCBEx fNotify, v
|
|||||||
}
|
}
|
||||||
LOG_DEBUG("RGBAutoExposeThres : %f [%d]\n", exposeThres, nnnRet);
|
LOG_DEBUG("RGBAutoExposeThres : %f [%d]\n", exposeThres, nnnRet);
|
||||||
#endif
|
#endif
|
||||||
//设置回调
|
|
||||||
VzNL_SetDeviceStatusNotifyEx(m_pHandle,fNotify, param);
|
|
||||||
|
|
||||||
//获取内部接口类
|
//获取内部接口类
|
||||||
VzNL_QueryDeviceData(m_pHandle, (void **)(&m_pDeviceCore));
|
VzNL_QueryDeviceData(m_pHandle, (void **)(&m_pDeviceCore));
|
||||||
|
|||||||
@ -22,10 +22,15 @@ public:
|
|||||||
// 初始化设备
|
// 初始化设备
|
||||||
int InitDevice() override;
|
int InitDevice() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置状态回调函数
|
||||||
|
*/
|
||||||
|
int SetStatusCallback(VzNL_OnNotifyStatusCBEx fNotify, void *param) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open设备
|
* Open设备
|
||||||
*/
|
*/
|
||||||
int OpenDevice(const char* sIP, VzNL_OnNotifyStatusCBEx fNotify, void *param) override;
|
int OpenDevice(const char* sIP) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取版本信息
|
* 获取版本信息
|
||||||
|
|||||||
@ -100,7 +100,7 @@ static std::string GetLogPath()
|
|||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
return "/sdcard/" + appName + "/Log";
|
return "/sdcard/" + appName + "/Log";
|
||||||
#else
|
#else
|
||||||
return "~/" + appName + "/Log";
|
return appName + "/Log";
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user