コンテンツにスキップ
ステージングサーバー
開発サーバー

エラー処理とリカバリ#

このトピックでは、エラーハンドリングが重要である理由を説明します。

産業用カメラシステムは、障害が発生する可能性が単にあるだけでなく、発生することが想定される環境で動作します。一般的なデスクトップアプリケーションとは異なり、これらのシステムは数時間から数日間にわたって連続稼働し、外部ハードウェアと連携することがよくあります。このため、エラーハンドリングは任意のものではなく、システム設計の核心的な側面となります。

一般的なエラーの原因は次のとおりです。

  • ネットワークの中断(特にGigEカメラを使用している場合)
  • USBの切断
  • トリガー信号の欠落または不安定
  • CPUの過負荷または画像処理の遅延
  • 帯域幅の制限
  • 無効なカメラ構成、または状態に依存するカメラ構成

次の図は、エラーハンドリングが重要である理由を示しています。

System starts → runs normally → transient failure occurs

適切な処理がない場合:

Unhandled exception → application crashes → acquisition stops

適切な処理がある場合:

Failure → detect → recover → continue

目標は、すべての障害の発生を防止することではありません。目標は、障害を可視化し、制御可能にし、回復できるようにすることです。

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接続時のパケットロス
  • 帯域幅の不足
  • 一時的なトランスポート層の問題
  • カメラまたはドライバーの不安定化

この種のエラーは通常、1フレームのみに影響します。アプリケーションは通常、問題をログに記録し、そのフレームをスキップして、取り込みを継続できます。

タイムアウトエラー#

タイムアウトが発生する状況: RetrieveResult() 画像待ち状態であるにもかかわらず、設定されたタイムアウト時間内に画像が到着しない。

with camera.RetrieveResult(
    1000,
    pylon.TimeoutHandling_ThrowException
) as grab_result:
    image = grab_result.Array

主な原因:

  • Trigger Modeが有効になっているが、トリガー信号が到着しない
  • カメラが画像を取得していない
  • Exposure Timeが想定よりも長い
  • タイムアウト値が短すぎる
  • カメラの設定に矛盾がある

タイムアウトはトリガーシステムで特に一般的です。タイムアウトが発生したからといって、必ずしもカメラが故障しているわけではありません。多くの場合、アプリケーションが一度も発生しなかったイベントを待機していることを意味します。

ランタイム例外#

ランタイム例外は、単一フレームの取り込みを超える問題を示します。

例:

  • カメラのケーブルが抜けている
  • ネットワーク接続が切断された
  • デバイスのリセット
  • 無効なカメラ状態
  • 無効なPropertyアクセス
try:
    # acquisition code
    pass
except Exception as e:
    print("Camera error:", e)

これらのエラーが発生した場合は通常、取り込みの停止、待機、カメラの再列挙、デバイスの再オープンなどのリカバリロジックが必要になります。

エラーハンドリング戦略#

堅牢なシステムでは通常、複数の戦略を組み合わせます。

フレームごとのハンドリング#

カメラは稼働しているものの、個々のフレームが失敗する可能性がある場合に使用します。

with camera.RetrieveResult(2000) as grab_result:
    if grab_result.GrabSucceeded():
        process(grab_result.Array)
    else:
        log_error(grab_result.ErrorDescription)

このアプローチは、偶発的なフレーム損失が許容される場合に有用です。取り込みループを維持し、1枚の不良画像のためにシステム全体が停止するのを回避します。

一般的なユースケース:

  • ライブ表示
  • 監視システム
  • クリティカルではない画像ストリーム

例外処理#

使用 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)

取り込みエラーが発生すると、内部バッファやグラビングの状態がクリーンな取り込みパイプラインを表さなくなる場合があります。

  1. 取り込みが通常通り実行されます。
  2. エラーが発生します。
  3. 例外が発生します。
  4. 例外ハンドラーが問題をログに記録します。
  5. StopGrabbing() 取り込みパイプラインをリセットします。
  6. アプリケーションが少し待機します。
  7. ループが取り込みを再試行します。

このパターンにより、手動介入なしで一時的な障害からシステムを復旧させることができます。

取得エラーが発生した後は、内部バッファまたは取得状態が、もはや正常な取得パイプラインを表していない可能性があります。

Error → uncertain acquisition state → reset required

そのため、呼び出すことが StopGrabbing() リカバリーループの不可欠な部分となります。これは以下の点に役立ちます。

  • 現在の取り込み操作の停止
  • 内部バッファの解放または再利用
  • クリーンな再起動に向けたカメラの準備

これによりすべてのハードウェア障害が解決されるわけではありませんが、多くの場合、最初の安全なリカバリーステップとなります。

カメラ切断の処理#

物理的な切断は、実際の運用で最もよくある障害事例の1つです。

Camera unplugged → communication lost → exception

堅牢なアプリケーションでは、ハードウェアはいつでも消失する可能性があるという前提で設計する必要があります。

典型的なリカバリシーケンスを以下に示します。

Detect error
   ↓
Stop acquisition
   ↓
Wait briefly
   ↓
Re-enumerate cameras if needed
   ↓
Reconnect or report fatal failure

本番システムでは、再接続ロジックは通常、基本的なグラブループよりも上位のレベルで実装されます。

リソースの安全性#

を使用して、 with grab resultの管理は不可欠です。

with camera.RetrieveResult(...) as grab_result:
    image = grab_result.Array

これにより、ブロック内で例外が発生した場合でも、grab resultが確実に解放されます。

適切なクリーンアップを行わないと、取り込みが停止する可能性があります。

Unreleased grab results → buffers unavailable → acquisition stalls

これが、本ガイドのすべてのサンプルでgrab resultにコンテキストマネージャを使用している理由です。

出力の代わりにロギングを使用する#

サンプルについては、 print() はシンプルで読みやすいです。本番環境では、Pythonの logging モジュールを使用することをお勧めします。

import logging

logging.exception("Camera acquisition failed")

ロギング機能を使用すると、Timestamp、重要度レベル、永続ファイル、および長期稼働システムの優れた診断情報が提供されます。

回復可能なエラーと致命的なエラー#

すべてのエラーを同じ方法で処理すべきではありません。

エラー 一般的な処理
単一のフレーム取得失敗 ログに記録して続行
Trigger Modeでのタイムアウト トリガー設定の確認または再試行
一時的な帯域幅の問題 ログに記録、負荷の軽減、続行
カメラの接続切断 停止、再列挙、再接続
起動時に必要なカメラが見つからない 即座に失敗させる
無効な設定 停止してエラーを報告

本番アプリケーションでは、再試行可能なエラーと、オペレーターの介入が必要なエラーを明確に区別する必要があります。

主なポイント#

  • 産業環境ではエラーの発生は避けられません。
  • フレームレベルのエラーとシステムレベルの例外の両方を処理してください。
  • タイムアウトの使用を検討し、適切な長さを指定してください。
  • 使用 with リソースの解放を確実に行うためです。
  • 無人運用システム向けにリカバリーループを実装してください。
  • 本番環境では、ロギングと明確なエラー分類を使用してください。

適切に設計されたエラー処理戦略により、安定した自律的なカメラアプリケーションが保証されます。