# ๐Ÿ“Š Pusher-v5 ๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ ๋ฐ ๊ทœ๊ฒฉ์„œ AI๊ฐ€ ํ™˜๊ฒฝ์„ ์กฐ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋ฉ”ํŠธ๋ฆญ/๋กœ๊ทธ/๋Œ€์‹œ๋ณด๋“œ/์›น์†Œ์ผ“ API๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ๋ฐ˜๋“œ์‹œ ์ค€์ˆ˜ํ•ด์•ผ ํ•˜๋Š” ์—„๊ฒฉํ•œ ๋ฐ์ดํ„ฐ ๊ทœ๊ฒฉ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์ •์˜๋˜์ง€ ์•Š์€ ๋ณ€์ˆ˜๋‚˜ ์ž„์˜์˜ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€/์‚ญ์ œํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. --- ## 1. Pusher-v5 ํ™˜๊ฒฝ ๊ทœ๊ฒฉ (Environment Specification) * **Observation Space (23์ฐจ์› ์—ฐ์† ๋ฒกํ„ฐ, Box(-inf, inf, (23,), float64))**: * `obs[0:7]`: 7๊ฐœ ์กฐ์ธํŠธ ๊ฐ๋„ (Joint angles, rad) * `obs[7:14]`: 7๊ฐœ ์กฐ์ธํŠธ ๊ฐ์†๋„ (Joint velocities) * `obs[14:17]`: Fingertip / Pusher ๋๋‹จ 3D ์œ„์น˜ (x, y, z) * `obs[17:20]`: ๋ฌผ์ฒด(Object/Cylinder) 3D ์œ„์น˜ (x, y, z) * `obs[20:23]`: ๋ชฉํ‘œ ์ง€์ (Goal/Target) 3D ์œ„์น˜ (x, y, z) * **Action Space (7์ฐจ์› ์—ฐ์† ๋ฒกํ„ฐ, Box(-2.0, 2.0, (7,), float32))**: * 7๊ฐœ ๋กœ๋ด‡ ํŒ” ์กฐ์ธํŠธ์— ๊ฐ€ํ•ด์ง€๋Š” ํ† ํฌ(Torque) ์ œ์–ด๊ฐ’. * **Step Return `info` Dictionary**: ```python { "reward_dist": float, # ๋ฌผ์ฒด์™€ ๋ชฉํ‘œ ์ง€์  ๊ฐ„ ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜ ์Œ์ˆ˜ ๋ณด์ƒ (-norm(obj-goal) * 1.25) "reward_ctrl": float, # ์ œ์–ด ํ† ํฌ ํŽ˜๋„ํ‹ฐ (-norm(action)^2 * 0.1) "reward_near": float # ๋กœ๋ด‡ ํŒ” ๋๋‹จ๊ณผ ๋ฌผ์ฒด ๊ฐ„ ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜ ์Œ์ˆ˜ ๋ณด์ƒ (-norm(tip-obj)) } ``` --- ## 2. WebSocket ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ํŒจํ‚ท ์Šคํ‚ค๋งˆ (`/ws/simulation`) ### Server → Client (`sim_frame`): ```json { "type": "sim_frame", "frame": "", "episode": 1, "step": 42, "step_reward": -0.452, "ep_reward": -18.24, "dist_goal": 0.220, "dist_arm": 0.185, "reward_ctrl": -0.082, "joints": [0.12, -0.45, 0.88, -1.20, 0.05, 0.32, -0.15], "tip_pos": [0.35, -0.12, 0.04], "obj_pos": [0.45, 0.05, -0.05], "goal_pos": [0.60, 0.10, -0.05], "actions": [0.1, -0.2, 0.5, -0.8, 0.0, 0.2, -0.1], "policy": "trained", "done": false } ``` ### Client → Server Command: ```json { "command": "start" } { "command": "pause" } { "command": "step" } { "command": "reset" } { "command": "set_policy", "policy": "trained" } { "command": "toggle_hud" } { "command": "set_speed", "speed": 1.0 } ``` --- ## 3. ํ•™์Šต ๋ฉ”ํŠธ๋ฆญ ์Šคํ‚ค๋งˆ (`results/metrics.json`) ```json { "eval_timesteps": [0, 10000, 20000, 30000], "eval_rewards": [-57.51, -50.12, -49.22, -49.25], "eval_lengths": [100, 100, 100, 100], "eval_dist_goal": [0.220, 0.220, 0.220, 0.220], "eval_dist_arm": [0.302, 0.245, 0.210, 0.187], "total_timesteps": 30720 } ``` ## 4. ์‹คํ–‰ ์„ค์ • ์Šคํ‚ค๋งˆ (`results/config.json`) ```json { "timesteps": 500000, "eval_freq": 50000, "n_eval_episodes": 2, "seed": 42, "output_dir": "./results", "zip_name": "ppo_pusher_bundle.zip", "learning_rate": 0.0003 } ``` --- ## 5. ํ•™์Šต ์ƒํƒœ ๋ฐ ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ ์Šคํ‚ค๋งˆ (`/api/train/status`) ```json { "is_training": true, "progress": 45, "current_timesteps": 225000, "total_timesteps": 500000, "status": "Training in progress... (45%)", "logs": [ "[11:50:12 AM] [PPO Step 050000] Progress: 10.0% | Training Speed: 2150 FPS", "[11:50:24 AM] [PPO Step 100000] Progress: 20.0% | Training Speed: 2180 FPS" ] } ``` --- ## 6. ์ฒดํฌํฌ์ธํŠธ ๊ฐค๋Ÿฌ๋ฆฌ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ (`/api/checkpoints`) ```json { "checkpoints": [ { "name": "step_0000000", "step": 0, "reward": -57.51, "dist_goal": 0.220, "mp4": "/results/videos/step_0000000.mp4", "gif": "/results/videos/step_0000000.gif" } ] } ```