protomotions¶
protomotions tracks a reference motion under physics with NVIDIA GEAR's Generalist Tracking Policy for the Unitree G1.
Deprecated, removed in 0.7
The DeprecationWarning points at wbc, which walks the G1 from velocity commands; it does not track a motion clip, so clip tracking has no in-tree replacement after 0.7.
This page plays a reference motion clip on a simulated Unitree G1 that balances and reacts to contact, and chains it after kimodo.
onnx_path and yaml_path take a local file each; a Hub id is not fetched for you.
pip install 'strands-robots[protomotions,sim-mujoco]' # onnxruntime + pyyaml + huggingface_hub; the fences below also need mujoco
What it is¶
ProtoMotionsPolicy wraps the ONNX Generalist Tracking Policy (GTP) from NVIDIA GEAR's ProtoMotions framework, BeyondMimic-trained, published at cagataydev/protomotions-gtp-unitree-g1 (unified_pipeline.onnx plus its unified_pipeline.yaml sidecar). Each tick it reads root and anchor rotation plus joint position and velocity, looks ahead into a MotionPlayer reference window, and emits PD joint targets for the G1's 29 actuators. requires_images is False. Output is smoothed by the config's action_ema_alpha (1.0 is passthrough).
from strands_robots.policies import create_policy
policy = create_policy("protomotions", onnx_path="unified_pipeline.onnx", yaml_path="unified_pipeline.yaml", motion="walk.npz")
policy = create_policy("gtp_g1", onnx_path="unified_pipeline.onnx", motion="walk.npz") # same provider
Constructor keywords¶
| keyword | type | default |
|---|---|---|
onnx_path |
str \| Path \| None |
None |
yaml_path |
str \| Path \| None |
None |
motion |
MotionPlayer \| dict[str, Any] \| str \| Path \| None |
None |
session |
ProtoMotionsSession \| None |
None |
providers |
list[str] \| None |
None |
history_length |
int |
1 |
no **kwargs: an unknown keyword is a TypeError |
All keyword-only, no **kwargs: a typo is a TypeError at build time. Without yaml_path the ProtoMotionsConfig defaults apply; they match the shipped weights. motion may be a MotionPlayer, a cache dict, or a .npz / .pt path, and may be None at build time. providers defaults to ["CUDAExecutionProvider", "CPUExecutionProvider"]. history_length=1 matches the upstream checkpoint.
Per-call keywords¶
| keyword | meaning |
|---|---|
motion |
swap in a new reference without rebuilding the policy (also policy.load_motion(...)) |
anchor_rot_xyzw, root_ang_vel_local |
supply these from an IMU on hardware instead of deriving them from the observation |
The observation may carry the flat observation.state or the joint names in GTP_G1_JOINT_NAMES directly; either shape works.
From a prompt to a tracked motion¶
kimodo samples a qpos trajectory. strands_robots.policies.protomotions.bridge.qpos_to_motion_data(qpos, fps, proto_mjcf_path, control_dt=0.02) converts it into a MotionPlayer cache (body positions and rotations, finite-difference velocities). This policy tracks that cache.
from strands_robots.policies import create_policy
from strands_robots.policies.kimodo import KimodoConfig
from strands_robots.policies.kimodo._diffusers_agent import DiffusersKimodoAgent
from strands_robots.policies.protomotions.bridge import qpos_to_motion_data
config = KimodoConfig()
agent = DiffusersKimodoAgent(config) # the sampler KimodoPolicy builds internally
qpos = agent.sample("a person waving with the right hand", num_frames=120, diffusion_steps=100, guidance_scale=7.5, seed=0)
cache = qpos_to_motion_data(qpos, fps=config.native_fps, proto_mjcf_path="g1_bm_no_mesh_box_feet.xml") # (frames, 7 + 29) -> MotionPlayer cache
tracker = create_policy("protomotions", onnx_path="unified_pipeline.onnx", motion=cache)
The MJCF is g1_bm_no_mesh_box_feet.xml from NVlabs/ProtoMotions (curl -LO https://raw.githubusercontent.com/NVlabs/ProtoMotions/main/protomotions/data/assets/mjcf/g1_bm_no_mesh_box_feet.xml); its three meshed siblings need Git LFS, otherwise the parse fails with decoder failed for mesh file.
Run it¶
Needs the extra and the two artifact files.
from strands_robots.simulation import create_simulation
sim = create_simulation("mujoco")
sim.create_world()
sim.add_robot("g1")
result = sim.run_policy(
robot_name="g1",
policy_provider="protomotions",
policy_config={"onnx_path": "unified_pipeline.onnx", "yaml_path": "unified_pipeline.yaml", "motion": "walk.npz"},
duration=5.0,
control_frequency=50.0,
)
print(result["status"])
Limits¶
- Unitree G1 only, 29 actuators, the ordering in
GTP_G1_JOINT_NAMES. - The tracker needs a reference. With
motion=Noneand no per-callmotion,get_actionsrefuses. - Without a CUDA provider the ONNX runs on CPU at a lower rate; the default provider list falls through to it.