Stage 1: Prepare the humanoid USD#

A locomotion policy learns the dynamics represented by the training asset. Incorrect mass, inertia, collision, joint, or actuator properties therefore become part of the behavior the policy learns. Prepare and validate the USD before you encode the same robot in AGILE. Longer training cannot correct these errors; the policy instead adapts to the incorrect model.

This stage assumes nothing about what your robot’s manufacturer publishes. Where H2 has published actuator values, they are shown as a worked example, but every procedure here also works when the only information you have is the asset itself.

Choose your starting point#

Three assets can stand in for the humanoid in this stage, and which one you have changes only where you begin, not what you validate:

Asset

When to use it

Shipped reference H2

Isaac/Robots/Unitree/H2/H2.usda, included with Isaac Sim. The most convenient way to practice this stage against a known-good humanoid. Start at Start from the reference H2 asset.

Your own humanoid URDF

The path most readers will follow for real work. Start at Import a custom humanoid from URDF.

Robot Menagerie H2

The asset the reference AGILE task trains on, retrieved by fetch_h2_usd() in Stage 2 rather than opened by hand. You do not prepare this one; see What Stage 2 actually trains on.

All three converge on the inspection, pose, gain, and validation sections that follow, which are the point of this stage.

What Stage 2 actually trains on#

The reference H2 task does not train with the USD that you open in Stage 1. Stage 2 calls fetch_h2_usd() to retrieve H2 from the AGILE Robot Menagerie, so edits to the shipped Isaac Sim asset do not affect the reference run.

Use Stage 1 to learn the validation process on an asset that you can inspect. For your own humanoid, point the Stage 2 robot configuration at the USD you validate here. That USD then becomes the training asset, and all the Stage 1 checks apply directly to it.

Keep these differences between the two H2 assets in mind:

  • The Menagerie asset provides collision_profile and hands variant sets. Stage 2 selects feet_only and none respectively. The shipped asset provides only a Physics variant set. If your own robot uses variants, define their names and selections in its Stage 2 spawn configuration.

  • The collider audit later in this stage teaches you how to verify collision coverage. The reference task uses the Menagerie asset’s selected colliders; your custom task uses the collision geometry in your own USD, so audit it before training.

See also

  • Simulating a dexterous hand in Isaac Sim walks through the same inspect, collider, and gain-tuning workflow on a smaller asset.

  • Gain Tuner is the reference for the tuning workflow and for the Sinusoidal and dt Sweep test modes that this stage does not use.

  • Rigging a Legged Robot for a Locomotion Policy covers the general legged-robot case outside the humanoid context. Note that its temporary anchor is attached to the torso for pose capture; for gain testing, anchor the articulation root instead.

Start from the reference H2 asset#

Open Isaac/Robots/Unitree/H2/H2.usda from the Content Browser. The asset was generated from Unitree’s h2_description package by the URDF importer, so it already has the structure this workflow expects:

  • The default prim is H2, and the articulation root is /H2/Geometry/pelvis.

  • A Physics variant set carries physics, physx, mujoco, and none payloads. Check which variant is selected in the Property panel under Variants before you edit anything, and author physics edits into the payload layer backing that variant so that a later geometry update does not discard them.

  • The robot is floating base. It contains no world fixed joint, which is what locomotion training requires.

  • It has 31 revolute joints: six per leg (hip_pitch, hip_roll, hip_yaw, knee, ankle_roll, ankle_pitch), three waist joints, two head joints, and seven per arm.

Several properties still need your attention before training, and they are easy to miss because the asset opens and simulates without complaint:

Property

State in the shipped asset

Action

Drive stiffness and damping

Uniform 1000 and 10 on all 31 joints, which the runtime reports as 57295.8 and 573.0 in radian units.

Replace with per-group values. A single stiffness shared by a leg and a wrist is a placeholder rather than a tuned plant. A fresh URDF import authors 0 for both instead, so neither starting point gives you usable gains. See Author the actuator gains.

Maximum joint velocity

The drive performance envelope is inf, but every joint still resolves a finite limit at runtime, from 20 rad/s at the hips and knees to 100.7 rad/s at the ankle roll.

Verify rather than add. Read the resolved limits back with the joint-properties snippet in Deploying policies in Isaac Sim and confirm they match your hardware, instead of assuming the inf envelope means the drive is unbounded.

Effort limits

Authored per joint and mostly consistent with Unitree’s published values.

Spot-check against H2 actuator gains. Waist roll and pitch carry 180 N·m where Unitree publishes 120 N·m for the waist group, and shoulder pitch carries 120 N·m where the published arm group is 54 N·m. Confirm which applies to your hardware.

Armature and joint friction

Not authored; both resolve to zero.

Unitree publishes armature = 0.01 for every actuated group. Author it here or set it in the AGILE actuator configuration in Stage 2, but do not set it in both places with different values.

Sensor and hand frames

Absent. The asset was built with fixed-joint merging enabled, so imu_in_pelvis, imu_in_torso, and the hand links the URDF declares are not present as prims.

The reference observation terms do not read an IMU prim, so this costs you nothing on the H2 path. If your own observation terms or deployment interface reference those frames by name, re-import from URDF with merging disabled rather than trying to recover them from this asset.

Note

The head joints (head_pitch_joint and head_yaw_joint) carry drives in the asset but do not appear in Unitree’s published actuator groups. Decide deliberately whether the policy commands them, holds them, or leaves them to a randomized action, and record that decision for Stage 2.

Import a custom humanoid from URDF#

Follow Importing a URDF and save the result as a USD asset. Three importer settings determine whether the asset is usable for locomotion training.

  1. Set Base Type to Mobile. The default is Source, which defers to the source URDF; because H2 declares its floating base only in a commented-out block, importing H2 on the default authors a /H2/Physics/root_joint fixed joint between the root prim and the pelvis, which produces an articulation that cannot translate. A locomotion policy trained against a world-fixed root learns a plant that does not exist. Setting Mobile removes that joint and leaves only the fixed joints the URDF itself declares.

  2. Enable Allow Self-Collision if your robot’s arms can reach its torso or legs. Without it, training can discover poses that pass limbs through the body.

  3. Set Robot Type to Humanoid so the importer tags the asset for the robot schema that the robotics tools read.

Note

Fixed-joint merging is what separates the two starting points, and you do not have to do anything to get it right from the GUI. The import dialog does not expose the option and the importer does not merge by default, so a GUI import preserves the sensor and inertial frames the URDF declares. For H2 that means a fresh import keeps imu_in_pelvis and imu_in_torso as plain Xform frames, and keeps left_hand_link and right_hand_link as rigid bodies, while the shipped asset was built with merging enabled and contains none of them. The reference H2 observation terms do not read an IMU prim, so preserve these frames only if your own observation terms or your deployment interface reference them by name. If you script the import instead, leave merge_fixed_joints at its default of False while you validate.

Isaac Sim URDF import dialog with H2.urdf selected and Base Type set to Mobile

H2.urdf selected with Allow Self-Collision enabled, Robot Type set to Humanoid, and Base Type set to Mobile.#

The importer writes USD Asset Structure 3.0: a thin root layer over payloads/base.usda for geometry and a Physics variant set over the physics payloads. Author gains and limits into the physics payload so that geometry updates from your CAD or URDF source do not discard your tuning.

A fresh import is structurally sound but not yet trainable. Importing H2 with the settings above gives 31 revolute joints, 34 rigid bodies, 23 colliders, and a single articulation root on pelvis, which matches what Stage 2 expects. What it does not give you is the actuator model:

After a fresh import

What you get

What to do before Stage 2

World fixed joint

/H2/Physics/root_joint unless Base Type is Mobile

Confirm no world fixed joint survives. The hand fixed joints the URDF declares are fine.

Drive stiffness and damping

0 and 0 on every joint

Author per-group gains. An undriven articulation collapses the moment you press Play.

Max force

Taken from the URDF effort attributes

Reconcile against the manufacturer’s published spec. H2’s URDF and Unitree’s published groups disagree on the arms: 130 against 54 N·m at shoulder pitch, and 10 against 25 N·m at the wrists.

Armature, joint friction, and drive velocity

Unauthored

Decide whether they live in the USD or in the Stage 2 actuator configuration, and set them in one place only.

Sensor and hand frames

Preserved when fixed-joint merging is disabled

Keep them if Stage 2 observations or your deployment interface reference them by name.

Inspect the articulation#

