7e4ef6f98b
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
33 lines
2.4 KiB
Python
33 lines
2.4 KiB
Python
"""Validate full registered trajectory and decode both deliverable videos."""
|
|
import json, subprocess
|
|
import numpy as np
|
|
from l20_calibrated import Calibration, ROOT
|
|
|
|
out=ROOT/'output/l20_2047635068/bottle_grasp'
|
|
m=np.load(out/'registered_motion.npz'); c=Calibration()
|
|
names=list(m['joint_names']); q=m['qpos']
|
|
limits=np.array([c.urdf_limits[n] for n in names])
|
|
coupling=max(float(np.max(np.abs(q[:,names.index(n)]-np.interp(q[:,names.index(a)],x,y)))) for n,(a,x,y) in c.curves.items())
|
|
report=dict(frames=len(q),finite=all(bool(np.isfinite(m[k]).all()) for k in ['qpos','wrist_pos','wrist_quat_wxyz','bottle_pos','bottle_quat_wxyz']),
|
|
limit_violations=int(np.sum((q<limits[:,0]-1e-8)|(q>limits[:,1]+1e-8))),
|
|
max_passive_coupling_error_rad=coupling,
|
|
max_penetration_mm=float(m['penetration_m'].max()*1000),
|
|
frames_above_1_5_mm=int(np.sum(m['penetration_m']>.0015)),
|
|
wrist_axis_range_m=np.ptp(m['wrist_pos'],axis=0).tolist(),
|
|
max_joint_step_rad=float(np.abs(np.diff(q,axis=0)).max()),
|
|
frames_with_joint_step_above_0_2_rad=int(np.sum(np.max(np.abs(np.diff(q,axis=0)),axis=1)>.2)),
|
|
max_wrist_step_m=float(np.linalg.norm(np.diff(m['wrist_pos'],axis=0),axis=1).max()),
|
|
max_command_quantization_error_rad=float(np.max(np.abs(np.array([c.decode(cmd,names) for cmd in m['command_u8']])-q))),videos={})
|
|
for filename,expected in [('contact_registration.mp4',len(q)),('physics_test.mp4',len(np.load(out/'physics_motion.npz')['qpos']))]:
|
|
path=out/filename
|
|
probe=json.loads(subprocess.check_output(['ffprobe','-v','error','-count_frames','-select_streams','v:0','-show_entries','stream=width,height,nb_read_frames,r_frame_rate','-of','json',str(path)]))['streams'][0]
|
|
subprocess.run(['ffmpeg','-v','error','-i',str(path),'-f','null','-'],check=True)
|
|
assert int(probe['nb_read_frames'])==expected
|
|
report['videos'][filename]=dict(probe,full_decode_passed=True)
|
|
report['geometry_checks_passed']=report['finite'] and report['limit_violations']==0 and coupling<1e-8 and report['frames_above_1_5_mm']==0
|
|
report['physical_retention_passed']=json.loads((out/'physics_validation.json').read_text())['retained']
|
|
report['execution_ready']=False
|
|
report['execution_limitations']=['Local pose jumps remain; no joint velocity constrained optimization','Free object retention test failed','Object trajectory is an inferred registration target']
|
|
(out/'delivery_validation.json').write_text(json.dumps(report,indent=2))
|
|
print(json.dumps(report,indent=2))
|