Newer
Older
TIASShot / docs / 03_PLAN / PLAN_06_実機自動テスト計画.md

実機自動テスト計画 (Hardware-in-the-Loop Test Plan)

目的 (Purpose)

PLAN_05 の 4 層モデルで「層④: 実機」に残っている確認(SDK の実呼び出し・実画像)を,Claude が実機を操作して自動で確認するようにする.人間の役割を「機材をつなぐ・チャートを置く・テストしてよいと合図する」という物理的な準備だけに絞る.

前提 (Preconditions)

2026-10-06 にユーザーと確認した.

項目内容
接続カメラ(ImagingSource・Lumenera)と光源は,Claude が動作している開発 PC に接続できる
機材両機種がそろっている
対象機種ImagingSource だけを対象にし,Lumenera の実機テストは行わない(2026-10-08 にユーザーが決定.Lumenera は解像度が相対的に低く今後あまり使わない見込みのため).--camera lucam の実装は残すが,検査の対象にしない
実行してよい条件ユーザーが会話の中で明示的に合図したときだけ.撮影の本番中に機材を操作しないため,合図なしに実機テストを実行しない

仕組み (Design)

既存のセルフテスト(TIASshot.exe --selftest.偽カメラ・ヘッドレス)と同じ考え方で,実機版の検査モードを追加する.

  • 起動: TIASshot.exe --hwtest --camera <lucam|iscam> [--with-chart] [--hwtest-keep] --hwtest-out <結果ファイル>.ランナー scripts/verify/run_hwtest.py がビルドから実行・判定までを行う(run_selftest.py と同じ形)
  • --with-chart: チャートが必要な検査(connect → calibrate → shot → close-saving → close-calibrating → cleanup)を行う.校正は止めない.チャート不要の検査は行わないため,--camera iscam と --camera iscam --with-chart をカラーチャートをはめたまま続けて実行する.全体の上限はチャート不要 600 秒・--with-chart 1200 秒,ランナーの打ち切りはそれぞれ 720 秒・1320 秒
  • --keep(ランナー)= --hwtest-keep: 合格時も作業フォルダ(%TEMP%\TIASshot-hwtest\work-*)を残す(不合格・タイムアウト時は常に残る).--with-chart では校正後のフレームとその変換画像を証拠の画像(evidence\calibrated-frame-raw.png・evidence\calibrated-frame-srgbNN.png.NN は変換の次元)として保存する.撮影データ・校正データは作業フォルダの data\ に保存され,合格時は作業フォルダごと削除される
  • ビルドフラグ: HWTEST(Debug 系の構成のみ).診断・評価機能を Release に含めない方針(CLAUDE.md・ENV_06)に従う
  • フォーム: ImagingSource は SDK の画面部品(ICImagingControl)を使うため,ヘッドレスではなく実際の Form1 を表示して動かす.人間がその場にいる前提なので表示してよい
  • カメラの選択: 両機種を同時につないでも,--camera で指定した機種だけを使う(通常起動の Form1_Load は Lumenera を優先して探すため,そのままでは ImagingSource を検査できない)
  • 結果: 項目ごとの PASS / FAIL と測定値を結果ファイルに書き,終了コード(0=合格,1=不合格あり,2=実機テスト自体の異常,3=タイムアウト)で返す.セルフテストの結果ファイルと同じ書式にする

守ること (Safety)

  • 保存先は一時フォルダ(%TEMP% 配下)にする.本番の保存先(C:\TIAS_Data 等)には書き込まない
  • 同梱の config.xml は変更しない(一時フォルダに複製して保存先等を差し替える)
  • カメラのデバイス状態ファイル({DeviceName}.xml)は読むだけで,上書きしない.露光・ゲイン等を検査で変えた場合は,終了時に元の値へ戻す
    • ImagingSource の露光・ゲインは絶対値(VCDAbsoluteValueProperty.露光は秒,ゲインは dB)で読み書きし,元の絶対値そのものへ戻して読み戻しで確かめる(整数の段(VCDRangeProperty)で扱うと元の値に戻せないため)
  • チャート不要の検査の間は自動校正(チャート検出・ホワイトバランスの調整・変換行列の算出)を止める(CameraBase の校正停止フラグ.HWTEST ビルド限定).はめたチャートで校正が走ると露光・ゲイン・ホワイトバランスが検査中に変わるため
  • 光源は検査の最後に必ずポートを閉じる(失敗した場合も).消灯はしない(アプリ終了時に光源を消さない仕様に合わせる.light 項目の最後に再点灯した状態で終わる)
  • 待機には必ずタイムアウトを付ける

検査項目 (Test Items)

チャート不要(--with-chart なし)