Inspect the imported or library asset before you touch drives. Each of these catches a class of failure that is expensive to diagnose after training starts.

  1. Enable collider visualization with Eye > Show by Type > Physics > Colliders > All and confirm every contact surface has geometry. Rigid-body colliders draw green and static colliders draw magenta, so magenta on a robot you expect to be dynamic means the physics has not resolved and you are looking at the wrong thing.

  2. Enable joint visualization with Eye > Show by Type > Physics > Joints and confirm each axis points where you expect. A reversed axis trains a policy that drives the joint the wrong way, and the symptom appears only at deployment.

  3. Open Window > Robot Inspector and confirm every moving link has plausible mass, center of mass, and inertia. Zero or default inertia on a limb is a common URDF export defect. The Tree hierarchy mode is easier to scan than the stage when payloads spread prims across layers.

  4. Confirm the asset uses meters, kilograms, seconds, radians, and newtons in its source data.

  5. Confirm the joint axes, position limits, velocity limits, and effort limits match the robot.

  6. Confirm exactly one articulation root exists, on the root link. On H2 that is /H2/Geometry/pelvis. Do not attach the humanoid to the world with a fixed joint for locomotion training.

  7. Confirm joint and link names are stable and unique. You reference these names in the AGILE robot and task configurations, and renaming them later invalidates a trained policy.

Unitree H2 in the Isaac Sim viewport with rigid-body collision geometry drawn in green

Collider visualization on the imported H2. Convex hulls cover the torso, thighs, and feet, while the shin is represented only by the thin rod at the knee.#

Do not read “has colliders” as “has the right colliders.” The imported H2 puts collision on 23 of its 34 rigid-body links, and the shipped asset on 21 of 32; the two extra links in the imported asset are left_hand_link and right_hand_link, which merging removes. That sounds complete until you look at what the shapes are. Most links carry a convex hull of their visual mesh, but the URDF also ships two crude primitive stand-ins per leg:

Link

Collider

What to check

.*_ankle_pitch_link

Convex hull mesh

This is the foot, and it is the contact surface that matters most for locomotion. The ankle roll link carries no collider, so do not look for the foot there.

.*_knee_link

Cylinder, 0.35 m long and 0.025 m radius

A 5 cm-diameter rod is a placeholder for the shin, not a representation of it. If your task rewards or terminations depend on shin contact, replace it.

.*_hip_roll_link

Sphere, 0.05 m radius

A 10 cm ball at the hip. Adequate for self-collision rejection, poor for anything that contacts the thigh.

Eleven links carry no collider at all in both assets: .*_hip_pitch_link, .*_ankle_roll_link, .*_wrist_pitch_link, .*_wrist_roll_link, waist_yaw_link, waist_roll_link, and head_pitch_link. None of them is at the end of a chain, so the robot has no uncovered extremity, but the gaps are not all the same size: the hip pitch, ankle roll, and head pitch are single uncovered links between two covered ones, while the waist and each wrist have two uncovered links in a row. Walk your own robot’s chains the same way and confirm where the gaps fall rather than assuming the count is enough.

Note

If you audit the asset with a script rather than the viewport, traverse instance proxies. Both H2 assets store their geometry as USD instances, so a plain Usd.Stage.Traverse() walks past the prototypes and reports 4 colliders instead of 23. Use Usd.PrimRange.Stage(stage, Usd.TraverseInstanceProxies()) and confirm the count matches what collider visualization draws before you conclude that geometry is missing.

Warning

Do not transform the asset’s root prim directly. Both H2 assets carry a Physics variant set on that prim, and authoring over it can clear the variant selection, which silently removes every joint and articulation root from the stage while the robot still looks correct in the viewport. Parent the asset under your own Xform and move that instead. If the physics disappears, check the variant selection in the Property panel under Variants before anything else.

Author the standing pose#

This is the pose the asset holds when you open it and the posture every check in this stage is measured against, so it should be a posture the robot can hold. Unitree’s published home keyframe places the H2 base at 1.03 m with the following joint positions. USD joint positions in the GUI are degrees, while the published values and AGILE configuration are radians. Joint names below use the .* wildcard, as the AGILE configuration does, so .*_knee_joint covers both left_knee_joint and right_knee_joint; in the GUI you set each side individually.

Joint

Radians

Degrees

Notes

.*_hip_pitch_joint

-0.25

-14.32

Slight forward lean at the hip.

.*_knee_joint

0.50

28.65

Bent knee; keeps the leg off its limit.

.*_ankle_pitch_joint

-0.25

-14.32

Levels the foot under the bent knee.

.*_shoulder_pitch_joint

0.35

20.05

.*_elbow_joint

0.87

49.85

left_shoulder_roll_joint

0.18

10.31

Mirrored, so the sign differs per side.

right_shoulder_roll_joint

-0.18

-10.31

Mirrored, so the sign differs per side.

All remaining joints

0.0

0.0

Includes waist, head, wrists, and yaw and roll of the hips.

A drive target is not a start state. The drive pulls the joint toward its target once simulation begins, so a robot that only has targets authored springs into the pose from wherever the joints happen to sit. Author the pose as state as well:

  1. Select the actuated joints, right-click, and choose Add > Physics > Joint State Angular. This applies PhysicsJointStateAPI:angular, which exposes state:angular:physics:position and state:angular:physics:velocity. Both are in degrees and degrees per second, matching the drive attributes rather than the radian values in your AGILE configuration.

  2. Set Position to the pose value and Velocity to 0 on every actuated joint. PhysX applies joint state at the first step, which is what makes it the start state.

  3. Set the matching Target Position on each angular drive, and Target Velocity to 0, so the drive holds the pose it starts in rather than pulling away from it.

You can edit both sets of values in one place with Tools > Robotics > Joint Inspector, which exposes State Position and State Velocity alongside Target Position and Target Velocity.

Unitree H2 standing in the authored home pose with slightly bent knees and arms at its sides

H2 holding the published home pose. The stance is shallow by design: the hips, knees, and ankles carry just enough bend to unlock the legs while keeping the torso upright.#

Important

The pose you author here governs the asset in Isaac Sim, not the training reset. Once you reach Stage 2, the init_state block on the AGILE articulation configuration is what determines the spawn and per-episode reset pose, and the reference H2 task uses a shallower crouch than Unitree’s published keyframe. Treat this pose as the validated starting point you carry into Stage 2, and expect to reconcile the two rather than assuming the USD values reach training.

Tip

If you would rather capture a pose the robot settles into than type one in, anchor the robot with a temporary fixed joint on the articulation root, uncheck Reset Simulation on Stop in Edit > Preferences > Physics, play until the pose looks right, and stop. The settled state is left on the joints, so save the layer, delete the fixed joint, and re-enable Reset Simulation on Stop. Run it twice to confirm the pose survives a reset.

Author the actuator gains#

Neither starting point gives you usable gains. A fresh import authors 0 stiffness and 0 damping, so the articulation collapses on Play. The shipped asset authors a uniform 1000 and 10 across a 16 kg leg chain and a wrist, which holds any pose you give it like a statue and teaches the policy an actuator that does not exist. Both need replacing with per-group values.

Anchor the robot before you test anything#

Do this first. Every gain test below plays the timeline, and the robot is floating base, so an unanchored humanoid falls for the whole duration of the test and every number you read back describes a robot in free fall rather than a robot tracking a target.

  1. Add a temporary fixed joint between the world and the articulation root (/H2/Geometry/pelvis). Anchor the root itself rather than the torso or waist: an anchor higher up leaves the waist joints free between the anchor and the legs, so the leg joints are tested against a base that still moves, and the waist joints carry a load they would not carry in free flight.

    Stage tree and property panel showing a temporary fixed joint bound to the H2 pelvis

    The anchor with Body 0 left empty so it binds to the world, and Body 1 set to /H2/Geometry/pelvis.#

  2. Remove or deactivate the ground plane for the duration of the tests, if your stage has one. Floor contact reports as BLOCKED in Snap to Limits, which masks real results. A bare H2.usda has no ground plane, so there may be nothing to remove.

Warning

Delete the temporary fixed joint before you save the asset for training. A world-fixed root that survives into Stage 2 produces a robot that trains standing in place and appears to learn nothing.

Understand what the gains do#

A PhysX position drive is a spring-damper. The force it applies is

\[F = K_p \, (\theta_{target} - \theta) + K_d \, (\dot{\theta}_{target} - \dot{\theta})\]

where \(K_p\) is stiffness and \(K_d\) is damping. Their ratio sets how the joint answers a new target:

Regime

Behavior

Cause

Underdamped

Overshoots and oscillates before settling.

Stiffness is high relative to damping.

Critically damped

Reaches the target quickly without overshooting.

Stiffness and damping are balanced.

Overdamped

Approaches the target slowly without overshooting.

Damping is high relative to stiffness.

Aim for near-critical damping. Oscillation or overshoot means raise damping or lower stiffness; a joint that creeps toward its target means raise stiffness or lower damping.

Find stable gains for your robot#

Open Tools > Robotics > Asset Editors > Gain Tuner and select the robot in the Robot dropdown. If the panel shows an ADD ROBOT SCHEMA button instead of a joint table, the asset has no Robot Schema; apply it first, since the tool reads the schema’s joint list. Work one joint group at a time on the Gain Settings tab, starting with the heaviest chain, because a leg that is stable will not be destabilized by a wrist but the reverse is not true. For each group, apply the position-drive heuristic from Tuning Workflow:

  1. Set damping to 0 and raise stiffness until the joint converges near its target. Without the derivative term you can see the stiffness response on its own.

  2. Reduce the stiffness by one order of magnitude.

  3. Add damping one order of magnitude below the stiffness. This baseline should not overshoot. Reduce damping further if you want a faster response.

  4. Fine-tune both around that baseline for stability, response time, and overshoot.

Evaluate each iteration on the Test Gains tab with Test Mode set to Step Function, which drives sudden position changes and is the closest analogue to how a policy issues targets during training. Enable Test for the joints in the group, give them the same Sequence so they run together, and click Run Test, which starts the timeline when the simulation is not already playing. Read the result in Charts.

Gain Tuner charts comparing commanded and observed positions for three H2 leg joints

A Step Function run on the left leg. The square wave is the command and the curves are the observed positions, so the gap between them is the tracking error that Test Information reports as peak and RMS.#

Tip

If you have no reference values at all, switch the Controller Gains form to Natural Frequency / Damping Ratio. You then specify a target natural frequency in Hz and a dimensionless damping ratio, where \(\zeta = 1.0\) is critically damped, and Gain Tuner converts them to stiffness and damping using the joint’s effective inertia. That is often easier to reason about than an absolute stiffness, because a frequency and a damping ratio mean the same thing on a hip as on a wrist. The conversion needs inertia, so play the timeline first, and note that it uses the home configuration.

Start from published values when they exist#

Manufacturer gains encode the real actuator rather than a guess, so use them as your starting point and validate rather than tune from zero. A robot of similar size, joint count, and actuator class can also provide initial values, but treat those as a first guess and run the same tests.

Unitree publishes H2 actuator gains in radian SI. Gain Tuner shows revolute joints in degrees under PhysX and radians under Newton, so the joint table columns read Stiffness / Kp (deg) and Damping / Kd (deg). Convert stiffness \(S\) and damping \(D\) with:

\[S_{deg} = S_{rad} \times \frac{\pi}{180} \qquad D_{deg} = D_{rad} \times \frac{\pi}{180}\]

Enter effort_limit in the Max Force column with no conversion. The PhysX values for the published H2 groups are:

Joint group

Stiffness (rad)

Damping (rad)

Stiffness (deg)

Damping (deg)

Max Force (N·m)

hip_pitch, hip_roll, hip_yaw, knee

200.0

4.0

3.491

0.0698

360

waist_yaw, waist_roll, waist_pitch

150.0

3.0

2.618

0.0524

120

shoulder_*, elbow, wrist_roll

40.0

2.0

0.698

0.0349

54

ankle_roll

40.0

2.0

0.698

0.0349

19

ankle_pitch

40.0

2.0

0.698

0.0349

66

wrist_pitch, wrist_yaw

20.0

1.0

0.349

0.0175

25

