Repository navigation
feat(scene): unify body actuator configuration across model formats - #100
Conversation
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It changes public config API and actuator-preservation semantics across core plus two simulator backends with subtle unit-conversion and keyframe logic that requires simulator execution and human sign-off to fully validate.
Review effort: Balanced
Findings: None
What changed in this PR
This PR unifies joint-actuator configuration so it is owned by the model instance (BodyCfg/RobotCfg) rather than being a URDF-only augmentation on UrdfFileCfg. It introduces a new format-neutral actuator config module shared by MJCF and URDF instances across both the MuJoCo and MotrixSim scene compilers, with None preserving imported actuators, {} removing them, and an explicit mapping replacing the entire set. Replacement also resets obsolete keyframe control/activation data while preserving joint pose/velocity.
Changes:
- New
config/scene/actuator.py(ActuatorCfg,MotorActuatorCfg,PositionActuatorCfg);BodyCfg.actuators: dict[str, ActuatorCfg] | None; actuator declarations removed fromUrdfFileCfg. - New
apply_actuator_cfgsin both backends (MuJoCo handles hinge degree→radian ctrl-range conversion; MotrixSim resets keyframectrlonly, since MSD has no activation state), wired into each compiler before attach; old URDF-only actuator paths removed. - Dex-EVT robot migrated to body-owned actuator mapping; new backend/core test suites; bilingual docs updated.
| File | Description |
|---|---|
motrix_env_core/.../config/scene/actuator.py |
New format-neutral actuator config classes with finite-gain validation |
motrix_env_core/.../config/scene/base.py |
Adds BodyCfg.actuators field + validation and updated docstring |
motrix_env_core/.../config/scene/urdf.py |
Removes ActuatorCfg/PositionActuatorCfg and UrdfFileCfg.actuators |
motrix_env_core/.../config/scene/__init__.py |
Re-exports actuator classes from the new module |
motrix_env_mujoco/.../actuators.py |
New MuJoCo actuator replacement (position/motor, keyframe reset) |
motrix_env_mujoco/.../urdf.py, compiler.py |
Removes URDF actuator building; wires apply_actuator_cfgs |
motrix_env_motrixsim/.../actuators.py |
New MotrixSim actuator replacement with keyframe ctrl reset |
motrix_env_motrixsim/.../urdf.py, compiler.py |
Removes URDF actuator building and unconditional clear; wires new path |
motrix_envs/.../robot/dex_evt.py |
Migrates drive params to BodyCfg.actuators dict |
*/tests/test_*actuator*.py, test_mujoco_scene_compiler.py |
New/updated coverage incl. degree-unit regression; PYTHONPATH fix |
docs/.../robots.md, docs/.../scene.md (en/zh) |
Documents new actuator declaration and migration |
I verified the migration is complete: no remaining references to the removed UrdfFileCfg.actuators, the actuator_name property, or ActuatorCfg imported from scene.urdf; @configclass deep-copies the mutable actuators default per instance; __init__/__all__ are consistent; and backend validation ordering guarantees invalid inputs don't mutate the spec/world. I did not find concrete objective defects to comment on. The degree/radian conversion and cross-backend keyframe behavior rest on simulator-specific semantics that have regression tests but cannot be executed in this review environment.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Summary
This is PR 1 of the robot/deployment configuration refactor, extracted onto
mainwithout the robot package extraction or deployment runtime changes.BodyCfg, shared by MJCF and URDF instances.Nonepreserves imported actuators,{}removes them, and an explicit mapping replaces the complete actuator set.Scope / migration
Actuation belongs to the body instance, not the URDF file augmentation. Move
UrdfFileCfg(actuators=[...])declarations toBodyCfg(actuators={name: cfg, ...}); usemotrix_env_core.config.scene.actuatorfor the definition-module imports. Joint references use source-model names before prefix/suffix decoration. Replacement is not append/merge: declare the complete desired set. Actuatorname/actuator_namefields are replaced by dictionary keys. Inherited hinge control limits honor the MJCF compiler angle unit (including the default degree setting); slide limits retain their length units.No robot assets/package extraction, dependency/lock changes, deployment runtime/task/artifact changes, or hardware backend changes are included. The original large branch is preserved.
Review
Independent subagent review was requested before submission. It identified a degree-based MJCF hinge range conversion issue; the fix and regression coverage are included and re-reviewed before submission.
Validation
prek run --all-filesandgit diff --checkpassed.-E -W --keep-going, Python 3.10/Sphinx 8.1.3). Subsequent requested simplification removes the added tutorial section and migration prose/dead links; both tutorial files now matchmain.inheritrangeduring parsing, but its MSD Python actuator API does not expose an inheritance field. Programmatic position actuator creation therefore keeps the resolved joint-limit assignment.