3 点を反映しました。変更は pi05/run_policy_client.py のみ(未コミット)。 変えた行 ┌─────────┬─────────────────────────────────────────────────────────────────┐ │ 行 │ 変更 │ ├─────────┼─────────────────────────────────────────────────────────────────┤ │ 23-26 │ docstring: 「動きが止まらない / 読めない / │ │ │ 送信が失敗したときは送り直しをやめる」 │ ├─────────┼─────────────────────────────────────────────────────────────────┤ │ │ from j0_sweep_scan import SEND_WAIT_SEC, SPEED, │ │ 81 │ _send_and_wait_arrival — SPEED=20 / SEND_WAIT=1.0 │ │ │ は本線の値をそのまま import(二重定義しない) │ ├─────────┼─────────────────────────────────────────────────────────────────┤ │ 83-85 │ visual_servo_pick から daemon_send_angles を追加 import │ ├─────────┼─────────────────────────────────────────────────────────────────┤ │ 205-206 │ _fmt6()(記録用に 6 関節を丸める小物) │ ├─────────┼─────────────────────────────────────────────────────────────────┤ │ │ read_until_still() を変更(A6): 戻り値が (角度 or None, │ │ 209-235 │ 止まったか, 直前に読めた角度 or None) の 3 │ │ │ つに。読み取りに失敗したら 1 番目は │ │ │ None(古い値を代わりに返さない)、3 番目に最後に読めた値 │ ├─────────┼─────────────────────────────────────────────────────────────────┤ │ 237-336 │ settle_target を変更(A5・A2・A6) │ ├─────────┼─────────────────────────────────────────────────────────────────┤ │ 550-551 │ 呼び出し側は変更なし │ └─────────┴─────────────────────────────────────────────────────────────────┘ settle_target の変更点: - A5: 送り直しは _send_and_wait_arrival をやめ、その中で使っている 1 回だけ送る層 daemon_send_angles(tgt.tolist(), speed=SPEED, wait=SEND_WAIT_SEC) を直接呼ぶ。中で再送しないので sends が実際の送信回数と一致し、上限を超えません。送ったあとは read_until_still() で止まるのを待ってから判定。例外が出たら sent: false と error を記録して send_failed で終了(チャンク本体の送信は今までどおり _send_and_wait_arrival) - A2: still=False(2.0 秒で打ち切り)なら追加の送り直しをやめ、[WARN] を出して not_still で戻る。判定順は「tol 以内か → 止まっているか → 上限か」。tol 以内なら動いていても送らないので、そこでは警告を出しません - A6: 途中で読めなくなったら read_failed で終了し、final_err / joint / final_actual は null。最後に読めた値は last_valid_actual に別に残す。disabled も含め、どの reason でも同じ形(reason / tol / sends / final_err / joint / final_actual / last_valid_actual / tries) 止める条件は増えていません(settle_target はチャンクループを抜けず、exit_code も触りません)。_send_and_wait_arrival 本体・HOME・SPEED・SEND_WAIT・J4_SAFE・J 1_SAFE_MAX・apply_limits・h・q・グリッパー・ドライランは未変更です。 確認結果(偽の daemon・偽の時計、10 ケースすべて OK) OK 1_converged OK 6_read_failed_first OK 2_not_converged OK 7_dryrun OK 3_retries0 OK 8_cap_2_sends OK 4_not_still_from_start OK 9_not_still_after_1 OK 5_send_failed OK 10_read_failed_after_send 前回の 7 つ(抜粋): - 1 +2.0° → +0.4°: converged / settle の送信 1 回(daemon_send_angles(50.0, speed=20, wait=1.0)) - 3 --settle-retries 0: {"reason":"disabled","sends":0,"final_err":null,"joint" :null,"final_actual":null,"last_valid_actual":null,"tries":[]} — ほかと同じ形、settle の読みも送りも 0 回 - 5 送信が例外: send_failed / try に "sent": false, "error": "RuntimeError: ..." - 7 ドライラン: 本体も settle も送信 0 回、settle キーなし 今回ふえた 3 つ: 8. 上限 2 回を超えない — どの経路でも daemon_send_angles の呼び出しは最大 2 回。実測は本体 1 回 + settle 2 回で、sends: 2 と一致(旧版は内部再送で 3 回になり得ました) 9. 1 回目のあと止まらない → not_still [SETTLE] 送り直し 1 回目 最大ずれ 2.00°(関節 j1)→ 5.90° (動きが止まらないまま 2.0 秒で打ち切り) [SETTLE] not_still (動きが止まらない) 送信 1 回 最後の最大ずれ 5.90°(関節 j1) [WARN] ... settle: {"reason":"not_still","sends":1,...} try: {"still": false} 送り直しは 1 回でやめ、2 回目は送っていません。 10. 送り直しのあとの読み取り失敗 → 古い値で判定しない [SETTLE] 送り直し 1 回目 最大ずれ 2.00°(関節 j1)→ 読めず [SETTLE] read_failed (関節角を読めない) 送信 1 回 最後の最大ずれ 不明 settle: {"reason":"read_failed","sends":1,"final_err":null,"joint":null,"final_ actual":null, "last_valid_actual":[0.0, 50.4, 0.0, 0.0, -40.0, -30.0]} この last_valid_actual は目標から 0.4° のずれ、つまり古い値を使えば converged と誤記録される状況です。新しい版では read_failed のままで、final_* は null、拾えた値は last_valid_actual に分けて残っています。 また 4_not_still_from_start(settle に入った時点ですでに動き続けている)では、送信 0 回で not_still を返して何も送っていません。