AlexWortega commited on
Commit
8fe6fb5
·
verified ·
1 Parent(s): 6912d12

Upload tinyvla2/scripts/eval_libero_canon.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. tinyvla2/scripts/eval_libero_canon.py +47 -10
tinyvla2/scripts/eval_libero_canon.py CHANGED
@@ -47,6 +47,14 @@ def main():
47
  p.add_argument("--n-action-steps", type=int, default=25,
48
  help="actions executed per predicted chunk before re-planning")
49
  p.add_argument("--grip-mode", default="threshold", choices=["threshold", "linear"])
 
 
 
 
 
 
 
 
50
  p.add_argument("--save-video-dir", type=Path, default=None)
51
  args = p.parse_args()
52
 
@@ -117,18 +125,30 @@ def main():
117
  "morphology": morph,
118
  "embodiment_id": torch.tensor([0], device="cuda")}
119
 
120
- def decode(chunk_norm):
121
- """(chunk, >=7) normalized canonical -> (chunk-1, 7) OSC actions."""
122
- phys = chunk_norm[:, :7] * span / 2 + mid
123
- phys = phys[1:] # drop the identically-zero anchor delta
 
 
 
 
 
 
 
 
 
 
124
  osc = np.zeros((len(phys), 7), dtype=np.float32)
125
  osc[:, :6] = phys[:, :6] * mscale
126
- if args.grip_mode == "threshold":
127
- osc[:, 6] = np.where(phys[:, 6] > fit["grip_threshold"], -1.0, 1.0)
128
- else:
129
- osc[:, 6] = phys[:, 6] * fit["grip_a"] + fit["grip_b"]
130
  return np.clip(osc, -1.0, 1.0)
131
 
 
 
 
 
 
132
  fps = meta.fps
133
  total = succ = 0
134
  per_task = {}
@@ -149,6 +169,7 @@ def main():
149
  frames = [] if args.save_video_dir else None
150
  latent, last_refresh = None, -1e9
151
  queue, done, step_i, ep_succ = [], False, 0, False
 
152
  while not done and step_i < args.max_steps:
153
  if not queue:
154
  batch = to_batch(obs, task_text)
@@ -159,8 +180,24 @@ def main():
159
  batch["semantic_latent"] = latent
160
  with torch.autocast("cuda", torch.bfloat16):
161
  pred = policy.predict_action_chunk(batch)[0].float().cpu().numpy()
162
- queue = list(decode(pred)[: args.n_action_steps])
163
- act = queue.pop(0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  try:
165
  obs, _, terminated, truncated, info = env.step(act[None])
166
  except ValueError:
 
47
  p.add_argument("--n-action-steps", type=int, default=25,
48
  help="actions executed per predicted chunk before re-planning")
49
  p.add_argument("--grip-mode", default="threshold", choices=["threshold", "linear"])
50
+ p.add_argument("--decode", default="servo", choices=["servo", "scaled"],
51
+ help="servo (default): integrate predicted deltas into a desired EE pose and "
52
+ "command the error against the measured pose. The naive scaled decode "
53
+ "replays achieved motion as a command, which the OSC controller "
54
+ "under-tracks: GT round-trip replay scores 1/5 scaled vs 3/5 servo "
55
+ "against a 4/5 raw-GT ceiling.")
56
+ p.add_argument("--kp", type=float, default=120.0)
57
+ p.add_argument("--kr", type=float, default=12.0)
58
  p.add_argument("--save-video-dir", type=Path, default=None)
59
  args = p.parse_args()
60
 
 
125
  "morphology": morph,
126
  "embodiment_id": torch.tensor([0], device="cuda")}
127
 
128
+ def to_physical(chunk_norm):
129
+ """(chunk, >=7) normalized canonical -> (chunk-1, 7) physical deltas.
130
+
131
+ Drops the anchor delta: sidecars built from observation state have
132
+ a_pose == s_pose, so chunk[0] is identically zero.
133
+ """
134
+ return (chunk_norm[:, :7] * span / 2 + mid)[1:]
135
+
136
+ def grip_cmd(openness):
137
+ if args.grip_mode == "threshold":
138
+ return -1.0 if openness > fit["grip_threshold"] else 1.0
139
+ return float(np.clip(openness * fit["grip_a"] + fit["grip_b"], -1, 1))
140
+
141
+ def decode_scaled(phys):
142
  osc = np.zeros((len(phys), 7), dtype=np.float32)
143
  osc[:, :6] = phys[:, :6] * mscale
144
+ osc[:, 6] = [grip_cmd(g) for g in phys[:, 6]]
 
 
 
145
  return np.clip(osc, -1.0, 1.0)
146
 
147
+ def measured_pose(obs):
148
+ rs = obs["robot_state"]
149
+ return (np.asarray(rs["eef"]["pos"]).flatten(),
150
+ Rotation.from_quat(np.asarray(rs["eef"]["quat"]).flatten()))
151
+
152
  fps = meta.fps
153
  total = succ = 0
154
  per_task = {}
 
169
  frames = [] if args.save_video_dir else None
170
  latent, last_refresh = None, -1e9
171
  queue, done, step_i, ep_succ = [], False, 0, False
172
+ des_p, des_R = None, None
173
  while not done and step_i < args.max_steps:
174
  if not queue:
175
  batch = to_batch(obs, task_text)
 
180
  batch["semantic_latent"] = latent
181
  with torch.autocast("cuda", torch.bfloat16):
182
  pred = policy.predict_action_chunk(batch)[0].float().cpu().numpy()
183
+ phys = to_physical(pred)[: args.n_action_steps]
184
+ if args.decode == "servo":
185
+ queue = list(phys) # consumed as deltas, servoed below
186
+ des_p, des_R = measured_pose(obs) # re-anchor each re-plan
187
+ else:
188
+ queue = list(decode_scaled(phys))
189
+ if args.decode == "servo":
190
+ d = queue.pop(0)
191
+ cur_p, cur_R = measured_pose(obs)
192
+ des_p = des_p + d[:3]
193
+ des_R = Rotation.from_rotvec(d[3:6]) * des_R
194
+ act = np.zeros(7, dtype=np.float32)
195
+ act[:3] = args.kp * (des_p - cur_p)
196
+ act[3:6] = args.kr * (des_R * cur_R.inv()).as_rotvec()
197
+ act[6] = grip_cmd(d[6])
198
+ act = np.clip(act, -1, 1)
199
+ else:
200
+ act = queue.pop(0)
201
  try:
202
  obs, _, terminated, truncated, info = env.step(act[None])
203
  except ValueError: