From 953921c684c2eeab6d41bbe925d79da678ebc465 Mon Sep 17 00:00:00 2001 From: Ben <987807597@qq.com> Date: Sun, 23 Aug 2026 11:59:11 +0800 Subject: [PATCH] fix: stop point-cloud wait on SDK auto-stop --- src/VizumCamera.cpp | 116 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 14 deletions(-) diff --git a/src/VizumCamera.cpp b/src/VizumCamera.cpp index c164a2b..23f79c0 100755 --- a/src/VizumCamera.cpp +++ b/src/VizumCamera.cpp @@ -78,6 +78,7 @@ struct VizumCamera::Impl { std::mutex scanLineMutex; std::atomic autoDetectRunning{false}; std::atomic isPaused{true}; + std::atomic scanCompletionStatus{0}; PointCloud accumulatedCloud; }; @@ -99,11 +100,27 @@ struct VizumCamera::Impl { #define m_scanLineMutex m_impl->scanLineMutex #define m_autoDetectRunning m_impl->autoDetectRunning #define m_isPaused m_impl->isPaused +#define m_scanCompletionStatus m_impl->scanCompletionStatus #define m_accumulatedCloud m_impl->accumulatedCloud #ifdef ENABLE_VIZUM_CAMERA namespace { +const char* DeviceStatusName(int status) +{ + switch (static_cast(status)) { + case keDeviceWorkStatusUnknown: return "Unknown"; + case keDeviceWorkStatus_Eye_Comming: return "Eye_Comming"; + case keDeviceWorkStatus_Eye_Reconnect: return "Eye_Reconnect"; + case keDeviceWorkStatus_Working: return "Working"; + case keDeviceWorkStatus_Offline: return "Offline"; + case keDeviceWorkStatus_Device_Swing_Finish: return "Device_Swing_Finish"; + case keDeviceWorkStatus_Device_Auto_Stop: return "Device_Auto_Stop"; + case keDeviceWorkStatus_Device_Swing_Running: return "Device_Swing_Running"; + default: return "Other"; + } +} + void AutoOutputLaserLineExCB(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint, void* pParam) @@ -144,19 +161,40 @@ void VizumCamera::HandleAutoOutputLaserLine(int dataType, void* laserLinePoint) void VizumCamera::HandleDeviceStatusChange(int status) { #ifdef ENABLE_VIZUM_CAMERA - LOG_INFO("[VizumCamera] Device status changed: {}", status); + const char* statusName = DeviceStatusName(status); + LOG_INFO("[VizumCamera] Device status changed: {} ({})", statusName, status); + + const bool completesScan = + status == static_cast(keDeviceWorkStatus_Device_Swing_Finish) + || status == static_cast(keDeviceWorkStatus_Device_Auto_Stop); + if (completesScan) { + if (!m_autoDetectRunning.load()) { + LOG_INFO("[VizumCamera] Completion status {} ({}) received outside an active " + "scan wait; ignored", + statusName, status); + return; + } + size_t scanLines = 0; + size_t validPoints = 0; + { + std::lock_guard lock(m_scanLineMutex); + scanLines = m_accumulatedScanLines.size(); + validPoints = m_accumulatedCloud.points.size(); + } + m_scanCompletionStatus = status; + LOG_INFO("[VizumCamera] Scan completion status received: {} ({}); " + "releasing scan wait, scan lines={}, valid points={}", + statusName, status, scanLines, validPoints); + m_isPaused = true; + return; + } if (status == static_cast(keDeviceWorkStatus_Offline)) { LOG_WARN("[VizumCamera] Camera went offline"); - } else if (status == static_cast(keDeviceWorkStatus_Device_Swing_Finish)) { - LOG_INFO("[VizumCamera] Camera swing finished - setting m_isPaused=true"); - m_isPaused = true; } else if (status == static_cast(keDeviceWorkStatus_Device_Swing_Running)) { LOG_INFO("[VizumCamera] Camera swing motor started running"); } else if (status == static_cast(keDeviceWorkStatus_Eye_Reconnect)) { LOG_INFO("[VizumCamera] Camera reconnected"); - } else if (status == static_cast(keDeviceWorkStatus_Device_Auto_Stop)) { - LOG_INFO("[VizumCamera] Device auto stop signal received"); } #else (void)status; @@ -539,8 +577,20 @@ bool VizumCamera::Connect(const std::string& ipAddress) return false; } - // 设置设备状态回调 - VzNL_SetDeviceStatusNotify(m_deviceHandle, &DeviceStatusCB, this); + // 设置设备状态回调。静态扫描以 Device_Auto_Stop 作为官方完成信号,注册失败不可静默继续。 + const int statusNotifyResult = VzNL_SetDeviceStatusNotify(m_deviceHandle, &DeviceStatusCB, this); + if (statusNotifyResult != 0) { + char statusErrorMsg[256] = {0}; + VzNL_GetErrorInfo(statusNotifyResult, statusErrorMsg); + LOG_ERROR("[VizumCamera] Failed to register device status callback: {} (error code: {})", + statusErrorMsg, statusNotifyResult); + VzNL_CloseDevice(m_deviceHandle); + m_deviceHandle = nullptr; + m_ipAddress.clear(); + return false; + } + LOG_INFO("[VizumCamera] Device status callback registered; scan completion events: " + "Device_Auto_Stop or Device_Swing_Finish"); // OpenDevice 之后立即设置图像输出格式(在此之前设置对本次连接无效) VzNL_SetOutputImageFormat(keVzNLImageType_BGR888); @@ -948,12 +998,15 @@ bool VizumCamera::CapturePointCloudWithAutoDetect(PointCloud& pointCloud, int ti } // 3. 启动自动检测模式(与VznlCamera::StartAutoDetect一致) + m_scanCompletionStatus = 0; m_isPaused = false; + m_autoDetectRunning = true; LOG_INFO("[VizumCamera] Step 2: Starting AutoDetectEx..."); result = VzNL_StartAutoDetectEx(m_deviceHandle, keResultDataType_PointXYZRGBA, keFlipType_None, &AutoOutputLaserLineExCB, this); if (result != 0) { + m_autoDetectRunning = false; VzNL_GetErrorInfo(result, errorMsg); LOG_ERROR("[VizumCamera] Failed to start auto detect: {} (error code: {})", errorMsg, result); // 尝试清理 @@ -967,13 +1020,21 @@ bool VizumCamera::CapturePointCloudWithAutoDetect(PointCloud& pointCloud, int ti // 检查自动检测状态 VzBool isDetecting = VzNL_IsAutoDetecting(m_deviceHandle, &errorCode); - LOG_INFO("[VizumCamera] IsAutoDetecting: {}", isDetecting == VzTrue ? "Yes" : "No"); + if (errorCode == 0) { + LOG_INFO("[VizumCamera] IsAutoDetecting after start: {}", + isDetecting == VzTrue ? "Yes" : "No"); + } else { + char detectingErrorMsg[256] = {0}; + VzNL_GetErrorInfo(errorCode, detectingErrorMsg); + LOG_WARN("[VizumCamera] Failed to query IsAutoDetecting after start: {} " + "(error code: {})", detectingErrorMsg, errorCode); + } // 3. 等待扫描完成 // 策略:等待以下任一条件满足: - // 1. 收到摆镜完成信号 (m_isPaused = true) + // 1. 收到 SDK 扫描完成信号 Device_Auto_Stop 或 Device_Swing_Finish // 2. 等待超时 - // 3. 如果5秒后仍无数据到达,提前退出(可能摆镜未运动) + // 5秒后仍无数据时持续告警,但保留等待,避免慢启动时误判失败。 int maxWaitTime = (timeoutMs > 0) ? timeoutMs : 30000; LOG_INFO("[VizumCamera] Step 3: Waiting up to {}ms for scan to finish...", maxWaitTime); LOG_INFO("[VizumCamera] NOTE: The camera will collect point cloud data while the swing motor is running."); @@ -1006,7 +1067,11 @@ bool VizumCamera::CapturePointCloudWithAutoDetect(PointCloud& pointCloud, int ti // 如果时间太短且没有点云,可能是虚假的结束信号(例如刚开始时的残留信号),忽略并继续 if (elapsed < 2000) { // 2秒内结束且无数据 - LOG_WARN("[VizumCamera] Received Swing_Finish signal too early ({}ms) without data. Ignoring...", elapsed); + const int completionStatus = m_scanCompletionStatus.load(); + LOG_WARN("[VizumCamera] Received completion status {} ({}) too early " + "({}ms) without data. Ignoring...", + DeviceStatusName(completionStatus), completionStatus, elapsed); + m_scanCompletionStatus = 0; m_isPaused = false; } else { LOG_WARN("[VizumCamera] Scan finished but no points received after {}ms.", elapsed); @@ -1070,14 +1135,36 @@ bool VizumCamera::CapturePointCloudWithAutoDetect(PointCloud& pointCloud, int ti break; } } + // 从此处起 StopAutoDetect 触发的 Auto_Stop 仅属于清理动作,不能改写本次完成原因。 + m_autoDetectRunning = false; int totalDuration = static_cast(std::chrono::duration_cast( std::chrono::steady_clock::now() - startTime).count()); + const int completionStatus = m_scanCompletionStatus.load(); if (m_isPaused) { - LOG_INFO("[VizumCamera] Scan finished by swing completion signal. Duration: {}ms", totalDuration); + LOG_INFO("[VizumCamera] Scan finished by completion status {} ({}). Duration: {}ms", + DeviceStatusName(completionStatus), completionStatus, totalDuration); } else { - LOG_INFO("[VizumCamera] Scan finished by timeout. Duration: {}ms", totalDuration); + int detectingError = 0; + const VzBool stillDetecting = VzNL_IsAutoDetecting(m_deviceHandle, &detectingError); + char detectingErrorMsg[256] = {0}; + if (detectingError != 0) { + VzNL_GetErrorInfo(detectingError, detectingErrorMsg); + } + size_t timeoutScanLines = 0; + size_t timeoutValidPoints = 0; + { + std::lock_guard lock(m_scanLineMutex); + timeoutScanLines = m_accumulatedScanLines.size(); + timeoutValidPoints = m_accumulatedCloud.points.size(); + } + LOG_WARN("[VizumCamera] Timeout diagnostics: duration={}ms, autoDetecting={}, " + "detectError={} ({}), completion status={} ({}), scan lines={}, valid points={}", + totalDuration, stillDetecting == VzTrue ? "Yes" : "No", detectingError, + detectingError == 0 ? "none" : detectingErrorMsg, + DeviceStatusName(completionStatus), completionStatus, + timeoutScanLines, timeoutValidPoints); } // 输出扫描过程中的状态 @@ -1578,6 +1665,7 @@ SLCameraPtr CreateVizumCamera() #undef m_scanLineMutex #undef m_autoDetectRunning #undef m_isPaused +#undef m_scanCompletionStatus #undef m_accumulatedCloud } // namespace StructuredLight