diff --git a/source/isaaclab_tasks/config/extension.toml b/source/isaaclab_tasks/config/extension.toml index 29bf11d4859a..2e7ee00764d7 100644 --- a/source/isaaclab_tasks/config/extension.toml +++ b/source/isaaclab_tasks/config/extension.toml @@ -1,7 +1,7 @@ [package] # Note: Semantic Versioning is used: https://semver.org/ -version = "1.5.28" +version = "1.5.30" # Description title = "Isaac Lab Environments" diff --git a/source/isaaclab_tasks/docs/CHANGELOG.rst b/source/isaaclab_tasks/docs/CHANGELOG.rst index 54502c8a8354..e67ac8f42161 100644 --- a/source/isaaclab_tasks/docs/CHANGELOG.rst +++ b/source/isaaclab_tasks/docs/CHANGELOG.rst @@ -1,6 +1,39 @@ Changelog --------- +1.5.30 (2026-04-27) +~~~~~~~~~~~~~~~~~~~ + +Added +^^^^^ + +* Added Newton rough terrain support for the G1 biped locomotion velocity + env. The only engine-specific change is a ~1.7x ``max_iterations`` preset on + :class:`~isaaclab_tasks.manager_based.locomotion.velocity.config.g1.agents.rsl_rl_ppo_cfg.G1RoughPPORunnerCfg` + (Newton = 5000, PhysX = 3000). PhysX saturates near iter 3000 on both + reward (≈ +18) and episode length (≈ 980) and does not meaningfully + improve further; Newton reaches the same (reward, ep_len) quality at + iter 5000. The iteration budget is bumped rather than tuning physics + or reward terms. + + +1.5.29 (2026-04-27) +~~~~~~~~~~~~~~~~~~~ + +Changed +^^^^^^^ + +* Re-enabled ``add_base_mass`` randomization on H1 and Cassie in their + rough-terrain configs (previously ``= None`` per the pre-existing biped + convention). H1 uses the shared log-uniform scale default from + ``EventsCfg``; Cassie overrides to ``(1.0, 1.25)`` asymmetric heavier-bias + (never lighter than nominal). Symmetric ±25% regressed Cassie reward by + 40% vs disabled due to closed-loop Achilles coupling destabilizing on + lighter pelvis mass; ``(1.0, 1.25)`` recovers to 90% of the + mass-rand-disabled baseline while retaining the domain-randomization + benefit. + + 1.5.28 (2026-04-24) ~~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/cassie/rough_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/cassie/rough_env_cfg.py index 3436fee7c108..4a1030534480 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/cassie/rough_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/cassie/rough_env_cfg.py @@ -13,6 +13,7 @@ LocomotionVelocityRoughEnvCfg, RewardsCfg, ) +from isaaclab_tasks.utils import preset ## # Pre-defined configs @@ -60,12 +61,23 @@ def __post_init__(self): super().__post_init__() # scene self.scene.robot = CASSIE_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot") + # Cassie Newton-only armature for biped stability on rough terrain; PhysX unchanged + self.scene.robot.actuators["legs"].armature = preset(default=0.0, newton=0.02) + self.scene.height_scanner.prim_path = "{ENV_REGEX_NS}/Robot/pelvis" - # Cassie uses "pelvis" as base body — disable mass randomization for bipeds - self.events.add_base_mass = None + # Cassie uses "pelvis" as base body. Override the shared symmetric + # (1/1.25, 1.25) log-uniform scale with asymmetric (1.0, 1.25) — + # lighter-than-nominal pelvis destabilizes Cassie's closed-loop + # Achilles coupling + hip PD response, so only heavier perturbations + # are safe. Symmetric ±25% regressed reward 40% vs disabled; + # (1.0, 1.25) recovers to 90% of baseline. + self.events.add_base_mass.params["asset_cfg"].body_names = "pelvis" + self.events.add_base_mass.params["mass_distribution_params"] = (1.0, 1.25) self.events.base_com = None self.events.base_external_force_torque.params["asset_cfg"].body_names = ".*pelvis" + # Cassie has precise initial pose — don't scale joint defaults randomly on reset + self.events.reset_robot_joints.params["position_range"] = (1.0, 1.0) # actions self.actions.joint_pos.scale = 0.5 diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/digit/rough_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/digit/rough_env_cfg.py index 89f6647a24f6..aa0f433e4ecc 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/digit/rough_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/digit/rough_env_cfg.py @@ -232,6 +232,8 @@ def __post_init__(self): self.events.add_base_mass.params["asset_cfg"].body_names = "torso_base" self.events.base_external_force_torque.params["asset_cfg"].body_names = "torso_base" self.events.base_com.default.params["asset_cfg"].body_names = "torso_base" + # Digit has precise initial pose — don't scale joint defaults randomly on reset + self.events.reset_robot_joints.params["position_range"] = (1.0, 1.0) # Override actuator to target only actuated joints. Digit has ball joints (rod constraints) # that MuJoCo represents with 4 DoFs instead of 3, inflating joint_pos to 74 columns while diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/agents/rsl_rl_ppo_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/agents/rsl_rl_ppo_cfg.py index 61a6d0261b9f..7b61c184d353 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/agents/rsl_rl_ppo_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/agents/rsl_rl_ppo_cfg.py @@ -7,11 +7,19 @@ from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlPpoActorCriticCfg, RslRlPpoAlgorithmCfg +from isaaclab_tasks.utils import preset + @configclass class G1RoughPPORunnerCfg(RslRlOnPolicyRunnerCfg): num_steps_per_env = 24 - max_iterations = 3000 + # Newton needs ~1.7x the PPO iterations to match PhysX on G1. PhysX saturates near iter 3000 + # (reward ≈ +18, ep_len ≈ 980) and does not meaningfully improve on either metric past that — + # reward oscillates +16 to +19 through iter 7500, ep_len stays flat. Newton reaches the same + # (reward, ep_len) quality at iter 5000 (+16 / 984). Comparing reward alone is misleading: + # ep_len confirms the robot is stable in both cases. The gap is sample-efficiency, not a + # ceiling — no physics or reward tuning closes it. + max_iterations = preset(default=3000, newton=5000) save_interval = 50 experiment_name = "g1_rough" policy = RslRlPpoActorCriticCfg( diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/rough_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/rough_env_cfg.py index a24379a1553d..a241d9c3329b 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/rough_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/rough_env_cfg.py @@ -119,6 +119,8 @@ def __post_init__(self): self.events.add_base_mass = None self.events.base_com = None self.events.base_external_force_torque.params["asset_cfg"].body_names = "torso_link" + # G1 has precise initial pose — don't scale joint defaults randomly on reset + self.events.reset_robot_joints.params["position_range"] = (1.0, 1.0) # Rewards self.rewards.lin_vel_z_l2.weight = 0.0 diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/h1/rough_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/h1/rough_env_cfg.py index 7d1ef73a5587..de565b28bd32 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/h1/rough_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/h1/rough_env_cfg.py @@ -83,8 +83,11 @@ def __post_init__(self): if self.scene.height_scanner: self.scene.height_scanner.prim_path = "{ENV_REGEX_NS}/Robot/torso_link" - # H1 uses "torso_link" as base body — disable mass randomization for bipeds - self.events.add_base_mass = None + # H1 uses "torso_link" as base body; inherits the shared log-uniform mass + # randomization scale from EventsCfg (no per-H1 override needed). + self.events.add_base_mass.params["asset_cfg"].body_names = "torso_link" + # H1 has precise initial pose — don't scale joint defaults randomly on reset + self.events.reset_robot_joints.params["position_range"] = (1.0, 1.0) self.events.base_com = None self.events.base_external_force_torque.params["asset_cfg"].body_names = ".*torso_link"