※ 穴に何もはめないと中が暗く明るさの変化を評価しにくいため,カラーチャート(または白板)をはめた状態で行う.この検査の間は,チャートが写っても自動校正を走らせない(テストモードだけの処理.2026-10-08 にユーザーと合意).

ID確認内容判定の仕方
connect指定した機種に接続でき,機種名・シリアル番号が取れるConnect() の成否
previewプレビューが流れる一定時間に届いたフレーム数(フレームレートの下限)
exposure-gain露光・ゲインの設定がフレームに効く基準の明るさを探してから,露光を 1 段(2^n 秒の段で半分・2 倍),ゲインを範囲の幅の ±10% 上げ下げしたときの平均輝度の変化の向きと量.飽和した向きは確認しない.終了時に元の値へ戻ったことを読み戻しで確かめる
light光源が点灯・消灯し,閉じた後に開き直せる点灯時と消灯時のフレームの平均輝度の差,ポートの再オープンの成否
close-previewプレビュー中に閉じる処理を呼んでもすぐ戻る後始末の所要時間(上限つき)と例外の有無,閉じた後に届いたフレーム数
reconnect切断した後に再接続できる2 回目の Connect() の成否とフレームの到着
cleanup後始末と書き込み禁止露光・ゲインを戻す → カメラ切断 → 光源のポートを閉じる(消灯しない)の成否,設定・デバイス状態ファイル・本番の保存先が変わっていないこと

露光・ゲインの基準探し: 元の露光に最も近い 2n 秒の段に合わせ,平均輝度が中間(30〜220)かつ飽和画素(254 以上)の割合が 1% 以下になるまで露光を 1 段ずつ動かす(最大 12 段).実測で露光 1 段は 0.497 倍(黒レベル 15.2 を引いた値)≈ 0.5 倍,ゲイン 1 dB は 1.122 倍 ≈ 10(1/20) と理論どおりに効いた.

チャートが必要(--with-chart.人間がチャートをカメラの前に置いてから実行する)

※ チャート不要の検査と同じくカラーチャートをはめたまま続けて実行できる(付け外しは不要).こちらは自動校正を走らせて結果を確かめる.--with-chart ではチャート不要の検査(preview〜reconnect)は行わない(connect・cleanup は共通.cleanup ではホワイトバランスを戻さない.校正で変わるのはカメラ側の値だけで,次の接続でデバイス状態ファイルの値に戻る).

ID確認内容判定の仕方
calibrate実物の舌診チャートで自動校正が完了し,校正後のフレームを変換した色票が参照値に近い校正の待ち時間(最初のフレーム → チャート検出 → 校正完了.上限 60 秒),校正完了後に撮影ボタンが有効になること,校正データが一時フォルダに保存されること.校正後のフレームを校正の変換行列で変換し,24 色票の平均と参照値(tcc_srgb)の差を保存画像と同じ 8bit(切り詰め後)・チャネルごとの差の絶対値で判定する(平均,白色票を除いた最大,白色票の最大).白色票は参照値の BGR の和が最大の色票(13 番).ΔE76・白飛びの割合・当てはめの誤差は参考
shot単発・連続撮影で保存される単発 1 枚・連続 3 枚(間隔 1000 ms).撮影直後は保存中で撮影ボタンが無効,保存完了(上限つき)後に再有効化されること,保存されたファイル(撮影画像・変換画像・Info.csv)と撮影ログの行数・備考,撮影時刻の間隔(設定値との差),エラー通知の有無
close-saving保存中に閉じようとすると取り消され,保存後は閉じられる連続 5 枚(間隔 0 ms.保存が先に終わったら 10 枚で再試行)の保存中に閉じる処理を呼び,取り消しの成否と表示文・後始末が走っていないこと.保存完了後に閉じる処理の所要時間・後始末の順序(closing → timer → camera → light)・閉じた後に届いたフレーム数
close-calibrating校正中に閉じてもすぐ戻る再接続して校正中になってから 500 ms 後に閉じる処理を呼び,所要時間・後始末の順序・例外の有無・閉じた後に届いたフレーム数

※ 判定のしきい値はチャート不要の検査はフェーズ 1,チャートが必要な検査はフェーズ 2 の実測から決めた(下記「確定したしきい値と実測値」).

確定したしきい値と実測値 (Thresholds and Measurements)

フェーズ 1 の実測(ImagingSource DFK 33UX178.シリアル 35620307・10620446.カラーチャートをはめた状態)と,フェーズ 2 の実測(同機種.シリアル 10620446.2026-10-08 の 2 回)から決めた.しきい値の本体は HwTest/HwTestJudge.cs.