Multi-select each joint group in the table and enter the values. Then set Save Target to the physics payload layer and press Save. The dropdown lists every payloads/Physics/*.usda layer on the stage and defaults to the neutral physics.usda; choose the layer backing the variant you are working in if you want the edit to be backend-specific.

Gain Tuner listing the H2 joints with per-group stiffness, damping, and max force values

Gain Tuner after the published groups are entered. Max Joint Velocity reads inf for every joint because that column reports the drive performance envelope rather than the limit the joint resolves at runtime.#

Important

These USD gains are not the plant the policy ultimately learns. Isaac Lab and AGILE apply the actuator configuration from the task at runtime, overriding the drive values in the USD. Author them here so the asset is correct in isolation and so the Gain Tuner tests below are meaningful, then carry the same numbers into the Stage 2 actuator groups. If the two disagree, the task configuration wins.

Note

Published gains are tracking gains for the policy loop, not static-hold gains. A Step Function run on H2’s left leg with Unitree’s values reports a peak error of 32.7 degrees at the hip pitch, 15.5 at the knee, and 34.0 at the ankle pitch, and if you press Play with the pose as the target and no policy running, the robot sags and folds rather than holding it. At 200 N·m/rad the knee needs a large tracking error before it produces the torque gravity demands. That is expected and is not a reason to raise the gains. The shipped asset’s uniform 1000 in degree units is roughly 57000 N·m/rad, which is why it holds any pose like a statue, and why it is a poor starting point for training.

Validate the drives#

Once a group tracks acceptably, use the remaining test modes to catch authoring mistakes rather than to search for better gains. A unit conversion that is off by the factor of 57.3 between radians and degrees, a missing max force, or reversed joint bodies all surface here as failures across nearly every joint at once.

Keep the anchor and the removed ground plane from Anchor the robot before you test anything in place for these tests, for the same reason.

  1. Run Snap to Limits across the actuated joints. It commands each joint to its lower limit, holds, then commands the upper limit, so it verifies that gains, limits, and collision geometry agree.

    Gain Tuner Snap to Limits results listing pass, fail, and blocked outcomes per H2 joint

    Snap to Limits results per joint, with the settling time and the mean and maximum error at each limit.#

  2. Run Stress last. It drives joints with extreme random commands and exposes solver instabilities of the kind that aggressive reinforcement learning exploration produces.

  3. Delete the temporary fixed joint, and restore the ground plane if you removed one.

Read the per-joint verdicts precisely:

Result

Meaning

PASS

Both limits were reached within tolerance.

FAIL

The limit was not reached and the joint was still moving. This points at gains or dynamics.

BLOCKED

The limit was not reached and the joint stalled, typically against self-collision or another physical constraint.

Note

Expect a mixed result on H2 and read it correctly. Snap to Limits with Unitree’s published gains passes 13 of 31 joints; the rest report BLOCKED or FAIL. That is not an authoring error, for the same reason the Step Function errors above are large.

To separate contact blocking from insufficient torque, run the test again with Disable Self-Collisions During Test. On H2 the two runs differ by a single joint, which says the limiting factor is torque rather than contact. Disable Velocity Limits During Test isolates the velocity ceiling the same way. What should worry you instead is a joint that fails while its mirror twin passes, or one whole side of the robot failing at once.

Tip

If joints go unstable near their limits rather than simply failing to reach them, select PhysicsScene in the Stage panel and raise Time Steps Per Second to 120 before you change any gains.

Validate the physical model#

The sections above cover the static properties and the drives in isolation. Confirm the dynamic behavior of the whole robot before you configure the training task:

  1. Restore the ground plane, place the robot above it, press Play, and confirm that it falls and settles without exploding, tunneling through the ground, or developing persistent contact jitter.

  2. Exercise each joint through a conservative range in Tools > Robotics > Joint Inspector and confirm that its direction, limit, and reported state are correct.

  3. Confirm the robot is floating base with no world fixed joint remaining, and that exactly one articulation root exists on the root link.

  4. Read the position, velocity, and effort limits back at runtime rather than trusting the authored attributes. On H2 the drive performance envelope reports an infinite velocity while the joints resolve finite limits, so the authored value and the effective value disagree.

  5. Confirm the drive stiffness and damping are the per-group values you authored rather than a uniform value repeated across every joint.

Unitree H2 articulation standing on a ground plane in the Isaac Sim viewport beside the stage tree

The H2 articulation loaded and holding its standing pose on a ground plane in Isaac Sim.#

Record the Stage 2 inputs#

The USD is only one part of the training model. Record the following values while their meaning is visible in Isaac Sim. In Stage 2, you encode them in the AGILE robot configuration; in Stage 3, you reference the same names and frames from MDP terms. The H2 values are given as a worked example; substitute your own robot’s names throughout.

Record

H2 reference value

USD path and articulation root prim

Isaac/Robots/Unitree/H2/H2.usda, root /H2/Geometry/pelvis. Record the path to your asset here; the reference task supplies its own with fetch_h2_usd() instead of taking a path.

Root link, foot links, and fall-termination links

Root pelvis; feet left_ankle_pitch_link and right_ankle_pitch_link, which are the links that carry the foot colliders; termination contacts on pelvis and torso_link

Ordered joint names and the controlled subset

31 revolute joints; the reference task controls 14 (12 leg joints plus waist_roll_joint and waist_pitch_joint). Read the order back from the articulation rather than from the URDF, using the joint-order snippet in Debugging: H2 resolves breadth-first, starting left_hip_pitch_joint, right_hip_pitch_joint, waist_yaw_joint, left_hip_roll_joint, which is not the declaration order.

Default standing root pose, joint positions, and joint velocities

Base at 1.03 m with the joint positions in Author the standing pose, and all joint velocities zero. The reference AGILE task overrides these in init_state with a shallower crouch at 1.015 m; carry your values into Stage 2 deliberately rather than assuming they apply.

Position, velocity, and effort limits

All three resolve at runtime; record the resolved values, not the authored attributes

Actuator stiffness, damping, armature, friction, saturation, and expected control delay

Published groups in Author the actuator gains; armature = 0.01 per group, and friction unauthored in both assets

IMU and other sensor frames used to produce policy observations

imu_in_pelvis and imu_in_torso if you imported from URDF with fixed-joint merging disabled. The shipped asset contains neither, so record the link you will attach an IMU to instead.

Do not infer these values from the H2 example for another robot. The names determine which simulated bodies and joints an MDP term resolves, while the physical values determine the dynamics the policy experiences.

Troubleshooting by layer#

Symptom

Likely layer

Check

The robot explodes or develops persistent jitter.

Scale, inertia, or collision geometry.

Check units, small or invalid inertias, initial interpenetration, self-collision, and solver settings.

The robot falls through or floats above the ground.

Collision geometry.

Confirm that the feet and ground have enabled colliders and compatible collision groups.

A joint moves in the wrong direction or beyond the expected range.

Joint definition.

Check the joint bodies, axis, local frames, limits, and unit conversion.

The robot cannot fall freely.

Articulation structure.

Remove world-fixed joints and confirm that one articulation root represents the floating base.

A later AGILE term cannot find a link or joint.

Naming contract.

Record the resolved articulation names, not display labels or URDF names that changed during import.

The robot looks correct but has no joints or articulation root.

Variant selection.

Confirm the Physics variant is still selected on the asset’s root prim. Authoring a transform over that prim can clear it.

Colliders draw magenta instead of green.

Physics resolution.

Magenta means static. The links are not resolving as rigid bodies, so check the variant selection and the payload before you trust any collider or mass reading.

A script reports far fewer colliders than collider visualization draws.

Traversal.

Traverse instance proxies with Usd.TraverseInstanceProxies(); the geometry is instanced.

The robot springs into its pose when simulation starts.

Joint state.

Drive targets alone are not a start state. Author PhysicsJointStateAPI position and velocity too.

Nearly every joint fails Snap to Limits at once.

Gain authoring.

Check the radian-to-degree conversion and confirm Max Force is set on every drive.

Completion checklist#

  • The USD contains one validated floating-base articulation.

  • Mass, inertia, collision, joint-axis, and joint-limit values are physically credible.

  • Contact surfaces that your task depends on carry collision geometry that represents them, not a placeholder primitive.

  • The robot falls and settles without unstable contacts.

  • Every joint moves in the expected direction and respects its limits.

  • Joint and link names are stable and unique.

  • The standing pose is authored as joint state, not only as drive targets.

  • Drive stiffness, damping, and max force are authored per joint group rather than uniformly.

  • The temporary fixed joint used for gain testing is deleted.

  • The Stage 2 input list records the asset, pose, actuator, joint, link, and sensor values.

Continue with Stage 2: Create a custom humanoid task in AGILE.