auto-iter 20260513-2231: GX019817 RoPE skip, 4 PLY done ready for stage06
This commit is contained in:
61
scripts/dvl_focal_sweep.py
Normal file
61
scripts/dvl_focal_sweep.py
Normal file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test multiple focal lengths on DVL and compare trajectory drift."""
|
||||
import subprocess, csv, sys, math
|
||||
from pathlib import Path
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
FRAMES = '/home/cosma/cosma-pipeline/data/20260505-Lepradet/frames/AUV210/GX039839'
|
||||
START = '2026-05-05T08:33:41'
|
||||
LABEL = 'GX039839'
|
||||
SCRIPT = '/home/cosma/cosma-qc/scripts/dvl_optical_full.py'
|
||||
|
||||
# focal in px equivalent to W/2 / tan(fov/2). W=518
|
||||
# fov 100°→f=217, 110°→f=185, 122°→f=143, 130°→f=121, 140°→f=94, 150°→f=70
|
||||
# But focal in px doesn't directly map to FOV unless we use that conversion. We pass --fov-deg.
|
||||
fovs = [90, 100, 110, 122, 135, 150]
|
||||
|
||||
results = []
|
||||
for fov in fovs:
|
||||
out_csv = f'/tmp/sweep_fov{fov}.csv'
|
||||
print(f'[sweep] fov={fov}', flush=True)
|
||||
r = subprocess.run(['python3', SCRIPT, '--frames-dir', FRAMES, '--altitude', '1.5',
|
||||
'--fov-deg', str(fov), '--fps', '1.0', '--start-iso', START,
|
||||
'--label', LABEL, '--out', out_csv], capture_output=True, text=True, timeout=600)
|
||||
if r.returncode != 0:
|
||||
print(f' FAIL: {r.stderr[-300:]}', flush=True)
|
||||
continue
|
||||
# parse last position + drift metrics
|
||||
rows = list(csv.DictReader(open(out_csv)))
|
||||
e = [float(r['east_m']) for r in rows]
|
||||
n = [float(r['north_m']) for r in rows]
|
||||
h = [float(r['heading_deg']) for r in rows]
|
||||
end_x, end_y = e[-1], n[-1]
|
||||
end_dist = math.sqrt(end_x**2 + end_y**2)
|
||||
path_len = sum(math.sqrt((e[i]-e[i-1])**2 + (n[i]-n[i-1])**2) for i in range(1, len(e)))
|
||||
bbox = (max(e)-min(e), max(n)-min(n))
|
||||
results.append({'fov': fov, 'csv': out_csv, 'end_x': end_x, 'end_y': end_y,
|
||||
'end_dist': end_dist, 'path_len': path_len, 'bbox': bbox, 'rows': rows,
|
||||
'e_arr': e, 'n_arr': n, 'h_arr': h})
|
||||
print(f' end=({end_x:.1f},{end_y:.1f}) dist={end_dist:.1f}m path={path_len:.1f}m bbox={bbox}', flush=True)
|
||||
|
||||
# Plot all trajectories
|
||||
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
|
||||
axes = axes.flatten()
|
||||
for ax, res in zip(axes, results):
|
||||
ax.plot(res['e_arr'], res['n_arr'], '-b', linewidth=0.8)
|
||||
ax.plot(res['e_arr'][0], res['n_arr'][0], 'go', markersize=8)
|
||||
ax.plot(res['e_arr'][-1], res['n_arr'][-1], 'r^', markersize=8)
|
||||
ax.set_xlabel('East (m)'); ax.set_ylabel('North (m)')
|
||||
ax.set_title(f'FOV={res["fov"]}° bbox=({res["bbox"][0]:.0f}×{res["bbox"][1]:.0f})m\nend_dist={res["end_dist"]:.1f}m path={res["path_len"]:.0f}m')
|
||||
ax.set_aspect('equal'); ax.grid(True, alpha=0.3)
|
||||
plt.suptitle(f'DVL focal sweep — {LABEL} (assume closed-loop survey → smaller end_dist=better)')
|
||||
plt.tight_layout()
|
||||
plt.savefig('/tmp/sweep_focal.png', dpi=110, bbox_inches='tight')
|
||||
print('[plot] /tmp/sweep_focal.png', flush=True)
|
||||
|
||||
# Summary
|
||||
print('\n=== Summary ===')
|
||||
for r in sorted(results, key=lambda x: x['end_dist']):
|
||||
print(f"FOV={r['fov']}°: end_dist={r['end_dist']:.1f}m path={r['path_len']:.0f}m bbox={r['bbox'][0]:.0f}×{r['bbox'][1]:.0f}m")
|
||||
Reference in New Issue
Block a user