項目しきい値実測値
preview のフレームレート10 fps 以上13〜18 fps
exposure-gain の露光1 段下げで比 0.8 以下,1 段上げで比 1.25 以上(向きごと.飽和した向きは確認しない)下げ 0.545(2026-10-08 13:38 の実行.上げは比 1.322 だが飽和画素 70% のため確認しない向き)
exposure-gain のゲイン平均輝度の差 3 以上(片側の向きだけ期待どおりでも合格)下げ −15.6(同上.上げは +47.1 だが飽和画素 68% のため確認しない向き)
基準の明るさ平均輝度 30〜220,飽和画素(254 以上)の割合 1% 以下元の露光に近い段(0.015625 秒)で 158.9
飽和の判定254 以上の画素の割合が 1% を超える—
light の点灯と消灯の差平均輝度の差 100 以上153〜196
close-preview の閉じる処理1000 ms 以内,閉じた後に届くフレーム 2 以下75〜221 ms,0 フレーム
reconnect再接続後に 5 フレーム以上964 ms で 5 フレーム(2026-10-08 13:38 の実行)
露光・ゲインの復元元の値との相対誤差 1% 以内一致
calibrate の校正の待ち時間60 秒以内5.0〜5.6 秒(チャート検出まで 1.6〜1.8 秒+校正 3.4〜3.8 秒)
calibrate の色の誤差(8bit・チャネルごとの |測定−参照|.17 次元)の平均5 以下1.57
calibrate の色の誤差の白色票を除いた最大10 以下3.47〜3.5(10 番)
calibrate の色の誤差の白色票(13 番)の最大40 以下(暫定.下記「17 次元の変換のノイズ」)24.65〜27.35
calibrate の ΔE76参考(判定しない)平均 1.20〜1.26,最大 10.11〜12.04(白色票)
shot の撮影間隔のずれ設定値との差 100 ms 以下4〜22 ms
shot・close-saving の保存の待ち時間180 秒以内(2026-10-09 に 90 秒から延ばした)1 枚あたり約 3.3 秒(5 枚で 16〜20 秒).重いアプリが動いていると約 11 秒(5 枚で 55 秒)
close-saving の閉じる処理保存中は取り消される.保存の完了後は 1000 ms 以内,閉じた後に届くフレーム 2 以下取り消しを確認,33〜72 ms,0 フレーム
close-calibrating の閉じる処理校正中になるまで 60 秒以内,閉じる処理 1000 ms 以内,閉じた後に届くフレーム 2 以下53〜98 ms,0 フレーム

17 次元の変換のノイズ (Noise of the 17-Term Conversion)

フェーズ 2 の実機テストで,白色票の色の誤差だけが大きい(24.65〜27.35.他の色票は 3.5 以下)ことが分かった.製品の性質であり,対策は要判断.対策は保留中の検討事項として TECH_03「保留中の検討事項」 で管理する(2026-10-09 に保留と決定).

  • 事実: 白色票の入力(約 226.標準偏差 3〜5.飽和なし)が 17 次元(3 次)の変換で約 10 倍に増幅され(変換後の標準偏差 約 50,8bit に切り詰める前の値 -249〜621),8bit の範囲を外れて点状のノイズ・白飛びになる(白色票の 255 の画素 約 73%).チャート外の白い台紙・枠でも点状のノイズが出る.平均の色は合っている(切り詰め前の値で平均すると参照値との差は 2 以内).白など色票の範囲の端の明るい色で,高次の多項式の外挿がノイズを増幅するためと考えられる
  • 回帰ではない(上流 v1.6 でも同じ): 2026-10-09 に v1.6 と現行で同じチャートを撮影し,同じ入力を両方のコードに通すと,マスク・色票の値・変換行列・変換後の画像(PNG/JPEG)がビット単位で一致した(色変換はリファクタリングで変わっていない).白色票の変換後の標準偏差も v1.6 51/39/23・現行 50/36/24(B/G/R)で同程度
  • 要判断: 対策(使う次元を下げる,入力・出力に制限をかける,色票の範囲外を別扱いにする等)は色の再現性に関わるため,研究室・上流と相談して決める.それまで白色票のしきい値 40 は暫定とし,色の誤差は白色票とそれ以外に分けて判定する
  • 付随して確かめたこと: CSV に保存する変換行列(小数 7 桁)は 17 次元の 3 次の係数では有効数字が約 3 桁しかなく,CSV から画像を再現すると 8bit で最大 2〜4 ずれる

進め方 (Workflow)

  1. 人間が機材をつなぎ,カラーチャート(または白板)を穴にはめて,「実機テストして」等と合図する
  2. Claude(verifier)が python scripts/verify/run_hwtest.py --camera <機種> と python scripts/verify/run_hwtest.py --camera <機種> --with-chart を続けて実行し,結果ファイルと終了コードで判定する
  3. 対象は ImagingSource(--camera iscam)だけ.Lumenera は行わない(上記「対象機種」)
  4. 人間に残る確認は,画面の見た目の最終確認など,数値で置き換えられないものだけにする

変更が必要なもの (Changes)

対象変更内容
TIASshot(本体)HWTEST フラグの追加,--hwtest の実装(検査項目・結果ファイル),カメラを機種指定で接続する口
scripts/verify/run_hwtest.pyビルド・実行・判定のランナー
.claude/verify-profile.md実機カメラ・光源・シリアルポートへの接続を,「ユーザーが会話の中で合図したとき」に限って許可する.合図がなければ実機テストは実行せず「検証不能(合図なし)」と報告する
.claude/rules/testing.md層④のうち実機テストで確認できる項目を明記する
TEST_01手動テストの項目を,実機テストで置き換えた分だけ減らす
ENV_04・ENV_06実機テストのコマンドと HWTEST フラグの説明

フェーズ (Phases)

フェーズ 1: 基盤とチャート不要の検査

  • HWTEST フラグ,--hwtest,機種指定の接続,結果ファイル,ランナーを作る
  • チャート不要の検査(connect・preview・exposure-gain・light・close-preview・reconnect)を実装する
  • 検証プロファイルを更新する
  • 完了条件: ImagingSource で人間の合図のもと実行でき,しきい値を実測から決めて全項目が合格する(当初は両機種としていたが,2026-10-08 に Lumenera を対象外とした)
  • 状態: ImagingSource で完了(2026-10-08.DFK 33UX178 の 2 個体で 7/7 合格).Lumenera の実機テストは行わない(対象外)
  • 実機テストで見つかった不具合: 同梱の DFK33UX178.xml は別個体(シリアル 41520093)のものを指しており,旧 IScam.Connect はファイルのデバイスを開いていたため,別個体では接続できず例外が外へ漏れていた.機種名でデバイスを開いてから設定だけを適用し,失敗は ErrorMsg+false で返すように直した(Cameras/IScamDeviceSelector.TECH_02)
  • 仕様変更: アプリ終了時に光源を消灯しない(ポートを閉じるだけ.上流 v1.7 と同じ.2026-10-08 にユーザーが確定).実機テストの後始末も同じく消灯しない

フェーズ 2: チャートが必要な検査

  • calibrate・shot・close-saving・close-calibrating を実装する
  • 完了条件: ImagingSource で実物のチャートを使って全項目が合格する
  • 状態: ImagingSource で完了(2026-10-08.DFK 33UX178(シリアル 10620446)で 2 回とも 6/6 合格)
  • 実機テストで見つかったこと: 17 次元の変換で白色票・白い台紙に点状のノイズ・白飛びが出る(上流 v1.6 から同じ.上記「17 次元の変換のノイズ」.対策は要判断)

フェーズ 3: 手動テストの縮小

  • TEST_01 の手動テストと PLAN_05 の「手動確認の目標形」を,実機テストで置き換えた分だけ縮める
  • 状態: 完了(2026-10-09).手動テストに残したのは,実機テストで確かめられない項目だけ: 通常起動で機種を自動で選ぶ流れ,プレビューの見た目,マウスでのボタン操作,撮影した画像の色の目視,撮影の途中で閉じる場合(未自動化),閉じた後も光源が点いたまま残ること,Lumenera を使う場合の確認
  • 後段の候補: 撮影の途中で閉じる場合の検査を実機テストに追加すれば,手動テストからさらに外せる

PLAN_05 との関係 (Relation to PLAN_05)

  • PLAN_05 フェーズ 3b(SDK アダプタからの判断ロジックの切り出し)とは独立に進められる.3b で切り出したロジックは層①で,SDK の呼び出しそのものは本計画の実機テストで確認する,という分担になる
  • PLAN_05 フェーズ 4(実機録画データによる回帰)の撮影は,本計画の実機テストの仕組みを使って自動化できる可能性がある(録画フレームの保存を検査モードに加える)

リスクと対策 (Risks)

リスク対策
撮影の本番中に Claude が機材を操作してしまう実行はユーザーの合図があったときだけ.検証プロファイルで明記し,合図がなければ検証不能として報告する
検査でカメラの設定が変わったまま残るデバイス状態ファイルは上書きしない.変えた露光・ゲインは終了時に元に戻す
光源のポートが開いたまま残る検査の最後(失敗時も)にポートを閉じる.光源は点いたままでよい(アプリ終了時と同じ仕様)
実機の個体差・照明で判定が不安定になるしきい値は実測から余裕を持って決める.輝度は絶対値ではなく変化の向きで判定する
SDK がハングして検査が終わらない検査全体と各項目にタイムアウトを付け,ランナー側でもプロセスを打ち切る