Repository navigation
Add energy rewards and MujocoStyleActuatorCfg (closes S4) - #179
Merged
KraHsu merged 2 commits intoMay 29, 2026
Merged
Conversation
Wraps Genesis 1.0's per-entity energy accessors —
``Articulation.gs_handle.{get_kinetic_energy, get_potential_energy,
get_total_energy}`` — into three reward terms that follow the same
``(env, asset_cfg=None)`` calling convention as the existing
``mdp.rewards`` primitives:
- ``kinetic_energy_l2`` returns ``T²`` per env. Non-negative; pair with
a negative weight to discourage high-energy motion.
- ``potential_energy`` returns the signed potential energy directly.
Genesis follows the conventional sign (negative below z = 0); pair
with the weight that matches the task intent.
- ``energy_budget(target_total=0.0)`` returns ``(total − target)²`` per
env. Non-negative; pair with a negative weight to keep the
articulation's total mechanical energy near a target.
The energy methods on every Genesis entity (validated via a real-scene
probe on ``gs.Scene + add_entity + build``) return ``(num_envs,)``
tensors; the wrappers stay shape-preserving and let the reward manager
apply weights / combine with other terms downstream.
Tests use a synthetic ``_FakeGsHandle`` exposing only the three energy
methods — same shape as the existing mdp-reward fakes; no real-Genesis
integration needed because the call surface is a single method per
function and the Genesis-side return shape was already validated by
the probe.
A convenience cfg for actuators whose parameters live in Mujoco's
``(gear, gain_prm, bias_prm)`` form. Only the canonical
``dyntype=none / gaintype=fixed / biastype=affine`` shape is supported
(every other combination raises with the same wording Genesis's own
MJCF parser uses when logging warnings) and ``bias_prm[0]`` must be
zero (``IdealPDActuator`` has no constant-offset force term).
Translation:
kp = -gear * bias_prm[1]
kv = -gear * bias_prm[2]
The result is a plain ``IdealPDActuatorCfg`` with ``class_type =
IdealPDActuator``, so the cfg integrates with the existing actuator
registry, DR hooks, and tests without new runtime code.
Genesis 1.0 has no separate "general actuator" runtime — the MJCF
parser at ``genesis/utils/mjcf.py`` translates the same Mujoco
attributes into ``set_dofs_kp`` / ``set_dofs_kv`` /
``set_dofs_force_range`` at load time. This cfg is the GeneLab-side
mirror: same named knobs for tasks that configure actuators in Python
rather than loading from an MJCF.
Docs: a new section on ``docs/concepts/actuators.{en,zh}.md`` covers
the translation table and a worked example. CHANGELOG ``### Added``.
KraHsu
added a commit
that referenced
this pull request
Jun 5, 2026
…energy Add energy rewards and MujocoStyleActuatorCfg (closes S4)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase S4 of the Genesis 1.0 migration (ADR-0001). Ships the two S4
sub-tasks that have a clean v1.0 implementation: the energy rewards and
a Mujoco-style actuator cfg helper. The remaining two boxes
(
SimulationCfg.actuator_modelselector, zero-copy writer refactor)are explicitly closed as not applicable on v1.0 — see the drift
table below.
Changes
Energy rewards
src/genelab/mdp/rewards/energy.py— three new reward primitiveswrapping Genesis 1.0's per-entity energy accessors:
kinetic_energy_l2(env, asset_cfg=None)—T²per env, non-negative.potential_energy(env, asset_cfg=None)— signed potential energy.energy_budget(env, target_total=0.0, asset_cfg=None)— squareddeviation of total mechanical energy from a target.
tests/test_mdp_rewards_energy.py— synthetic_FakeGsHandleexercises every reward path (4 tests).
Mujoco-style actuator cfg
src/genelab/actuator/mujoco_style.py—MujocoStyleActuatorCfgaccepts Mujoco's
(gear, bias_prm, dyntype="none", gaintype="fixed", biastype="affine")shape and translates it into(stiffness=-gear*bias_prm[1], damping=-gear*bias_prm[2])on top ofIdealPDActuator. Every other dyntype / gaintype / biastypecombination raises with the same wording Genesis's own MJCF parser
uses; non-zero
bias_prm[0]also raises becauseIdealPDActuatorhas no constant-offset force term.
src/genelab/actuator/__init__.py.tests/test_mujoco_style_actuator.py— 8 cfg-translation tests(sign convention, every rejection path, pass-through fields).
docs/concepts/actuators.{en,zh}.md— new "MJCF-style actuatorconfiguration" section + table-row pointer at the top.
Shared
CHANGELOG.md—### Addedentries for both the energy rewardsand the actuator cfg.
v1.0 drift on the closed S4 sub-tasks
Probing real Genesis 1.0 surfaced that two of the four S4 ADR
sub-tasks don't apply as the ADR scoped them, even after this PR:
mujoco_general.pyruntime actuator classdyntype/gaintype/biastypeonly appear ingenesis/utils/mjcf.pyas XML-parse-time concepts; the parser already translates them into the existing setters at load time. There's no separate Genesis class to wrap.MujocoStyleActuatorCfg— a thin Python-side cfg helper that mirrors the same translation MJCF does, so robots configured in Python rather than from an MJCF can use the same named knobs.SimulationCfg.actuator_modelselectorArticulationCfg.actuatorsfield already routes per-joint actuator selection.MujocoStyleActuatorCfgslots into the sameArticulationCfg.actuatorsdict as every other actuator cfg; no new selector needed.set_pos/set_quatin_articulation_writer.pytry/except envs_idxfallback). Remaining.contiguous()/.clone()inreset()exist for semantic reasons (Genesis expects contiguous; clone breaks aliasing with_joint_pos_target).dc_motorvsmujoco_generalMujocoStyleActuatorCfgproduces anIdealPDActuator— the same runtime the comparison would have been against.dc_motorvsMujocoStyleActuatorCfg → IdealPDActuatorcomparison isdc_motorvsIdealPDActuator, which is well-trodden ground in the locomotion best-practices guide.Drift findings recorded in saved memory
genesis-1.0-migration/s4-api-driftfor future phases / thepromotion-PR discussion.
Test plan
ruff checkruff format --checkpyright— 0 errors, 0 warningspytest— 598 passed (+12: 4 energy + 8 mujoco-style), 0 failedmkdocs build --strictRisks
MujocoStyleActuatorCfgis stricter than the underlying MJCFshape. A non-zero
bias_prm[0]raises rather than approximatingthe constant offset as a static torque. Genesis's parser logs a
warning for the same shape; this cfg promotes that warning to a
hard error so the user knows the cfg isn't faithful to the MJCF.
Rewards that want base-height tracking should still prefer
base_height_l2. Documented in the per-function docstring.Notes
ticked;
actuator_modelselector and zero-copy refactor closed asn/a-on-v1.0 with the rationale in the row footers. Comparison
reference-run box closed as redundant given the cfg-helper
reinterpretation. After this merges, S5 is the only remaining
phase before the
dev/bump-genesis-1.0 → mainpromotion PR.