fix: stop point-cloud wait on SDK auto-stop

This commit is contained in:
Ben 2026-08-23 11:59:11 +08:00
parent 4fd1b38f73
commit 953921c684

View File

@ -78,6 +78,7 @@ struct VizumCamera::Impl {
std::mutex scanLineMutex; std::mutex scanLineMutex;
std::atomic<bool> autoDetectRunning{false}; std::atomic<bool> autoDetectRunning{false};
std::atomic<bool> isPaused{true}; std::atomic<bool> isPaused{true};
std::atomic<int> scanCompletionStatus{0};
PointCloud accumulatedCloud; PointCloud accumulatedCloud;
}; };
@ -99,11 +100,27 @@ struct VizumCamera::Impl {
#define m_scanLineMutex m_impl->scanLineMutex #define m_scanLineMutex m_impl->scanLineMutex
#define m_autoDetectRunning m_impl->autoDetectRunning #define m_autoDetectRunning m_impl->autoDetectRunning
#define m_isPaused m_impl->isPaused #define m_isPaused m_impl->isPaused
#define m_scanCompletionStatus m_impl->scanCompletionStatus
#define m_accumulatedCloud m_impl->accumulatedCloud #define m_accumulatedCloud m_impl->accumulatedCloud
#ifdef ENABLE_VIZUM_CAMERA #ifdef ENABLE_VIZUM_CAMERA
namespace { namespace {
const char* DeviceStatusName(int status)
{
switch (static_cast<EVzDeviceWorkStatus>(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, void AutoOutputLaserLineExCB(EVzResultDataType eDataType,
SVzLaserLineData* pLaserLinePoint, SVzLaserLineData* pLaserLinePoint,
void* pParam) void* pParam)
@ -144,19 +161,40 @@ void VizumCamera::HandleAutoOutputLaserLine(int dataType, void* laserLinePoint)
void VizumCamera::HandleDeviceStatusChange(int status) void VizumCamera::HandleDeviceStatusChange(int status)
{ {
#ifdef ENABLE_VIZUM_CAMERA #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<int>(keDeviceWorkStatus_Device_Swing_Finish)
|| status == static_cast<int>(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<std::mutex> 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<int>(keDeviceWorkStatus_Offline)) { if (status == static_cast<int>(keDeviceWorkStatus_Offline)) {
LOG_WARN("[VizumCamera] Camera went offline"); LOG_WARN("[VizumCamera] Camera went offline");
} else if (status == static_cast<int>(keDeviceWorkStatus_Device_Swing_Finish)) {
LOG_INFO("[VizumCamera] Camera swing finished - setting m_isPaused=true");
m_isPaused = true;
} else if (status == static_cast<int>(keDeviceWorkStatus_Device_Swing_Running)) { } else if (status == static_cast<int>(keDeviceWorkStatus_Device_Swing_Running)) {
LOG_INFO("[VizumCamera] Camera swing motor started running"); LOG_INFO("[VizumCamera] Camera swing motor started running");
} else if (status == static_cast<int>(keDeviceWorkStatus_Eye_Reconnect)) { } else if (status == static_cast<int>(keDeviceWorkStatus_Eye_Reconnect)) {
LOG_INFO("[VizumCamera] Camera reconnected"); LOG_INFO("[VizumCamera] Camera reconnected");
} else if (status == static_cast<int>(keDeviceWorkStatus_Device_Auto_Stop)) {
LOG_INFO("[VizumCamera] Device auto stop signal received");
} }
#else #else
(void)status; (void)status;
@ -539,8 +577,20 @@ bool VizumCamera::Connect(const std::string& ipAddress)
return false; return false;
} }
// 设置设备状态回调 // 设置设备状态回调。静态扫描以 Device_Auto_Stop 作为官方完成信号,注册失败不可静默继续。
VzNL_SetDeviceStatusNotify(m_deviceHandle, &DeviceStatusCB, this); 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 之后立即设置图像输出格式(在此之前设置对本次连接无效) // OpenDevice 之后立即设置图像输出格式(在此之前设置对本次连接无效)
VzNL_SetOutputImageFormat(keVzNLImageType_BGR888); VzNL_SetOutputImageFormat(keVzNLImageType_BGR888);
@ -948,12 +998,15 @@ bool VizumCamera::CapturePointCloudWithAutoDetect(PointCloud& pointCloud, int ti
} }
// 3. 启动自动检测模式(与VznlCamera::StartAutoDetect一致) // 3. 启动自动检测模式(与VznlCamera::StartAutoDetect一致)
m_scanCompletionStatus = 0;
m_isPaused = false; m_isPaused = false;
m_autoDetectRunning = true;
LOG_INFO("[VizumCamera] Step 2: Starting AutoDetectEx..."); LOG_INFO("[VizumCamera] Step 2: Starting AutoDetectEx...");
result = VzNL_StartAutoDetectEx(m_deviceHandle, keResultDataType_PointXYZRGBA, result = VzNL_StartAutoDetectEx(m_deviceHandle, keResultDataType_PointXYZRGBA,
keFlipType_None, keFlipType_None,
&AutoOutputLaserLineExCB, this); &AutoOutputLaserLineExCB, this);
if (result != 0) { if (result != 0) {
m_autoDetectRunning = false;
VzNL_GetErrorInfo(result, errorMsg); VzNL_GetErrorInfo(result, errorMsg);
LOG_ERROR("[VizumCamera] Failed to start auto detect: {} (error code: {})", errorMsg, result); 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); 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. 等待扫描完成 // 3. 等待扫描完成
// 策略:等待以下任一条件满足: // 策略:等待以下任一条件满足:
// 1. 收到摆镜完成信号 (m_isPaused = true) // 1. 收到 SDK 扫描完成信号 Device_Auto_Stop 或 Device_Swing_Finish
// 2. 等待超时 // 2. 等待超时
// 3. 如果5秒后仍无数据到达,提前退出(可能摆镜未运动) // 5秒后仍无数据时持续告警,但保留等待,避免慢启动时误判失败。
int maxWaitTime = (timeoutMs > 0) ? timeoutMs : 30000; int maxWaitTime = (timeoutMs > 0) ? timeoutMs : 30000;
LOG_INFO("[VizumCamera] Step 3: Waiting up to {}ms for scan to finish...", maxWaitTime); 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."); 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秒内结束且无数据 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; m_isPaused = false;
} else { } else {
LOG_WARN("[VizumCamera] Scan finished but no points received after {}ms.", elapsed); LOG_WARN("[VizumCamera] Scan finished but no points received after {}ms.", elapsed);
@ -1070,14 +1135,36 @@ bool VizumCamera::CapturePointCloudWithAutoDetect(PointCloud& pointCloud, int ti
break; break;
} }
} }
// 从此处起 StopAutoDetect 触发的 Auto_Stop 仅属于清理动作,不能改写本次完成原因。
m_autoDetectRunning = false;
int totalDuration = static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>( int totalDuration = static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - startTime).count()); std::chrono::steady_clock::now() - startTime).count());
const int completionStatus = m_scanCompletionStatus.load();
if (m_isPaused) { 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 { } 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<std::mutex> 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_scanLineMutex
#undef m_autoDetectRunning #undef m_autoDetectRunning
#undef m_isPaused #undef m_isPaused
#undef m_scanCompletionStatus
#undef m_accumulatedCloud #undef m_accumulatedCloud
} // namespace StructuredLight } // namespace StructuredLight