Chord error 2.5 -> 10 cm, shell work skipped outside the 0-0.75 m band. Sweep pairs -39%, prepare -60%, near-ready 3-8% faster than L115 but still +13..+22% vs L109. Floor offset 7.88 mm; captures match L115 by eye; fast tier, walk audits, Clang/GCC W1/W8/W12 determinism green. Not for merge yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
80 lines
3.7 KiB
Python
80 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Measure L119 floor zero crossings at three route stations per passage."""
|
|
from __future__ import annotations
|
|
|
|
import csv
|
|
import json
|
|
import math
|
|
import os
|
|
import re
|
|
import statistics
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[4]
|
|
OUT = ROOT / "Saved/Linux/l119/density-probe"
|
|
BINARY = ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-clang"
|
|
DATA = ROOT / "Standalone/data/owner_world.json"
|
|
SLOPE = re.compile(
|
|
r"^\[L115DensitySlopeSample\] passage=(\S+) station=(\S+) s_m=([\d.]+) "
|
|
r".*?planned_floor_m=(-?[\d.]+) root_floor_m=(-?[\d.]+|nan) "
|
|
r"residual_m=(-?[\d.]+|nan)", re.M)
|
|
|
|
|
|
def main() -> int:
|
|
OUT.mkdir(parents=True, exist_ok=True)
|
|
log = OUT / "owner4-clang.log"
|
|
layout = OUT / "layout.json"
|
|
command = [
|
|
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
|
"timeout", "1740s", str(BINARY), str(DATA), "--world-assembler-prototype",
|
|
"--stream-benchmark", "--stream-pipeline", "--workers=12", "--clip-radius=3",
|
|
"--max-clip-level=8", "--max-level=8", "--camera=8,16,-372.2626953125,0,0",
|
|
"--audit-resolved-layout-passages", f"--resolved-layout-output={layout}",
|
|
]
|
|
with log.open("w", encoding="utf-8") as stream:
|
|
result = subprocess.run(command, cwd=ROOT,
|
|
env={**os.environ,
|
|
"VOXELFORGE_L115_DENSITY_PROFILE": "1"},
|
|
stdout=stream, stderr=subprocess.STDOUT,
|
|
check=False, timeout=1740)
|
|
if result.returncode:
|
|
raise SystemExit(f"L119 density probe failed: {log}")
|
|
text = log.read_text(encoding="utf-8", errors="replace")
|
|
groups: dict[tuple[str, str], list[dict]] = {}
|
|
for passage, station, distance, planned, root, residual in SLOPE.findall(text):
|
|
root_value = float(root) if root != "nan" else math.nan
|
|
residual_value = float(residual) if residual != "nan" else math.nan
|
|
groups.setdefault((passage, station), []).append({
|
|
"route_s_m": float(distance), "planned_floor_m": float(planned),
|
|
"root_floor_m": root_value, "offset_m": residual_value})
|
|
summary = []
|
|
with (OUT / "zero-crossing-offsets.csv").open("w", newline="", encoding="utf-8") as stream:
|
|
writer = csv.DictWriter(stream, fieldnames=("passage", "station", "route_s_m",
|
|
"planned_floor_m", "root_floor_m", "offset_m"))
|
|
writer.writeheader()
|
|
for (passage, station), samples in sorted(groups.items()):
|
|
for sample in samples:
|
|
writer.writerow({"passage": passage, "station": station, **sample})
|
|
finite = [sample["offset_m"] for sample in samples
|
|
if math.isfinite(sample["offset_m"])]
|
|
summary.append({"passage": passage, "station": station,
|
|
"samples": len(samples), "finite_roots": len(finite),
|
|
"max_abs_offset_m": max(map(abs, finite)) if finite else None,
|
|
"median_abs_offset_m": statistics.median(map(abs, finite))
|
|
if finite else None,
|
|
"p95_abs_offset_m": sorted(map(abs, finite))[
|
|
min(len(finite)-1, math.ceil(0.95*len(finite))-1)]
|
|
if finite else None})
|
|
if not summary or any(item["samples"] != 51 for item in summary):
|
|
raise RuntimeError("L119 density profile is missing 51-sample route stations")
|
|
(OUT / "zero-crossing-summary.json").write_text(
|
|
json.dumps(summary, indent=2) + "\n", encoding="utf-8")
|
|
print(f"[L119DensityProbe] exit={result.returncode} stations={len(summary)} "
|
|
f"log={log.relative_to(ROOT)}", flush=True)
|
|
return result.returncode
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|