依頼176 報告：実機推論の最初の待ちをなくし、チャンクの中で止まらずに流す（Log35）

■ やったこと
1. 空打ち（既定で入れた）
- pi05/policy_warmup.py を新しく作った。お手本（lab_start の $RAW_RANGE）の最初のエピソードの 1 枚目（384x216）・state[0]（7 つ）・prompt で 1 回だけ推論させて、答えを捨てる。
- lab_start.sh では、トンネル（5）のあと・デーモンやアームより前に「5b. 空打ち」として流す。--serve-only のときも行う。
- かかった秒は [WARM  ] の行に出す。時間の上限は、つなぐところから合わせて 300 秒。
- 失敗・答えない・Ctrl-C のときは [WARM  ] を 1 行出して、そのまま続ける（lab_start は止まらない）。
2. --flow / --flow-tol / --speed（run_policy_client.py。lab_start.sh にも --flow・--speed N を足し、そのまま渡す）
- 途中の点：単発の send_angles を 1 回送る。そのあとは関節角を読みながら待ち、次のどちらかで次の点を送る。
  - --flow-tol（既定 5°）以内に近づいた
  - 見込みの時間（0.15 秒＋角度÷(25°/秒×speed/20)。0.4〜1.5 秒）がたった
- チャンクの最後の点は今までどおり 3° の到着を確かめてから、次の推論へ進む。
- 送る直前の関節角の読み直し・max_move・関節の範囲・安全範囲は変えていない。新しい停止条件も足していない。
- --speed は推論のチャンク（と settle の送り直し）だけに効く。補正（キー・ゲームパッド）・巻き戻し・HOME は 20 のまま。
- log.jsonl の頭（type=model）に flow・flow_tol・speed を残す。--flow のときは中継点ごとに vias[].flow を残す（送った時刻 t_send・次へ進むと決めた時刻 t_next・次を実際に送った時刻 t_next_sent と send_gap_s・進んだわけ advance・残りの角度 err_deg）。最後の点は送った時刻と着いた時刻。
- --flow なし・速さ 20 では、送り方・log の中身・画面の出力は今までと同じ（git HEAD の版と比べるテストで確かめた）。
3. pi05/chunk_timing.py（読むだけ・何も書き出さない）
- チャンクごとに 推論・確認待ち・動いた・その他・合計 を出し、試行全体の合計・中央値も出す。
- 中継点ごとの間は、--flow の試行なら log の flow から、今までの試行なら recording/states.csv の送った時刻から出す。
- 試行を 2 つ以上渡すと、最後に比べる表を出す。
4. テスト：新しく足したもの・既存のものとも全部通った。数は次のとおり。
- 新しく足したもの：test_flow_send 16 件・test_chunk_timing 6 件
- 既存：test_lab_start.sh 210、test_rewind_correct 81（新しい 3 項目だけ比べる対象から外した）、pi05/ のほかのテスト全部、tools/test_gamepad_teleop 93
- test_power_ab は、最後の一括実行で 2 件落ちた。単独で流し直すと 20 件とも通った（1 回目の一括実行でも通っていた。今回の変更とは関係のない時間の揺れ）。
5. codex：4 回。
- 1 回目：必須 2 件（待つ間に読んだ値を送る前の守りに使っていた／空打ちが metadata 待ちで止まりうる）と推奨 3 件。全部直した。
- 2 回目・3 回目：推奨を直した。
- 4 回目：指摘なし。
6. コミット 0383893（8 ファイルを個別に add）。

■ 結果
pi05_20261113_193254 を chunk_timing.py で流した表（秒）：
== pi05_20261113_193254  (/Volumes/KIOXIA/r2r2r-data/runs/pi05_policy/pi05_20261113_193254)
   送り方: 記録なし (依頼 176 より前 = --flow なし・速さ 20)  速さ 20  モデル deep1 (PixelstoMotors/pi05-mecharm-deep-even10-lora-v1)  閉じる値 25
     チャンク      推論    確認待ち     動いた     その他      合計  中継点ごと (秒)  メモ
        0   57.53   20.93    5.81    0.13   84.40  0.50 0.92 0.94 0.32  始めに爪を開いた
        1    1.84    0.59    2.46    0.14    5.03  0.52 0.66 0.82 0.32  
        2    0.63    0.56    2.33    0.16    3.68  0.48 0.74 0.64 0.32  
        3    0.64    0.52    2.41    0.13    3.70  0.64 0.64 0.62 0.34  
        4    0.59    0.55    2.03    0.10    3.26  0.64 0.64 0.40 0.14  
        5    0.66    1.17    2.56    0.07    4.47  0.46 0.40 0.52 0.95  爪→閉
        6    1.62    0.60    2.35    0.10    4.67  0.56 0.64 0.60 0.30  
        7    0.62    1.32    2.47    0.13    4.53  0.48 0.76 0.64 0.32  
        8    0.61    1.31    2.33    0.05    4.31  0.62 0.62 0.64 0.30  
        9    1.54    1.10    2.30    0.12    5.06  0.62 0.62 0.56 0.32  
       10    0.55    0.50    2.97    0.14    4.17  0.94 0.86 0.72 0.24  
       11    0.56    0.48    5.35    0.09    6.47  0.82 0.82 0.52 3.08  爪→開
       12    0.86    1.56    2.33    0.12    4.87  0.64 0.64 0.62 0.28  
       13    1.49    0.48    3.11    0.13    5.20  0.82 0.72 1.02 0.34  
       14    0.59       -       -    0.00    0.59    HOME
       合計   70.30   31.68   40.81    1.60  144.40
     中央値    0.64    0.60    2.44    0.12    4.53
   推論: 1 回目 57.53 秒 / 2 回目からの中央値 0.63 秒   中継点の間の中央値 0.62 秒 (states.csv の送った時刻)
   そのほかの行: framing 1  tilt_fix 1


