ttll0928's picture
Initial release: RyWorld VLN stage1 discrete step15000 ckpt + eval pkg
4a61963
"""Per-episode metric extraction (NE / TL / SPL / OSR / nDTW / shortest_path)."""
import re
import sys
log_path = sys.argv[1]
log = open(log_path).read()
# Per-episode JSON-like block — capture ALL metrics
pat = re.compile(
r'"shortest_path_length":\s*([\d.]+).*?'
r'"NE":\s*([\d.]+).*?'
r'"success":\s*([\d.]+).*?'
r'"osr":\s*([\d.]+).*?'
r'"TL":\s*([\d.]+).*?'
r'"spl":\s*([\d.]+).*?'
r'"ndtw":\s*([\d.]+).*?'
r'"steps":\s*(\d+).*?'
r'"trajectory_id":\s*"([^"]+)".*?'
r'"fail_reason":\s*"([^"]+)"',
re.S,
)
finishes = re.compile(
r"\[(\d+)/30\]\[step_index:(\d+)\] finish: \[trajectory_id:([^\]]+)\]"
r"\[duration:([\d.]+) s\]\[step_count:(\d+)\]\[fps:([\d.]+)\]\[result:([^\]]+)\]"
)
per = {}
for m in pat.finditer(log):
spl_geo, ne, succ, osr, tl, spl, ndtw, steps, tid, reason = m.groups()
per[tid] = dict(
spl_geo=float(spl_geo), NE=float(ne), success=float(succ),
osr=float(osr), TL=float(tl), SPL=float(spl), nDTW=float(ndtw),
steps=int(steps), reason=reason,
)
H = "# | trajectory_id | result | NE | shortP | TL | SPL | OSR | nDTW | steps | sec | fps "
print(H)
print("-" * len(H))
agg = {k: 0.0 for k in ["NE", "TL", "SPL", "OSR", "nDTW", "spl_geo"]}
succ_n = 0
n = 0
fail_tally = {}
for m in finishes.finditer(log):
idx, step_idx, tid_full, dur, stepc, fps, result = m.groups()
parts = tid_full.split("_")
if len(parts) >= 8 and "_".join(parts[: len(parts) // 2]) == "_".join(parts[len(parts) // 2 :]):
tid_key = "_".join(parts[: len(parts) // 2])
else:
tid_key = tid_full
e = per.get(tid_key) or {}
NE = e.get("NE", float("nan"))
TL = e.get("TL", float("nan"))
SPL = e.get("SPL", float("nan"))
OSR = e.get("osr", float("nan"))
nDTW = e.get("nDTW", float("nan"))
spg = e.get("spl_geo", float("nan"))
succ = e.get("success", 1.0 if result == "success" else 0.0)
reason = e.get("reason", result)
n += 1
succ_n += int(succ == 1.0)
fail_tally[reason] = fail_tally.get(reason, 0) + 1
for k, v in [("NE", NE), ("TL", TL), ("SPL", SPL), ("OSR", OSR), ("nDTW", nDTW), ("spl_geo", spg)]:
if v == v:
agg[k] += v
print(
f"{idx:>2} | {tid_key[:24]:<24} | {result[:15]:<15} | "
f"{NE:>4.2f} | {spg:>6.2f} | {TL:>4.2f} | {SPL:>4.2f} | "
f"{OSR:>4.2f} | {nDTW:>4.2f} | {stepc:>5} | {float(dur):>4.0f} | {float(fps):>4.1f}"
)
print("-" * len(H))
if n:
print(f"\nAggregates over {n} episodes:")
print(f" SR = {succ_n}/{n} = {100*succ_n/n:5.1f}%")
print(f" NE = {agg['NE']/n:5.2f} m (lower better; success_radius = 3.0 m)")
print(f" SPL = {agg['SPL']/n:5.3f} (success-weighted, lower path = better)")
print(f" OSR = {agg['OSR']/n:5.3f} (oracle success rate — could have stopped within radius at any step)")
print(f" nDTW = {agg['nDTW']/n:5.3f} (path alignment 0-1, higher better)")
print(f" TL = {agg['TL']/n:5.2f} m (mean trajectory length)")
print(f" shortest_path = {agg['spl_geo']/n:5.2f} m (mean geodesic)")
print(f" fail_reasons: {fail_tally}")