Reinforcement Learning
stable-baselines3
deep-reinforcement-learning
ppo
mujoco
humanoid
adversarial-motion-priors
amp
character-animation
motion-capture
Eval Results (legacy)
Instructions to use Alopezcordero/AMP-HumanoidDirection-V0 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- stable-baselines3
How to use Alopezcordero/AMP-HumanoidDirection-V0 with stable-baselines3:
from huggingface_sb3 import load_from_hub checkpoint = load_from_hub( repo_id="Alopezcordero/AMP-HumanoidDirection-V0", filename="{MODEL FILENAME}.zip", ) - Notebooks
- Google Colab
- Kaggle
| """Shared, heading-invariant AMP feature construction. | |
| WHY THIS FILE EXISTS (the main bug in the original code): | |
| The discriminator was fed `concat[qpos[2:], qvel]`, which contains the root | |
| quaternion in the WORLD frame and the root linear velocity in the WORLD frame. | |
| Your task randomizes the walking direction every episode, but the mocap clips | |
| walk in one fixed world direction. So the discriminator learns to separate | |
| real/fake by *global heading*, not by gait quality -> the style reward | |
| actively punishes the policy whenever it follows a target direction that | |
| differs from the dataset's heading. Task reward and style reward fight each | |
| other and neither wins. | |
| Fix: express all root quantities in a local "heading frame" (yaw removed), | |
| exactly like the AMP paper. Both the policy transitions (amp_env.py) and the | |
| mocap transitions (motion_lib.py) MUST use this same function. | |
| Feature layout (45 dims -> transition pair is 90 = discriminator input_dim): | |
| root height 1 | |
| root orientation, yaw removed (quat, w>=0) 4 | |
| root linear velocity in heading frame 3 | |
| root angular velocity (MuJoCo body frame) 3 | |
| joint angles 17 | |
| joint velocities 17 | |
| """ | |
| import numpy as np | |
| AMP_OBS_DIM = 45 | |
| AMP_TRANSITION_DIM = 2 * AMP_OBS_DIM | |
| def quat_mul(a, b): | |
| """Hamilton product, MuJoCo [w, x, y, z] convention.""" | |
| w1, x1, y1, z1 = a | |
| w2, x2, y2, z2 = b | |
| return np.array([ | |
| w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2, | |
| w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2, | |
| w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2, | |
| w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2, | |
| ]) | |
| def yaw_from_quat(q): | |
| """ZYX-convention yaw (heading) of a [w, x, y, z] quaternion.""" | |
| w, x, y, z = q | |
| return np.arctan2(2.0 * (w * z + x * y), 1.0 - 2.0 * (y * y + z * z)) | |
| def build_amp_obs(qpos, qvel): | |
| """Humanoid-v5 layout: | |
| qpos = [x, y, z, qw, qx, qy, qz, 17 joint angles] (24,) | |
| qvel = [vx, vy, vz (world), wx, wy, wz (body), 17 vels] (23,) | |
| Returns float32 (45,) heading- and position-invariant features. | |
| """ | |
| quat = np.asarray(qpos[3:7], dtype=np.float64) | |
| yaw = yaw_from_quat(quat) | |
| c, s = np.cos(yaw), np.sin(yaw) | |
| # Rotates a world-frame vector into the heading frame (inverse yaw). | |
| R_inv = np.array([[c, s, 0.0], | |
| [-s, c, 0.0], | |
| [0.0, 0.0, 1.0]]) | |
| # Remove yaw from the root orientation: q_local = q_yaw^-1 (x) q | |
| half = -0.5 * yaw | |
| q_yaw_inv = np.array([np.cos(half), 0.0, 0.0, np.sin(half)]) | |
| quat_local = quat_mul(q_yaw_inv, quat) | |
| if quat_local[0] < 0.0: | |
| quat_local = -quat_local # canonical sign (quats double-cover) | |
| lin_vel_local = R_inv @ np.asarray(qvel[0:3], dtype=np.float64) | |
| # MuJoCo free-joint angular velocity (qvel[3:6]) is already expressed in | |
| # the body-local frame, i.e. heading-invariant. Left untouched. Either | |
| # way, expert and policy use the identical convention/transform. | |
| ang_vel = qvel[3:6] | |
| return np.concatenate([ | |
| qpos[2:3], # root height | |
| quat_local, # roll/pitch information only | |
| lin_vel_local, # forward/lateral/vertical speed relative to facing | |
| ang_vel, | |
| qpos[7:], # joint angles (already local) | |
| qvel[6:], # joint velocities (already local) | |
| ]).astype(np.float32) | |