#!/usr/bin/env python3 """log450_table.py — 11/6 (Log22) の実機推論9回を, ゲームパッドの補正と推論の実行時間でならべる (LOG450). 使い方: python3 log450_table.py /Volumes/KIOXIA/r2r2r-data/runs/pi05_policy - 11/6 の9回: 回ごとの結果・つかんだ推論・離した推論・ゲームパッドの補正 (始めと終わりの実測の差) - 推論1回分を実行するのにかかった時間 (t_exec_end - t_exec_start) を 10/31・11/1・11/6 でならべる 元の記録は読むだけ (書かない). """ import glob import json import statistics as st import sys from datetime import datetime from pathlib import Path ROOT = Path(sys.argv[1] if len(sys.argv) > 1 else "/Volumes/KIOXIA/r2r2r-data/runs/pi05_policy") def load(d): rows = [json.loads(x) for x in open(d / "log.jsonl", encoding="utf-8")] try: trial = json.load(open(d / f"{d.name}.json", encoding="utf-8")) except FileNotFoundError: trial = {} return rows, trial def med(xs): return round(st.median(xs), 2) if xs else None print("## 11/6 の9回 (pi05_20261106_*)\n") print("| 回 | 記録 | 結果 | 実行した推論 | 爪を閉じた推論 | 爪を開いた推論 | ゲームパッドの補正 (推論 何番のあと: 秒・送った回数・実測の変化) |") print("|---|---|---|---|---|---|---|") all_corr = [] for n, d in enumerate(sorted(ROOT.glob("pi05_20261106_*")), 1): rows, trial = load(d) ex = [r for r in rows if r.get("type") is None and r.get("executed")] close = [r["chunk"] for r in ex if r.get("grip_cmd") == 1] open_ = [r["chunk"] for r in ex if r.get("grip_cmd") == 0] cs = [] for r in rows: if r.get("type") == "correction" and r.get("device") == "gamepad": a, b = r["start_pose"], r["measured_after"] dj = [(k, b[k] - a[k]) for k in range(5) if abs(b[k] - a[k]) >= 1.0] txt = ", ".join(f"j{k} {v:+.1f}°" for k, v in dj) or "変化 1° 未満" cs.append(f"推論{r['after_chunk']}: {r['duration_s']:.1f}秒・{r['steps_sent']}回・{txt}") all_corr.append({"run": d.name, "after": r["after_chunk"], "dur": r["duration_s"], "sent": r["steps_sent"], "ignored": r.get("pad_ignored"), "dj": dj, "out": r.get("outside_envelope"), "after_close": bool(close) and r["after_chunk"] >= close[0]}) t0 = datetime.strptime(d.name[5:], "%Y%m%d_%H%M%S").strftime("%H:%M") res = {"success": "成功", "failure": "失敗"}.get(trial.get("outcome"), "記録なし") print(f"| {n} | {d.name} ({t0}) | {res} | {len(ex)} | {close} | {open_} | {' / '.join(cs)} |") print("\n## ゲームパッドの補正 (19回)\n") before = [c for c in all_corr if not c["after_close"]] after = [c for c in all_corr if c["after_close"]] for name, cs in (("つかむ前", before), ("つかんだあと", after), ("合わせて", all_corr)): ds = [c["dur"] for c in cs] print(f"- {name}: {len(cs)}回 かかった時間 中央 {med(ds)}秒・最短 {min(ds):.1f}秒・最長 {max(ds):.1f}秒・合計 {sum(ds):.1f}秒" f" 送った回数の中央 {med([c['sent'] for c in cs])} 受付なし 合計 {sum(c['ignored'] or 0 for c in cs)}") for name, cs in (("つかむ前", before), ("つかんだあと", after)): js = {} for c in cs: for k, v in c["dj"]: js.setdefault(k, []).append(v) print(f"- {name} に動いた関節: " + ", ".join(f"j{k} {len(v)}回 (中央 {med(v):+.1f}°・{min(v):+.1f}〜{max(v):+.1f}°)" for k, v in sorted(js.items()))) print("- 学習データの範囲の外で終えた補正: " + (", ".join(f"{c['run']} 推論{c['after']}のあと j{c['out']}" for c in all_corr if c["out"]) or "なし")) print("\n## 推論1回分を実行するのにかかった時間 (t_exec_end - t_exec_start)\n") print("| 日 | 記録の数 | 実行した推論 | 中央 | 最短 | 最長 | 中継点4点の推論の中央 |") print("|---|---|---|---|---|---|---|") for day in ("20261031", "20261101", "20261106"): ds, d4 = [], [] dirs = sorted(ROOT.glob(f"pi05_{day}_*")) for d in dirs: rows, _ = load(d) for r in rows: if r.get("type") is None and r.get("executed") and r.get("t_exec_start"): t = r["t_exec_end"] - r["t_exec_start"] ds.append(t) if len(r.get("sent_targets") or []) == 4 and r.get("grip_cmd") is None: d4.append(t) if ds: print(f"| {day[4:6]}/{day[6:]} | {len(dirs)} | {len(ds)} | {med(ds)}秒 | {min(ds):.2f}秒 | {max(ds):.2f}秒 | {med(d4)}秒 ({len(d4)}回) |") print("\n## 1回の補正にかかった時間 (correction の accept 行の t_end - t_start)\n") print("| 日 | 直し方 | 補正の数 | 中央 | 最短 | 最長 | 合計 |") print("|---|---|---|---|---|---|---|") for day in ("20261031", "20261101", "20261106"): ds, dev = [], set() for d in sorted(ROOT.glob(f"pi05_{day}_*")): rows, _ = load(d) for r in rows: if r.get("type") == "correction" and r.get("action") == "accept": ds.append(r["t_end"] - r["t_start"]) dev.add("ゲームパッド (p)" if r.get("device") == "gamepad" else "キー (c)") if ds: print(f"| {day[4:6]}/{day[6:]} | {' / '.join(sorted(dev))} | {len(ds)} | {med(ds)}秒 | {min(ds):.1f}秒 | {max(ds):.1f}秒 | {sum(ds):.1f}秒 |")