--episode を足しました。変更は pi05/camera_align.py の 1 ファイルだけ(未コミット)、run_policy_client.py は 1 行も触っていません。 変えた行 ┌─────────┬────────────────────────────────────────────────────────────────┐ │ 行 │ 変更 │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ 9-12, │ docstring: 使い方 2 │ │ 15-16, │ つ(写り方合わせ/ブロックの位置合わせ)、--episode │ │ 32-33 │ の説明と実行例 │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ │ pick_episode(raw_dir, episode=None) を新設。None │ │ 70-89 │ なら最初のエピソード(従来どおり)。完全一致 → 1 │ │ │ 本だけに当たる部分一致 → │ │ │ 見つからない/複数当たるときはエピソード一覧を出して ABORT │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ │ grasp_j0(ep_dir) │ │ 92-102 │ を新設。つかんだ瞬間(グリッパーが閉に変わるステップ)の j0 │ │ │ を返す。どの位置のお手本かを表示するためだけに使う │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ 105-118 │ load_reference(raw_dir) → load_reference(raw_dir, │ │ │ episode=None)。中身は pick_episode に委譲。既定の挙動は不変 │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ 179-183 │ _put() を新設(黒で縁取ってから描く) │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ 186, │ draw_overlay(..., ref_label="") に引数追加。文字を _put │ │ 195-200 │ に変更し、左下に ref: <エピソード名> j0=±NN.N を表示 │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ 207-211 │ --episode オプション追加 │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ 216-225 │ load_reference(..., args.episode) に変更し、[REF ] │ │ │ 行でお手本名・つかんだ瞬間の j0・使い方を表示 │ ├─────────┼────────────────────────────────────────────────────────────────┤ │ 240-241 │ draw_overlay に ref_label を渡す │ └─────────┴────────────────────────────────────────────────────────────────┘ load_reference の第 2 引数は既定 None なので、run_policy_client.py の load_reference(Path(args.raw_dir)) は今までどおり最初のエピソードを基準にします(写り方の検査の基準は固定のまま) 。判定(dy・dx・response)のしきい値も変えていません。 位置 C・D・E の確認 カメラを開く部分(cv2.VideoCapture / cv2.imshow)は iPhone が要るのでここでは実行できません。基準の選択 → 画像の読み込み → 重ね画像の生成まで(open_top_camera() の直前まで)を実データで確かめました。 ┌────────────────────────┬──────────────────┬────────┬───────────┬───────┐ │ 指定 │ 選ばれたお手本 │ 基準コ │ つかんだ │ 重ね │ │ │ │ マ │ 瞬間の j0 │ 画像 │ ├────────────────────────┼──────────────────┼────────┼───────────┼───────┤ │ --episode │ run_0001_2026101 │ 000000 │ │ 1152x │ │ なし(位置A) │ 9_183454 │ .jpg 3 │ -36.4° │ 648 │ │ │ │ 84x216 │ │ 生成 │ ├────────────────────────┼──────────────────┼────────┼───────────┼───────┤ │ --episode run_0001_202 │ run_0001_2026101 │ 000000 │ │ │ │ 61019_192343(位置C) │ 9_192343 │ .jpg 3 │ -27.7° │ 生成 │ │ │ │ 84x216 │ │ │ ├────────────────────────┼──────────────────┼────────┼───────────┼───────┤ │ --episode run_0001_202 │ run_0001_2026101 │ 000000 │ │ │ │ 61019_193404(位置D) │ 9_193404 │ .jpg 3 │ -61.6° │ 生成 │ │ │ │ 84x216 │ │ │ ├────────────────────────┼──────────────────┼────────┼───────────┼───────┤ │ --episode run_0001_202 │ run_0001_2026101 │ 000000 │ │ │ │ 61019_194818(位置E) │ 9_194818 │ .jpg 3 │ +13.2° │ 生成 │ │ │ │ 84x216 │ │ │ ├────────────────────────┼──────────────────┼────────┼───────────┼───────┤ │ --episode │ run_0001_2026101 │ 同上 │ -27.7° │ 生成 │ │ 192343(部分一致) │ 9_192343 │ │ │ │ └────────────────────────┴──────────────────┴────────┴───────────┴───────┘ j0 が 4 つとも違うので、狙いどおり別のブロック位置のお手本が選べています。異常 系も確認しました: 存在しない名前 → 19 本の一覧を出して終了、run_0001(19 本に該当)→ 「19 本に当てはまります」で終了。 途中で見つけて直した不具合 重ね画像を実際に描いて確認したところ、resp=... と ref: の行が机の白い背景の上で ほぼ読めませんでした(薄いグレーの文字で縁取りなし)。_put() で黒の縁取りを入れて直しています。下は位置E の重ね画像(左の赤ブロック = ライブ、グリッパーの右脇にうっすら見える赤 = お手本E のブロック): - 文字はマットの黒でも机の白でも読めます - 左下に ref: run_0001_20261019_194818 j0=+13.2 が出ます 実用上の注意が 1 つ: 位置E のようにブロックが HOME のアームの陰に入る位置だと、お手本のブロックが見えにくいです。その場合は --alpha 0.7 でお手本を濃くすると合わせやすくなります。 commit は指示がなかったので止めてあります(pi05/camera_align.py のみ変更)。入れてよければ個別指定で commit します。