Source code for wbc_mjlab.presets.wbc

"""Default WBC preset: Zest Table S4 core + deploy extras."""

from __future__ import annotations

from dataclasses import replace

from mjlab.envs import ManagerBasedRlEnvCfg
from mjlab.managers.termination_manager import TerminationTermCfg

import wbc_mjlab.env.mdp as mdp
from wbc_mjlab.env.mdp.commands import MotionCommandCfg

# Zest Table S4: exp(-κ‖e‖²/σ²) with κ = 1/4.
_TRACKING_KAPPA = 0.25


[docs] def apply_wbc( cfg: ManagerBasedRlEnvCfg, *, motion_body_names: tuple[str, ...], ee_termination_bodies: tuple[str, ...], ) -> None: """Default WBC stack: Zest tracking + RSI on all keybodies, EE height, light regularizers. Args: cfg: Env config to mutate in place. motion_body_names: Keybodies for tracking rewards / RSI. ee_termination_bodies: Bodies for z-only EE height termination. """ rw = cfg.rewards # --- Zest Table S4 tracking (all weight 1.0); whole-body keybodies --- rw["motion_global_root_pos"].weight = 1.0 rw["motion_global_root_pos"].params["std"] = 0.4 rw["motion_global_root_ori"].weight = 1.0 rw["motion_global_root_ori"].params["std"] = 0.5 rw["motion_root_lin_vel_b"].weight = 1.0 rw["motion_root_lin_vel_b"].params["std"] = 0.6 rw["motion_root_ang_vel_b"].weight = 1.0 rw["motion_root_ang_vel_b"].params["std"] = 1.5 rw["motion_body_pos"].weight = 1.0 rw["motion_body_pos"].params.pop("std", None) rw["motion_body_pos"].params["sigma_per_keybody"] = 0.2 rw["motion_body_pos"].params["body_error_aggregate"] = "sum" rw["motion_body_pos"].params["body_names"] = motion_body_names rw["motion_body_ori"].weight = 1.0 rw["motion_body_ori"].params.pop("std", None) rw["motion_body_ori"].params["sigma_per_keybody"] = 0.4 rw["motion_body_ori"].params["body_error_aggregate"] = "sum" rw["motion_body_ori"].params["body_names"] = motion_body_names rw["motion_joint_pos"].weight = 1.0 rw["motion_joint_pos"].params.pop("std", None) rw["motion_joint_pos"].params.pop("per_joint", None) rw["motion_joint_pos"].params["sigma_per_joint"] = 0.3 for name in ( "motion_global_root_pos", "motion_global_root_ori", "motion_root_lin_vel_b", "motion_root_ang_vel_b", "motion_body_pos", "motion_body_ori", "motion_joint_pos", ): rw[name].params["kappa"] = _TRACKING_KAPPA # --- WBC extras (mjlab whole-body vel; not in Zest Table S4) --- rw["motion_body_lin_vel"].weight = 0.5 rw["motion_body_lin_vel"].params["std"] = 1.0 rw["motion_body_lin_vel"].params["body_names"] = motion_body_names rw["motion_body_ang_vel"].weight = 0.5 rw["motion_body_ang_vel"].params["std"] = 3.14 rw["motion_body_ang_vel"].params["body_names"] = motion_body_names rw["motion_joint_vel"].weight = 0.0 rw["angular_momentum"].weight = 0.0 rw["survival"].weight = 1.0 rw["action_rate_l1"].weight = -0.1 rw["joint_acc"].weight = -5.0e-6 rw["joint_limit"].weight = -1.0 rw["actuator_torque_soft_limit"].weight = -0.1 rw["actuator_torque_soft_limit"].params["soft_ratio"] = 0.9 rw["foot_slip"].weight = -0.0 rw["anti_shake"].weight = 0.0 # rw["anti_shake"].params["body_names"] = ("left_wrist_yaw_link", "right_wrist_yaw_link") # rw["anti_shake"].params["threshold"] = 1.5 cfg.observations["actor"].history_length = 1 cfg.observations["actor"].terms.pop("ref_joint_vel", None) motion_cmd = cfg.commands["motion"] assert isinstance(motion_cmd, MotionCommandCfg) motion_cmd.assistive_wrench_enabled = True motion_cmd.rsi = replace( motion_cmd.rsi, similarity_from_rewards=True, bin_width_s=4.0, similarity_norm_by_remaining_clip=True, min_bin_span_ratio=0.5, persist_failure_levels=True, ) cfg.terminations["anchor_pos"].params["threshold"] = 0.35 cfg.terminations["ee_body_pos"] = TerminationTermCfg( func=mdp.bad_motion_body_pos_z_only, params={ "command_name": "motion", "threshold": 0.25, "body_names": ee_termination_bodies, }, ) cfg.terminations["keybody_ground_contact_force"] = TerminationTermCfg( func=mdp.excessive_keybody_ground_contact_force, params={ "sensor_name": "keybodies_ground_contact", "body_names": motion_body_names, "body_slot_order": motion_body_names, "force_threshold": 2000.0, }, )