Fix LEAPP export of PD gains for explicit actuators#6252
Conversation
The LEAPP exporter read joint PD gains from ``data.default_joint_stiffness`` / ``data.default_joint_damping``. These buffers only hold the gains of implicit actuators (which write them to the simulation); explicit actuators such as ``DCMotor`` and ``IdealPDActuator`` compute their PD term internally and apply it as joint effort, leaving the sim-level gains at zero. As a result the exported policy graph carried zero ``kp``/``kd`` for those joints and the deployed policy was effectively unactuated (in Sim2MuJoCo and on hardware). Source the gains from ``asset.actuators`` instead, which is correct for every actuator model (a no-op for implicit actuators, whose buffers already match). Signed-off-by: Lionel Gulich <lgulich@nvidia.com>
| if stiffness is None or damping is None: | ||
| return None, None |
There was a problem hiding this comment.
Asymmetric None check changes prior behavior
The original code independently checked and exported kp_gains and kd_gains — if only one buffer was present, it was still exported. _effective_joint_gains now returns (None, None) when either buffer is absent (stiffness is None or damping is None), so a hypothetical asset that exposes only default_joint_stiffness (or only default_joint_damping) would now silently skip both exports. While this combination is uncommon in practice, the downstream calling code's two independent if kp_gains is not None / if kd_gains is not None guards suggest the caller expects they can be independently None, which is no longer possible after this change.
|
looks good. Thanks for catching this. Not sure how common it is to have kp but not kd and vice versa. If it is not possible we can probably simplify the the downstream tensor semantic creation logic a little. if it is possible then we should not return (none, none) from the effective joint gains function. |
Description
LEAPP export bakes zero
kp/kdgains into the policy graph for any policy trained with an explicit actuator (e.g.DCMotor,IdealPDActuator).ExportPatcher._collect_action_static_outputsreads the joint PD gains fromdata.default_joint_stiffness/data.default_joint_damping. Those buffers only hold the gains of implicit actuators, which write them to the simulation. Explicit actuators compute their PD term internally and apply it as joint effort, leaving the sim-level joint stiffness/damping at 0. As a result the exported graph's*_kp_gains/*_kd_gainsoutputs are all zero, so a deployment that appliestorque = kp·(q* − q) − kd·q̇produces zero torque and the robot is unactuated (reproduced in Sim2MuJoCo, and it would fail identically on hardware).The fix sources the gains from
asset.actuators(the authoritative source for every actuator model) instead of the sim-level buffers. It is a no-op for implicit actuators, whosedata.default_joint_*buffers already equal the actuator gains, and recovers the real gains for explicit actuators.Fixes the zero-gain LEAPP export for explicit-actuator robots (no tracked issue).
Type of change
Verification
Tested with a G1 lower-body locomotion policy that uses
DCMotoractuators (legs hip kp=100, knee kp=200; damping 2.5/5.0):joint_pos_kp_gains/kd_gainswere all0; the robot collapsed immediately in Sim2MuJoCo (zero actuator torque).joint_pos_kp_gains = [100, 100, …, 200, 200, …],joint_pos_kd_gains = [2.5, …, 5.0, …]— and the robot holds a stable stand for the full evaluation. Verified by running the exporter with this change as the only modification (no downstream patching).Checklist
blackclean; no import changes)_effective_joint_gainsif preferred)source/isaaclab/changelog.d/CONTRIBUTORS.md