1 の 26.9 秒（チャンク 0 の推論が終わってから、チャンク 1 の推論を始めるまで）の中身
- 20.9 秒：確認の Enter 待ち（--auto でないため。--auto なしで進めている）
- 3.1 秒：開始時に爪を開く。内訳は次のとおり。
  - daemon の set_gripper の 2.0 秒（DAY175 対策で、開け閉めの前に必ず sleep(2) している。GRIP_OPEN_DAEMON_WAIT=0 でも、この 2 秒は残る）
  - Mac 側の 0.8 秒
  - 0.3 秒ほど
- 2.7 秒：中継点 4 点を動かす（送り間隔 0.50・0.92・0.94 秒＋最後 0.3 秒）
- 0.13 秒：次の推論の前の、角度の読み取りと撮影
- HOME・位置合わせ・録画の立ち上げは、チャンク 0 の推論より前に済んでいる（録画の開始から推論の開始まで 0.3 秒）。なので 26.9 秒には入っていない。
- チャンク 11（爪を開く）が 5.35 秒かかったのも、同じ daemon の 2 秒のため。

直し方の案（どれも直していない）
- (a) 確認待ち：--auto で流す。または、1 回目だけ確認して以降は自動にする。
- (b) daemon の set_gripper の前の 2 秒：開くときは短くする（Pi 側の変更。DAY175 の不具合が戻らないかの確かめが要る）。
- (c) 開始時に爪を開く：lab_start の 7 ですでに開いている。なので「開いている」と分かっているときは開くのを省く（3.1 秒減る）。

4 の調べた結果（record_teach_demo.py。変えていない）
- 送り方：区間ごとに単発の send_angles を 1 回送る。speed は SPEED_SINGLE=20。daemon の送ったあとの待ちは SEND_WAIT_SEC=1.0 秒。
- 到着の確かめ：区間ごとの許容（2〜3°。run_pick_place と同じ）で、0.3 秒おきに読む。上限は 8 秒以上。
- 爪の待ち：閉じたあと 2.0 秒。開くときは daemon 2 秒＋Mac 2 秒。
- 止まっている区間は、学習データを作るとき（build_demo_episodes の idle の詰め）に詰めている。なので、お手本は「speed 20 で途切れずに動く」データになっている。
- お手本 deep_even10_v1（50 本）：動いている間の速さは中央 25.6°/秒、上位 5% で 30.6°/秒。お手本の 1 チャンク（1 秒）は、その速さで 1 秒ぶん動いた量。
- 193254（speed 20・12V 5A）の実行中：上位 5% は 27.3°/秒で、お手本とほぼ同じ。ただし、動いているのは実行時間の 46% だけ。1 チャンクに 2.0〜2.6 秒かかっている（お手本の約 2.4 倍）。
- --flow（speed 20）の見込み：
  - 途中の点 3 つ × 0.4〜0.5 秒＋最後の点 0.3〜0.5 秒で、1 チャンクあたり約 1.5〜2.0 秒。
  - アームの速さはお手本と同じで、止まる時間が減る分だけ速くなる。
- --speed 30 の見込み：
  - speed に比例するなら約 38°/秒で、お手本の 1.5 倍の速さで動く（比例かどうかは測っていない）。
  - ただし送る間隔の下限 0.4 秒があるので、1 チャンクは約 1.3〜1.6 秒より縮まない。
  - 「速く動いて少し止まる」形になり、お手本（一定の速さ）とは動きの形がずれる。
  - 重さで j1 が遅れる分（今は 2〜3°）が、速いと増える見込み。

送る間隔の下限を 0.4 秒にしたわけ
- 0.1 秒ごとの連打は、DAY287 以前にコントローラーに無視された。
- 193254 の単発の送り間隔（どれも着いた）の最短が 0.40 秒だった。なので、実機で通った最短の値を下限にした。
- ゲームパッドで「動いている途中に次の目標を送ると無視されて手前で止まる」ことがあった（11/5）。なので --flow では、途中の点が無視されることがありうる。最後の点は今までどおりの到着確認（動かなければ 1 回だけ再送）で拾う。

■ 実機で比べるコマンド（位置5・閉じる値25。Log35 の Pod につなぎ直すので、2 回目からは空打ちが短い）
1. 今まで:          ./lab_start.sh --model deep1 --log Log35 --grip-value 25
2. --flow:          ./lab_start.sh --model deep1 --log Log35 --grip-value 25 --flow
3. --flow --speed 30: ./lab_start.sh --model deep1 --log Log35 --grip-value 25 --flow --speed 30
比べ方:
  python3 pi05/chunk_timing.py <1 の試行> <2 の試行> <3 の試行>
  （試行は runs/pi05_policy/pi05_日時。最後の「比べる」表の 動いた中央・中継点中央・合計 を見る。確認の Enter の時間は 確認待ち の列に分けて出る）

■ 変えたファイル
- 修正：pi05/run_policy_client.py、lab_start.sh、test_lab_start.sh、pi05/test_rewind_correct.py
- 新規：pi05/policy_warmup.py、pi05/chunk_timing.py、pi05/test_flow_send.py、pi05/test_chunk_timing.py

■ 決めてほしいこと
1. --flow-tol の既定 5° と、送る間隔の下限 0.4 秒（上限 1.5 秒）は、こちらで決めた仮の値です。実機で比べたあとに、このままでよいか決めてください。
2. 26.9 秒の直し方の案 (a)〜(c) のうち、どれをやるか。(b) は Pi の daemon を変えることになります。
3. lab_start.sh に --flow / --speed N を足しました（比べるコマンドを打てるようにするため。依頼の文にはない追加です）。残してよいか決めてください。
