dev
This commit is contained in:
parent
6cfcbbeb65
commit
7989f6c166
|
|
@ -238,6 +238,99 @@ class HikrobotSmartCamera(Component):
|
|||
|
||||
except Exception as e:
|
||||
self.log.error(f"Error getting debug camera state: {e}")
|
||||
|
||||
def is_camera_busy(self, handle=None):
|
||||
"""
|
||||
Check if the camera is currently busy.
|
||||
|
||||
This method checks the camera's device status and acquisition status to determine
|
||||
if it's currently busy with operations that would prevent scheme switching.
|
||||
|
||||
Args:
|
||||
handle: Camera handle. If None, uses the first camera handle.
|
||||
|
||||
Returns:
|
||||
bool: True if the camera is busy, False otherwise
|
||||
"""
|
||||
# Check if camera is connected
|
||||
if not self.connected:
|
||||
self.log.warning("Cannot check if camera is busy: Camera not connected")
|
||||
return True # Assume busy if not connected
|
||||
|
||||
# Get camera handle if not provided
|
||||
if handle is None:
|
||||
if len(self.cam_list) == 0:
|
||||
self.log.warning("Cannot check if camera is busy: No camera handles available")
|
||||
return True # Assume busy if no handles
|
||||
|
||||
handle = self.cam_list[0]["handle"]
|
||||
|
||||
# Check if an operation is already in progress
|
||||
if self.current_operation is not None:
|
||||
self.log.info(f"Camera is busy with operation: {self.current_operation}")
|
||||
return True
|
||||
|
||||
try:
|
||||
self.log.info("Checking if camera is busy...")
|
||||
|
||||
# Try to get the device status
|
||||
device_status = c_uint()
|
||||
nRet = mv_lib.MV_VS_GetEnumValue(handle, b"DeviceStatus", byref(device_status))
|
||||
|
||||
# If we get the 0x80030100 error, the camera is busy
|
||||
if nRet != MV_VS_OK:
|
||||
error_code = nRet & 0xFFFFFFFF
|
||||
if error_code == 0x80030100: # MV_VS_E_GC_GENERIC
|
||||
self.log.warning("Camera is busy: Detected MV_VS_E_GC_GENERIC error (0x80030100) when checking device status")
|
||||
return True
|
||||
else:
|
||||
self.log.warning(f"Error checking device status, error code: 0x{error_code:x}")
|
||||
else:
|
||||
# Log device status value
|
||||
self.log.info(f"Device status: {device_status.value}")
|
||||
|
||||
# Device status values (based on documentation and testing):
|
||||
# 0: Device is idle
|
||||
# 1: Device is busy with acquisition
|
||||
# 2: Device is busy with processing
|
||||
# 3: Device is busy with transfer
|
||||
if device_status.value > 0:
|
||||
self.log.warning(f"Camera appears busy: Device status is {device_status.value}")
|
||||
return True
|
||||
|
||||
# Try to get the acquisition status
|
||||
acquisition_status = c_uint()
|
||||
nRet = mv_lib.MV_VS_GetEnumValue(handle, b"AcquisitionStatus", byref(acquisition_status))
|
||||
|
||||
# If we get the 0x80030100 error, the camera is busy
|
||||
if nRet != MV_VS_OK:
|
||||
error_code = nRet & 0xFFFFFFFF
|
||||
if error_code == 0x80030100: # MV_VS_E_GC_GENERIC
|
||||
self.log.warning("Camera is busy: Detected MV_VS_E_GC_GENERIC error (0x80030100) when checking acquisition status")
|
||||
return True
|
||||
else:
|
||||
self.log.warning(f"Error checking acquisition status, error code: 0x{error_code:x}")
|
||||
else:
|
||||
# Log acquisition status value
|
||||
self.log.info(f"Acquisition status: {acquisition_status.value}")
|
||||
|
||||
# Acquisition status values (based on documentation and testing):
|
||||
# 0: Acquisition is idle
|
||||
# 1: Acquisition is active
|
||||
if acquisition_status.value > 0:
|
||||
self.log.warning(f"Camera appears busy: Acquisition status is {acquisition_status.value}")
|
||||
return True
|
||||
|
||||
# If we've reached this point, the camera is not busy
|
||||
self.log.info("Camera is not busy, safe to proceed with operations")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
self.log.error(f"Error checking if camera is busy: {e}")
|
||||
# Log the full exception traceback for debugging
|
||||
import traceback
|
||||
self.log.error(f"Exception traceback: {traceback.format_exc()}")
|
||||
return True # Assume busy if there's an error
|
||||
|
||||
def refresh_module_list(self):
|
||||
"""
|
||||
|
|
@ -282,7 +375,7 @@ class HikrobotSmartCamera(Component):
|
|||
self.log.error(f"Exception traceback: {traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def switch_scheme(self, solution_name, retry_count=0, max_retries=2):
|
||||
def switch_scheme(self, solution_name, retry_count=0, max_retries=2, force=False, wait_timeout=30):
|
||||
"""
|
||||
Switch to a different scheme/solution using the API as described in the documentation.
|
||||
|
||||
|
|
@ -290,6 +383,8 @@ class HikrobotSmartCamera(Component):
|
|||
solution_name: The name of the solution to switch to
|
||||
retry_count: Current retry attempt (used internally for recursion)
|
||||
max_retries: Maximum number of retry attempts for error recovery
|
||||
force: If True, attempt to switch scheme even if camera appears busy
|
||||
wait_timeout: Maximum time in seconds to wait for camera to become available
|
||||
|
||||
Returns:
|
||||
bool: True if the scheme switching process was successfully initiated, False otherwise
|
||||
|
|
@ -314,6 +409,43 @@ class HikrobotSmartCamera(Component):
|
|||
|
||||
handle = self.cam_list[0]["handle"]
|
||||
|
||||
# Check if camera is busy before proceeding
|
||||
if not force:
|
||||
is_busy = self.is_camera_busy(handle)
|
||||
if is_busy:
|
||||
self.log.warning(f"Camera is busy. Waiting for it to become available before switching to scheme: {solution_name}")
|
||||
|
||||
# Wait for the camera to become available with timeout
|
||||
start_time = time.time()
|
||||
wait_interval = 1.0 # Start with 1 second interval
|
||||
|
||||
while is_busy and (time.time() - start_time) < wait_timeout:
|
||||
# Wait with increasing interval (up to 3 seconds)
|
||||
self.log.info(f"Waiting {wait_interval:.1f} seconds before checking camera status again...")
|
||||
time.sleep(wait_interval)
|
||||
|
||||
# Increase wait interval for next iteration (up to 3 seconds)
|
||||
wait_interval = min(wait_interval * 1.5, 3.0)
|
||||
|
||||
# Check if camera is still busy
|
||||
is_busy = self.is_camera_busy(handle)
|
||||
if not is_busy:
|
||||
self.log.info("Camera is now available, proceeding with scheme switch")
|
||||
break
|
||||
|
||||
# If still busy after timeout, either retry or fail
|
||||
if is_busy:
|
||||
elapsed = time.time() - start_time
|
||||
self.log.warning(f"Camera still busy after waiting {elapsed:.1f} seconds")
|
||||
|
||||
if retry_count < max_retries:
|
||||
self.log.info(f"Retrying scheme switch (attempt {retry_count+1}/{max_retries})")
|
||||
return self.switch_scheme(solution_name, retry_count + 1, max_retries, force, wait_timeout)
|
||||
else:
|
||||
self.log.warning("Maximum retries reached, forcing scheme switch")
|
||||
# Continue with force=True on the last attempt
|
||||
force = True
|
||||
|
||||
# Get current camera state for debugging
|
||||
self.log.info("Getting camera state before scheme switch:")
|
||||
self._debug_camera_state(handle)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import time
|
|||
|
||||
from PyQt5.QtCore import pyqtSignal, QTimer
|
||||
from PyQt5.QtGui import QColor, QImage, QPalette, QPixmap
|
||||
from PyQt5.QtWidgets import QHeaderView, QProgressBar, QTableWidgetItem, QDialog, QVBoxLayout, QLabel, QApplication
|
||||
from PyQt5.QtWidgets import QHeaderView, QProgressBar, QTableWidgetItem, QDialog, QVBoxLayout, QLabel
|
||||
|
||||
from src.lib.helpers.blocking_dialog import BlockingDialog
|
||||
from src.ui.helpers import calc_foreground_color
|
||||
|
|
@ -172,46 +172,14 @@ class Test_Vision(Test_Test):
|
|||
if self.components[cam_type].current_operation != "switch_scheme":
|
||||
self.log.info(f"Initiating scheme switch to: {target_scheme}")
|
||||
|
||||
# Check if camera is busy before attempting to switch scheme
|
||||
if self.components[cam_type].is_camera_busy():
|
||||
self.log.warning(f"Camera is busy. Waiting for it to become available before switching to scheme: {target_scheme}")
|
||||
|
||||
# Update the progress dialog to show waiting status
|
||||
progress_dialog.status_label.setText("Status: Waiting for camera to become available...")
|
||||
progress_dialog.debug_label.setText("Debug info: Camera is busy with another operation")
|
||||
|
||||
# Try up to 3 times with increasing delays
|
||||
max_busy_retries = 3
|
||||
for retry in range(max_busy_retries):
|
||||
# Process events to keep UI responsive
|
||||
QApplication.processEvents()
|
||||
|
||||
# Wait with increasing delay
|
||||
wait_time = (retry + 1) * 2 # 2, 4, 6 seconds
|
||||
self.log.info(f"Waiting {wait_time} seconds before retry {retry+1}/{max_busy_retries}")
|
||||
|
||||
# Update progress dialog
|
||||
progress_dialog.debug_label.setText(f"Debug info: Waiting {wait_time} seconds before retry {retry+1}/{max_busy_retries}")
|
||||
|
||||
# Wait
|
||||
time.sleep(wait_time)
|
||||
|
||||
# Check again if camera is still busy
|
||||
if not self.components[cam_type].is_camera_busy():
|
||||
self.log.info("Camera is now available")
|
||||
break
|
||||
|
||||
if retry == max_busy_retries - 1:
|
||||
self.log.warning("Camera still busy after maximum retries, attempting to force scheme switch")
|
||||
progress_dialog.debug_label.setText("Debug info: Forcing scheme switch after maximum retries")
|
||||
# Update the progress dialog to show we're checking camera status
|
||||
progress_dialog.status_label.setText("Status: Checking camera availability...")
|
||||
progress_dialog.debug_label.setText("Debug info: Checking if camera is busy before switching scheme")
|
||||
|
||||
# Attempt to switch scheme, with force=True on the last retry if still busy
|
||||
force_switch = self.components[cam_type].is_camera_busy()
|
||||
if force_switch:
|
||||
self.log.warning("Forcing scheme switch even though camera appears busy")
|
||||
self.components[cam_type].switch_scheme(target_scheme, force=True)
|
||||
else:
|
||||
self.components[cam_type].switch_scheme(target_scheme)
|
||||
# Start the scheme switching process with wait_timeout parameter
|
||||
# This will automatically wait if the camera is busy
|
||||
self.log.info("Starting scheme switch with automatic busy detection and waiting")
|
||||
self.components[cam_type].switch_scheme(target_scheme, wait_timeout=25) # 25 seconds timeout to leave 5 seconds for the dialog timeout
|
||||
|
||||
# Show the dialog and wait for it to complete
|
||||
result = progress_dialog.exec_()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user