(args)
| 11 | |
| 12 | |
| 13 | def main(args): |
| 14 | import mujoco |
| 15 | |
| 16 | # Load the scene |
| 17 | xml_path = str(ASSETS_DIR / "scenes" / "franka_emika_panda" / "scene_blockpush.xml") |
| 18 | model = mujoco.MjModel.from_xml_path(xml_path) |
| 19 | data = mujoco.MjData(model) |
| 20 | |
| 21 | from avp_stream import VisionProStreamer |
| 22 | streamer = VisionProStreamer(ip=args.ip, record=False) |
| 23 | |
| 24 | # attach_to format: [x, y, z, yaw_degrees] |
| 25 | attach_to = [0.2, 1.0, 0.7, -90] |
| 26 | |
| 27 | streamer.configure_mujoco( |
| 28 | xml_path=xml_path, |
| 29 | model=model, |
| 30 | data=data, |
| 31 | relative_to=attach_to, |
| 32 | grpc_port=args.port, |
| 33 | ) |
| 34 | |
| 35 | streamer.start_webrtc() |
| 36 | |
| 37 | # Wait for connection and USDZ transfer |
| 38 | print("[CROSS-NETWORK] Waiting for WebRTC connection and scene transfer...") |
| 39 | if not streamer.wait_for_sim_channel(timeout=60.0): |
| 40 | print("Timeout or error waiting for connection!") |
| 41 | return |
| 42 | |
| 43 | |
| 44 | logs_dir = ASSETS_DIR / "logs" |
| 45 | episodes = sorted(logs_dir.glob("ep*.npz")) |
| 46 | |
| 47 | try: |
| 48 | for ep_idx in range(1, min(5, len(episodes) + 1)): |
| 49 | traj_path = logs_dir / f"ep{ep_idx}.npz" |
| 50 | if not traj_path.exists(): |
| 51 | continue |
| 52 | |
| 53 | print(f"📼 Playing episode {ep_idx}...") |
| 54 | traj = np.load(traj_path) |
| 55 | |
| 56 | qpos_log = traj["qpos"] |
| 57 | qvel_log = traj["qvel"] |
| 58 | ctrl_log = traj["ctrl"] |
| 59 | mocap_log = traj["mocap"] |
| 60 | |
| 61 | T = qpos_log.shape[0] |
| 62 | |
| 63 | # Initialize state |
| 64 | data.qpos[:] = qpos_log[0] |
| 65 | data.qvel[:] = qvel_log[0] |
| 66 | |
| 67 | if mocap_log.shape[0] > 0: |
| 68 | data.mocap_pos[1] = mocap_log[0, :3] |
| 69 | data.mocap_quat[1] = mocap_log[0, 3:] |
| 70 |
no test coverage detected