错误处理与恢复#
工业相机系统运行的环境中,故障不仅可能发生,而且是在预料之中的。与典型的桌面应用程序不同,这些系统通常连续运行数小时甚至数天,并与外部硬件进行交互。因此,错误处理并非可有可无,而是系统设计中的核心要素。
典型的错误来源包括:
- 网络中断,特别是使用 GigE 相机时
- USB 断开连接
- 缺少触发信号或触发信号不稳定
- CPU 过载或图像处理速度慢
- 带宽限制
- 相机配置无效或依赖于当前状态
以下图示说明了为什么错误处理至关重要:
没有适当的处理:
有适当的处理:
我们的目标不是防止所有可能的故障,而是让故障清晰可见、可控且可恢复。
pypylon 中的错误类型#
不同的错误类型需要不同的处理策略。
采集错误#
抓取错误意味着返回了抓取结果,但图像本身无效。
with camera.RetrieveResult(2000) as grab_result:
if grab_result.GrabSucceeded():
image = grab_result.Array
else:
print(grab_result.ErrorCode)
print(grab_result.ErrorDescription)
常见原因:
- GigE 连接期间发生丢包
- 带宽不足
- 传输层出现临时问题
- 相机或驱动程序不稳定
此类错误通常仅影响单帧图像。应用程序通常可以记录问题、跳过该帧并继续采集。
超时错误#
发生超时,因为 RetrieveResult() 正在等待图像,但在配置的超时时间内没有图像到达。
with camera.RetrieveResult(
1000,
pylon.TimeoutHandling_ThrowException
) as grab_result:
image = grab_result.Array
常见原因:
- 已启用 Trigger Mode,但没有触发信号到达
- 相机未在抓取图像
- Exposure Time 长于预期
- Timeout 值过短
- 相机配置不一致
超时在触发系统中尤为常见。超时并不一定意味着相机损坏,通常意味着应用程序正在等待一个未发生的事件。
运行时异常#
运行时异常表示超出了单帧采集范围的问题。
示例如下:
- 相机已拔出
- 网络连接丢失
- 设备重置
- 相机状态无效
- 参数访问无效
这些错误通常需要恢复逻辑,例如停止采集、等待、重新枚举相机或重新打开设备。
错误处理策略#
强健的系统通常会结合多种策略。
逐帧处理#
当相机仍在运行但个别帧可能会失败时,请使用此功能。
with camera.RetrieveResult(2000) as grab_result:
if grab_result.GrabSucceeded():
process(grab_result.Array)
else:
log_error(grab_result.ErrorDescription)
当偶尔丢失帧可以接受时,此方法非常有用。它可使采集循环保持活动状态,并避免因一张坏图而停止整个系统。
典型用例:
- 实时显示
- 监控系统
- 非关键图像流
异常处理#
使用 try/except 围绕可能在运行时失败的操作进行。
try:
with camera.RetrieveResult(
2000,
pylon.TimeoutHandling_ThrowException
) as grab_result:
if grab_result.GrabSucceeded():
process(grab_result.Array)
except Exception as e:
print("Error:", e)
这可以防止应用程序立即崩溃。但是,仅捕获异常是不够的。应用程序还必须决定是继续、重试、重置采集还是安全关闭。
恢复循环模式#
恢复循环结合了错误检测和自动恢复功能。以下代码示例显示了构建恢复循环的推荐模式。
import time
with pylon.InstantCamera(pylon.FirstFound) as camera:
while True:
try:
if not camera.IsGrabbing():
camera.StartGrabbing()
with camera.RetrieveResult(
2000,
pylon.TimeoutHandling_ThrowException
) as grab_result:
if grab_result.GrabSucceeded():
image = grab_result.Array
process(image)
else:
log_error(grab_result.ErrorDescription)
except Exception as e:
log_error(f"Acquisition error: {e}")
if camera.IsGrabbing():
camera.StopGrabbing()
time.sleep(0.5)
使用恢复循环时的事件顺序如下:
- 采集正常运行。
- 发生错误。
- 引发异常。
- 异常处理程序记录该问题。
StopGrabbing()重置采集管线。- 应用程序稍作等待。
- 循环重试采集。
此模式允许系统在无需人工干预的情况下从临时故障中恢复。
在发生采集错误后,内部缓冲区或抓取状态可能不再代表干净的采集管线。
这就是为什么调用 StopGrabbing() 是恢复循环中至关重要的一部分。它有助实现以下功能:
- 停止当前的采集操作
- 释放或回收内部缓冲区
- 为相机的干净重启做好准备
这并不能解决所有可能的硬件故障,但它通常是安全恢复的第一步。
相机断开连接处理#
物理断开连接是最常见的实际故障案例之一。
健壮的应用程序应假设硬件随时可能消失。
此处显示了典型的恢复序列:
Detect error
↓
Stop acquisition
↓
Wait briefly
↓
Re-enumerate cameras if needed
↓
Reconnect or report fatal failure
对于生产系统,重新连接逻辑通常在高于基本抓取循环的层级中实现。
资源安全性#
使用 with 对于抓取结果而言至关重要。
这可确保即使代码块内部发生异常,抓取结果也会被释放。
如果没有适当的清理,采集可能会停滞:
这就是本指南中的所有示例都为抓取结果使用上下文管理器的原因。
使用日志记录代替打印#
例如, print() 简单易读。在生产环境中,最好使用 Python logging 模块。
Logging 可为长时间运行的系统提供 Timestamp、严重性级别、持久化文件以及更好的诊断功能。
可恢复错误与致命错误#
并非所有错误都应以相同的方式处理。
| 错误 | 典型处理方式 |
|---|---|
| 单帧失败 | 记录日志并继续 |
| Trigger Mode 超时 | 检查触发配置或重试 |
| 临时带宽问题 | 记录日志、减少负载、继续 |
| 相机断开连接 | 停止、重新枚举、重新连接 |
| 启动时缺少必需的相机 | 快速失败 |
| 无效配置 | 停止并报告错误 |
生产应用程序应明确区分可重试的错误与需要人工干预的错误。
核心要点#
- 在工业环境中,错误是正常的。
- 同时处理帧级错误和系统级异常。
- 考虑使用超时机制并指定合适的长度。
- 使用
with以确保资源清理。 - 为无人值守系统实现恢复循环。
- 在生产环境中使用 logging 并进行清晰的错误分类。
设计良好的错误处理策略可确保相机应用程序稳定且自主地运行。