Refactor and cleanup core lift tasks#6013
Conversation
There was a problem hiding this comment.
Code Review: Refactor and cleanup core lift tasks
Well-structured consolidation that eliminates meaningful code duplication. The architecture choices are sound — merging deformable MDP terms into the shared lift/mdp package and moving lift_franka_soft under lift/config/franka_soft follows the established pattern of lift/config/franka. Here's a detailed analysis:
✅ Design Assessment
Architecture: The refactor correctly unifies rigid and deformable lift tasks under one package while keeping variant-specific configurations isolated in their respective config directories. The shared mdp package now owns all lift-specific observation, reward, and termination functions — this is the right ownership boundary.
Positive changes:
- Termination functions (
deformable_com_below_minimum,deformable_outside_table_bounds,ee_below_minimum) were correctly separated fromrewards.pyintoterminations.py— they were misplaced in the old code coupled_mjwarp_vbd_solver_cfg()extracted as a factory function eliminates config duplication between soft and cloth variants- The cloth
RewardsCfginheritance from the soft task's rewards is cleaner than the previous verbatim copy - Fixing the
newton_mjwarp_vdb→newton_mjwarp_vbdtypo and removing it fromenviron_docs.pyis a welcome correctness fix
Cross-module impact: Primarily self-contained. Breaking changes (env ID renames, import paths) are well-documented in the changelog entry. The migration path is clear.
🔍 Findings
🟡 franka_soft_env_cfg.py — Comment says "one-way coupled" but code is "two-way"
In the diff for PhysicsCfg, the old comment said:
# Newton physics: MJWarp rigid + VBD soft, one-way coupledThe new code correctly updates this to two-way coupled in franka_soft_env_cfg.py, but the franka_cloth_env_cfg.py comment still references "matches newton/examples/softbody/example_softbody_franka.py" which may be stale if that example has diverged. Minor, but worth verifying the comment accuracy.
🟡 franka_cloth_env_cfg.py — FrankaClothEnvCfg.__post_init__ does not call super().__post_init__()
The cloth config's __post_init__ duplicates several settings from the parent (decimation, episode_length_s, sim.dt, sim.render_interval, viewer settings) rather than calling super().__post_init__() and only overriding what differs. This is pre-existing behavior (not introduced by this PR), but since the file was substantially refactored, it's worth noting:
- The parent sets
self.sim.gravity = (0.0, 0.0, 0.0)which the cloth task intentionally does NOT inherit (cloth needs gravity for draping). This is correct. - However, if any new settings are added to
FrankaSoftEnvCfg.__post_init__()in the future, the cloth config won't pick them up — a maintenance hazard.
Consider adding a brief comment in FrankaClothEnvCfg.__post_init__ noting that it intentionally does NOT call super (to preserve gravity).
🟡 lift_franka_soft.py state machine script — dead code path after rename
Line 296:
elif args_cli.task == "Isaac-Lift-Cloth-Franka":The old code compared against "Isaac-Lift-Soft-Franka-Cloth-v0". The default task is "Isaac-Lift-Soft-Franka", so users would need to explicitly pass --task Isaac-Lift-Cloth-Franka to hit this branch. This is fine, but the script's --help text only mentions the default — consider documenting the cloth option in the argparse help string.
🔵 __init__.pyi — ObservationTermCfg import added to observations.py
The DeformableSampledPointsInRobotRootFrame.__init__ signature changed from cfg (untyped) to cfg: ObservationTermCfg. This is a good typing improvement. The TYPE_CHECKING guard is correctly used.
🔵 Import style: absolute vs relative
The change from from . import mdp to from isaaclab_tasks.core.lift import mdp (and similar for agents) is necessary for Isaac Lab's lazy_export() mechanism to work correctly when the module is imported from different relative positions after the directory restructure. This is correct.
🧪 Test Coverage
This is a refactoring PR (restructuring existing code, not adding new behavior). The relevant observations:
- Existing tests (
test_action_state_recorder_term.py,test_rsl_rl_export_flow.py,test_environment_determinism.py) are correctly updated with new environment IDs - Benchmark configs updated with new IDs
- The
coupled_mjwarp_vbd_solver_cfg()factory function produces identical config to what was inline before — no behavioral change to test - The termination function relocation is a pure code move with no logic changes
Verdict: No new tests needed for a code-move refactor. Existing test coverage (environment determinism, export flow, action/state recording) should catch regressions from the restructuring.
📋 Checklist Items
- ✅ Changelog entry (
mhaiderbhai-merge-lift-tasks.major.rst) is thorough and well-written - ✅
.skipchangelog fragments forisaaclabandisaaclab_rl(test-only changes) ⚠️ PR checklist items are all unchecked — please tick off the applicable ones before merge
Verdict
Minor fixes needed. The refactor is clean and well-executed. The breaking changes are properly documented with migration paths. Ship after addressing the checklist items and optionally the comment suggestions above.
Update (25c3c02): Incremental review after rebase onto develop.
The 12 new commits include a merge from develop bringing in infrastructure changes (cloner refactoring, Newton 1.2.1, PPISP peer dependency changes, etc.) plus a minor doc line-highlight fix. These develop changes are outside the scope of this lift-tasks PR.
Previous findings status:
- 🔴 My inline comment was NOT addressed. Line 304 in
lift_franka_soft.pystill passesFrankaClothEnvCfg()instead ofenv_cfgtogym.make(), ignoring CLI arguments (--num_envs,--device) for the cloth variant. Please fix. - 🟡 Other findings (comment accuracy,
__post_init__documentation, argparse help) remain optional suggestions.
No new issues introduced by the merge or doc fix.
Greptile SummaryThis PR consolidates the
Confidence Score: 4/5Safe to merge after fixing the gym.make call in the state machine script; the core library changes are structurally clean. The consolidation is well-executed — the deformable MDP functions are faithfully migrated, the shared solver helper eliminates real duplication, and the cloth reward inheritance removes verbatim copy-paste. The one functional regression is in the state machine script: after updating the task IDs the cloth branch still passes FrankaClothEnvCfg() (a fresh default) to gym.make instead of the already-parsed env_cfg, so --num_envs and --device CLI arguments are silently ignored for that path. scripts/environments/state_machine/lift_franka_soft.py — cloth branch of main() passes a fresh config to gym.make instead of the one parsed from CLI args. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
OLD_PKG["lift_franka_soft/\n(removed)"]
OLD_MDP["lift_franka_soft/mdp/\nobservations.py\nrewards.py\n(deleted)"]
OLD_PKG --> OLD_MDP
NEW_LIFT["lift/"]
NEW_CFG["lift/config/franka_soft/\nfranka_soft_env_cfg.py\nfranka_cloth_env_cfg.py"]
NEW_MDP["lift/mdp/\nobservations.py ← deformable COM\nrewards.py ← deformable rewards\nterminations.py ← deformable terminations"]
NEW_LIFT --> NEW_CFG
NEW_LIFT --> NEW_MDP
OLD_PKG -.->|"renamed to"| NEW_CFG
OLD_MDP -.->|"merged into"| NEW_MDP
GYM_OLD["Gym IDs (old)\nIsaac-Lift-Cube-Franka-v0\nIsaac-Lift-Soft-Franka-v0\nIsaac-Lift-Cloth-Franka-v0"]
GYM_NEW["Gym IDs (new)\nIsaac-Lift-Cube-Franka\nIsaac-Lift-Soft-Franka\nIsaac-Lift-Cloth-Franka"]
GYM_OLD -.->|"drop -v0"| GYM_NEW
PRESET_OLD["Physics preset (cloth)\nnewton_mjwarp_vdb ❌"]
PRESET_NEW["Physics preset (cloth)\nnewton_mjwarp_vbd ✅"]
PRESET_OLD -.->|"typo fixed"| PRESET_NEW
|
| ) | ||
| env_cfg.viewer.eye = (2.1, 1.0, 1.3) | ||
| env = gym.make("Isaac-Lift-Cloth-Franka-v0", cfg=FrankaClothEnvCfg(), render_mode=render_mode) | ||
| env = gym.make("Isaac-Lift-Cloth-Franka", cfg=FrankaClothEnvCfg(), render_mode=render_mode) |
There was a problem hiding this comment.
The cloth branch should use
env_cfg (already populated with --num_envs, --device, and the viewer override) just like the soft-body branch above, rather than creating a fresh default FrankaClothEnvCfg().
| env = gym.make("Isaac-Lift-Cloth-Franka", cfg=FrankaClothEnvCfg(), render_mode=render_mode) | |
| env = gym.make("Isaac-Lift-Cloth-Franka", cfg=env_cfg, render_mode=render_mode) |
Description
Consolidates the rigid and soft Franka lifting tasks into a single
isaaclab_tasks.core.liftpackage, eliminating the duplicatedlift_franka_softtask and its parallelmdpmodule. Soft and cloth variantsnow live as configs alongside the rigid one and share a common MDP package.
Changes
Package consolidation (breaking)
isaaclab_tasks.core.lift_franka_softunderisaaclab_tasks.core.lift.config.franka_soft, next to the rigidfrankaconfig.
shared
isaaclab_tasks.core.lift.mdppackage instead of a separate per-variantmdp. The oldlift_franka_soft/mdpmodule is removed.Environment IDs (breaking)
-v0version suffix from all lift Gym environment IDs:Isaac-Lift-Cube-Franka-v0→Isaac-Lift-Cube-FrankaIsaac-Lift-Cube-Franka-Play-v0→Isaac-Lift-Cube-Franka-PlayIsaac-Lift-Soft-Franka-v0→Isaac-Lift-Soft-FrankaIsaac-Lift-Cloth-Franka-v0→Isaac-Lift-Cloth-FrankaFixes
Isaac-Lift-Cloth-Frankaphysics preset from the misspellednewton_mjwarp_vdbtonewton_mjwarp_vbd, matching the soft-body task and theunderlying VBD solver.
RewardsCfg, which duplicated the soft task's rewards verbatim, nowinherits them instead of redefining.
Misc
and environment IDs.
lift_env_cfg.py.Migration
Update any
gym.make(...)/--taskcalls to use the unversioned environmentIDs listed above.
Checklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists there