diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560062.worker-4.1987684.0 b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560062.worker-4.1987684.0 new file mode 100644 index 0000000000000000000000000000000000000000..b9648f35fd63ecc9e8a390a8c57520762fead1fa --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560062.worker-4.1987684.0 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9810f67525bb37a9a1d327e614dc8d33bbc8ef16176d651bc94f91f05cff6c17 +size 64861888 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff new file mode 100644 index 0000000000000000000000000000000000000000..651f0bd76d1fbfe2e40dd933aa420b3ac5c14f6b --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff @@ -0,0 +1,30 @@ +--- git commit --- +59c3c413a30c0a375f2365e7f02a02e5023b9634 + + +--- git status --- +On branch dev/fdf +Your branch is up to date with 'origin/dev/fdf'. + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: src/tasks/velocity/config/vr_m3_12dof/__init__.py + +no changes added to commit (use "git add" and/or "git commit -a") + + +--- git diff --- +diff --git a/src/tasks/velocity/config/vr_m3_12dof/__init__.py b/src/tasks/velocity/config/vr_m3_12dof/__init__.py +index a6e8d27..e43f78c 100644 +--- a/src/tasks/velocity/config/vr_m3_12dof/__init__.py ++++ b/src/tasks/velocity/config/vr_m3_12dof/__init__.py +@@ -203,7 +203,7 @@ except (AttributeError, ImportError): + # Frequency Domain Filtering + register_mjlab_task( + task_id="VR-M3-12DOF-Foothold-FDF", +- env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(), ++ env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(mask_fraction=0.1), + play_env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(play=True), + rl_cfg=vr_m3_12dof_foothold_fdf_vr_rsl_rl_runner_cfg(), + runner_cls=VelocityOnPolicyRunner, \ No newline at end of file diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff new file mode 100644 index 0000000000000000000000000000000000000000..7d752229105146469e937c736f4169b4e7cde8e5 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff @@ -0,0 +1,12 @@ +--- git commit --- +13b0b308e7cd73f7d4188a8a3cde9a98db717e0f + + +--- git status --- +On branch main +Your branch is up to date with 'origin/main'. + +nothing to commit, working tree clean + + +--- git diff --- diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_0.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_0.pt new file mode 100644 index 0000000000000000000000000000000000000000..cf121334a76f31073afbf1ba6ad9050942f10005 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_0.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d850e035aa08b3366d36095a83adfa522b58555ecdbed7260f97715c1ab1419 +size 125693797 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_1000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_1000.pt new file mode 100644 index 0000000000000000000000000000000000000000..c7449644407229aa5836c546062123ab1048b804 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_1000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c2432e34fd154f17bc0e27c674b58102b1d7008fabf30e002af881f417f62d6 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_10000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_10000.pt new file mode 100644 index 0000000000000000000000000000000000000000..40f84141ef596a9655cdd08d00d8cc2247a13d3e --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_10000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7685cbeebc42fed4f06078950f47869ddde12ab81da4a99a3ce2e8499b0a9804 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_11000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_11000.pt new file mode 100644 index 0000000000000000000000000000000000000000..f32c5d32412776df133021d57453769bbc938d3b --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_11000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a31ffd0387b8431be7740c00763879d86a66373eab386d0805b13cc5200eea79 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_12000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_12000.pt new file mode 100644 index 0000000000000000000000000000000000000000..27742f03eedfa833ee6da5b6a9d0864a9e94e2e8 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_12000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d81fce1ce3c84ca0329b2d781feafc20a3c5afad915ea34ce9e3984edd8db8ec +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_13000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_13000.pt new file mode 100644 index 0000000000000000000000000000000000000000..a1769797888118c887961e9a1eff04e6f6dbd1b8 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_13000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2084898a7270fa845da6756bdd0b5aba988b9fc413fe351ae0333ca2a6771c34 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_14000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_14000.pt new file mode 100644 index 0000000000000000000000000000000000000000..5a29f39a0e625c4321fe31ff2385be224766f3b2 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_14000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2892edfba53832d2d92c29e60c5468c98d68ca0881b8dfed0131d3036c940225 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_15000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_15000.pt new file mode 100644 index 0000000000000000000000000000000000000000..83b83e2b8f0cd806ff4524b1192def58ef9ff0a1 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_15000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f220378de6781912c145c1637f33265a3960d414db09454ddebd2e939fec6edc +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_2000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_2000.pt new file mode 100644 index 0000000000000000000000000000000000000000..a1b2d3395e68c71865b1b3b6a885fcebdabe5191 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_2000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d6b2db6894ceeacf5b14c820af21ab031e71c895cb464dcbede5c67a27cd1901 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_3000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_3000.pt new file mode 100644 index 0000000000000000000000000000000000000000..624e8de84c4446f58dfee7b9ed54366a1bfb9db0 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_3000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7c75d06fe7c5a6acaa4e7b7b0bbeadca230bc49816d6132db69a59b268e017b +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_4000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_4000.pt new file mode 100644 index 0000000000000000000000000000000000000000..2d004e93c47ea45e0478e2974949a6ed75176cd0 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_4000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8abc01b9f1d53ac287456ab78144797b01bdfb8560f9d8aa2f2569a24940cc5 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_5000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_5000.pt new file mode 100644 index 0000000000000000000000000000000000000000..e4d8ec07bf3cddf488c6a15328e1d6be3971ba13 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_5000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4472b8c50ab3454efd6dcbd7594d2d6d240e60b887b5a5235111b2d6b39d231c +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_6000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_6000.pt new file mode 100644 index 0000000000000000000000000000000000000000..7324b0020dcec4cfebee43f7df0111ff6a3ba66f --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_6000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e35102d0878d04654af126b843b8db3448963925e83a7a238a9511a4174ad6df +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_7000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_7000.pt new file mode 100644 index 0000000000000000000000000000000000000000..fbc0fba31c57a2766a24ae74584440cced004dd9 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_7000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53d5c367d995b7b25524fcb45553defa6bdbce7d46cbe140dd3547bdc19cd2a3 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_8000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_8000.pt new file mode 100644 index 0000000000000000000000000000000000000000..39157dd6017429771a3efb62b7ebe4b8403fcdab --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_8000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57f79ae3a2a7f27f01b25ce45cf80e768b8187dadc4f9bb0c470579897c43a26 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_9000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_9000.pt new file mode 100644 index 0000000000000000000000000000000000000000..eb120da4b3d5a95ddd16ab9bc6e275a162cf8ff1 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/model_9000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8350585bbfb7f0ae8d3b469f130e02c773e745d9214fa79ac068a09dc9e1bfde +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/agent.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/agent.yaml new file mode 100644 index 0000000000000000000000000000000000000000..aa9b9f4a68d6235397146bc0edd8227bbcb7d230 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/agent.yaml @@ -0,0 +1,139 @@ +seed: 42 +num_steps_per_env: 24 +max_iterations: 100001 +obs_groups: + actor: + - base_ang_vel + - projected_gravity + - velocity_commands + - joint_pos_rel + - joint_vel_rel + - last_action + - gait_phase + - depth_image + critic: + - base_ang_vel + - projected_gravity + - velocity_commands + - joint_pos_rel + - joint_vel_rel + - last_action + - gait_phase + - base_lin_vel + - true_base_velocity + - foot_height + - foot_air_time + - foot_contact + - foot_contact_forces + - knee_reference + - height_scan + - foothold_target + - depth_image +save_interval: 1000 +experiment_name: vr_m3_12dof_dwt_foothold +run_name: vr_m3_12dof_dwt_foothold +logger: wandb +wandb_project: vr_m3_12dof +wandb_tags: !!python/tuple [] +resume: false +load_run: .* +load_checkpoint: model_.*.pt +clip_actions: null +upload_model: true +class_name: OnPolicyRunner +actor: + hidden_dims: !!python/tuple + - 1024 + - 512 + - 256 + - 128 + activation: elu + obs_normalization: true + cnn_cfg: + output_channels: !!python/tuple + - 32 + - 32 + kernel_size: !!python/tuple + - 3 + - 3 + stride: !!python/tuple + - 1 + - 1 + dilation: !!python/tuple + - 1 + - 1 + padding: 1 + padding_mode: replicate + norm: none + activation: relu + max_pool: false + max_pool_kernel_size: 3 + max_pool_stride: 2 + max_pool_padding: 0 + global_pool: none + head_output_dim: 64 + head_hidden_dims: + - 128 + - 64 + head_activation: relu + head_last_activation: relu + distribution_cfg: + init_std: 1.0 + std_type: scalar +critic: + hidden_dims: !!python/tuple + - 1024 + - 512 + - 256 + - 128 + activation: elu + obs_normalization: true + cnn_cfg: + output_channels: !!python/tuple + - 32 + - 32 + kernel_size: !!python/tuple + - 3 + - 3 + stride: !!python/tuple + - 1 + - 1 + dilation: !!python/tuple + - 1 + - 1 + padding: 1 + padding_mode: replicate + norm: none + activation: relu + max_pool: false + max_pool_kernel_size: 3 + max_pool_stride: 2 + max_pool_padding: 0 + global_pool: none + head_output_dim: 64 + head_hidden_dims: + - 128 + - 64 + head_activation: relu + head_last_activation: relu + distribution_cfg: + init_std: 1.0 + std_type: scalar +algorithm: + num_learning_epochs: 5 + num_mini_batches: 4 + learning_rate: 0.001 + schedule: adaptive + gamma: 0.99 + lam: 0.95 + entropy_coef: 0.005 + desired_kl: 0.01 + max_grad_norm: 1.0 + value_loss_coef: 1.0 + use_clipped_value_loss: true + clip_param: 0.2 + normalize_advantage_per_mini_batch: false + optimizer: adam + rnd_cfg: null + symmetry_cfg: null +multi_gpu: null diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/deploy.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/deploy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dbd7e02dc374facc48858c8643974a083663acca --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/deploy.yaml @@ -0,0 +1,93 @@ +joint_name: [left_hip_pitch_joint, left_hip_roll_joint, left_hip_yaw_joint, left_knee_pitch_joint, + left_ankle_pitch_joint, left_ankle_roll_joint, right_hip_pitch_joint, right_hip_roll_joint, + right_hip_yaw_joint, right_knee_pitch_joint, right_ankle_pitch_joint, right_ankle_roll_joint] +joint_ids_map: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] +step_dt: 0.02 +stiffness: [150.0, 150.0, 120.0, 200.0, 200.0, 200.0, 150.0, 150.0, 120.0, 200.0, + 200.0, 200.0] +damping: [25.0, 25.0, 4.0, 10.0, 8.0, 8.0, 25.0, 25.0, 4.0, 10.0, 8.0, 8.0] +default_joint_pos: [-0.1, 0.0, 0.0, 0.2, -0.1, 0.0, -0.1, 0.0, 0.0, 0.2, -0.1, 0.0] +commands: + twist: + ranges: + lin_vel_x: [0.0, 1.0] + lin_vel_y: [0.0, 0.0] + ang_vel_z: [-0.5, 0.5] + heading: null +actions: + JointPositionAction: + clip: null + scale: [0.6, 0.6, 0.271, 0.45, 0.15, 0.15, 0.6, 0.6, 0.271, 0.45, 0.15, 0.15] + offset: [-0.1, 0.0, 0.0, 0.2, -0.1, 0.0, -0.1, 0.0, 0.0, 0.2, -0.1, 0.0] + joint_names: [.*] + joint_ids: null +observations: + base_ang_vel: + params: {sensor_name: robot/imu_ang_vel} + clip: null + scale: [0.25, 0.25, 0.25] + history_length: 5 + projected_gravity: + params: {} + clip: null + scale: [1.0, 1.0, 1.0] + history_length: 5 + velocity_commands: + params: {command_name: twist} + clip: null + scale: [1.0, 1.0, 1.0] + history_length: 5 + joint_pos_rel: + params: {} + clip: null + scale: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + history_length: 5 + joint_vel_rel: + params: {} + clip: null + scale: [0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05] + history_length: 5 + last_action: + params: {} + clip: null + scale: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + history_length: 5 + gait_phase: + params: {period: 0.9, command_name: twist} + clip: null + scale: [1.0, 1.0] + history_length: 5 + depth_image: + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice [null, null, null] + body_names: null + body_ids: !!python/object/apply:builtins.slice [null, null, null] + geom_names: null + geom_ids: !!python/object/apply:builtins.slice [null, null, null] + site_names: null + site_ids: !!python/object/apply:builtins.slice [null, null, null] + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice [null, null, null] + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice [null, null, null] + camera_names: null + camera_ids: !!python/object/apply:builtins.slice [null, null, null] + light_names: null + light_ids: !!python/object/apply:builtins.slice [null, null, null] + material_names: null + material_ids: !!python/object/apply:builtins.slice [null, null, null] + pair_names: null + pair_ids: !!python/object/apply:builtins.slice [null, null, null] + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: [0, 1] + debug_vis: false + mask_fraction: 0.1 + clip: null + scale: [1.0, 1.0, 1.0, 1.0] + history_length: 1 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/env.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/env.yaml new file mode 100644 index 0000000000000000000000000000000000000000..883473cdb4250de06309cd65d36980dafec339bf --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/env.yaml @@ -0,0 +1,3768 @@ +decimation: 4 +scene: + num_envs: 1024 + env_spacing: 2.0 + terrain: + init_state: + pos: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + rot: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.0 + lin_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + ang_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + joint_pos: + .*: 0.0 + joint_vel: + .*: 0.0 + spec_fn: !!python/name:mjlab.entity.entity.%3Clambda%3E '' + articulation: null + sort_actuators: false + lights: !!python/tuple + - name: sun + body: world + mode: fixed + target: null + type: directional + castshadow: true + pos: !!python/tuple + - 0.0 + - 0.0 + - 1.5 + dir: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + cutoff: 45.0 + exponent: 10.0 + cameras: !!python/tuple [] + textures: !!python/tuple + - name: groundplane + type: 2d + builtin: checker + rgb1: !!python/tuple + - 0.2 + - 0.3 + - 0.4 + rgb2: !!python/tuple + - 0.1 + - 0.2 + - 0.3 + width: 300 + height: 300 + mark: edge + markrgb: !!python/tuple + - 0.8 + - 0.8 + - 0.8 + materials: !!python/tuple + - name: groundplane + rgba: !!python/tuple + - 1.0 + - 1.0 + - 1.0 + - 1.0 + texuniform: true + texrepeat: !!python/tuple + - 4.0 + - 4.0 + reflectance: 0.2 + texture: groundplane + geom_names_expr: !!python/tuple + - terrain$ + collisions: !!python/tuple [] + terrain_type: generator + terrain_generator: + seed: null + curriculum: true + size: !!python/tuple + - 8.0 + - 8.0 + border_width: 1.0 + border_height: 1.0 + num_rows: 10 + num_cols: 14 + color_scheme: height + sub_terrains: + flat: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + pyramid_stairs: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.3 + platform_width: 3.0 + holes: false + pyramid_stairs_med: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.45 + platform_width: 3.0 + holes: false + pyramid_stairs_wide: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.6 + platform_width: 3.0 + holes: false + pyramid_stairs_inv: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.3 + platform_width: 3.0 + holes: false + pyramid_stairs_inv_med: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.45 + platform_width: 3.0 + holes: false + pyramid_stairs_inv_wide: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.6 + platform_width: 3.0 + holes: false + open_stairs_pyramid: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width_range: !!python/tuple + - 0.3 + - 0.6 + platform_width: 3.0 + border_width: 1.0 + step_thickness: 0.05 + inverted: false + open_stairs_bowl: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width_range: !!python/tuple + - 0.3 + - 0.6 + platform_width: 3.0 + border_width: 1.0 + step_thickness: 0.05 + inverted: true + hf_pyramid_slope: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + slope_range: !!python/tuple + - 0.0 + - 0.4 + platform_width: 2.0 + inverted: false + border_width: 0.25 + horizontal_scale: 0.2 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + hf_pyramid_slope_inv: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + slope_range: !!python/tuple + - 0.0 + - 0.4 + platform_width: 2.0 + inverted: true + border_width: 0.25 + horizontal_scale: 0.2 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + stepping_stones: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 30 + patch_radius: 0.2 + max_height_diff: 0.03 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + stone_size_range: !!python/tuple + - 0.4 + - 0.8 + stone_distance_range: !!python/tuple + - 0.2 + - 0.5 + stone_height: 0.2 + stone_height_variation: 0.05 + stone_size_variation: 0.1 + floor_depth: 2.0 + displacement_range: 0.1 + platform_width: 1.0 + border_width: 0.0 + uniform_noise: + proportion: 0.15 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + noise_range: !!python/tuple + - 0.02 + - 0.1 + noise_step: 0.02 + downsampled_scale: null + horizontal_scale: 0.1 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + border_width: 0.25 + difficulty_range: !!python/tuple + - 0.0 + - 1.0 + add_lights: true + env_spacing: 2.0 + max_init_terrain_level: 5 + num_envs: 1024 + entities: + robot: + init_state: + pos: !!python/tuple + - 0 + - 0 + - 0.9 + rot: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.0 + lin_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + ang_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + joint_pos: + .*_hip_pitch_joint: -0.1 + .*_hip_roll_joint: 0.0 + .*_hip_yaw_joint: 0.0 + .*_knee_pitch_joint: 0.2 + .*_ankle_pitch_joint: -0.1 + .*_ankle_roll_joint: 0.0 + joint_vel: + .*: 0.0 + spec_fn: !!python/name:src.assets.robots.vr_m3.vr_m3_12dof_constants.get_spec '' + articulation: + actuators: !!python/tuple + - target_names_expr: !!python/tuple + - .*_hip_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 150.0 + damping: 25.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_hip_roll_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 150.0 + damping: 25.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_hip_yaw_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.02864 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 120.0 + damping: 4.0 + effort_limit: 130.0 + - target_names_expr: !!python/tuple + - .*_knee_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 10.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_ankle_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.03006 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 8.0 + effort_limit: 120.0 + - target_names_expr: !!python/tuple + - .*_ankle_roll_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.03006 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 8.0 + effort_limit: 120.0 + soft_joint_pos_limit_factor: 0.9 + sort_actuators: false + lights: !!python/tuple [] + cameras: !!python/tuple [] + textures: !!python/tuple [] + materials: !!python/tuple [] + collisions: !!python/tuple + - geom_names_expr: !!python/tuple + - .*_collision_\d+ + contype: 1 + conaffinity: 1 + condim: + ^(left|right)_ankle_roll_link_collision_\d+$: 3 + .*_collision_\d+: 1 + priority: + ^(left|right)_ankle_roll_link_collision_\d+$: 1 + friction: + ^(left|right)_ankle_roll_link_collision_\d+$: !!python/tuple + - 0.6 + solref: null + solimp: null + margin: null + gap: null + solmix: null + disable_other_geoms: true + sensors: !!python/tuple + - name: feet_ground_contact + primary: + mode: subtree + pattern: ^(left_ankle_roll_link|right_ankle_roll_link)$ + entity: robot + exclude: !!python/tuple [] + secondary: + mode: body + pattern: terrain + entity: null + exclude: !!python/tuple [] + fields: !!python/tuple + - found + - force + reduce: netforce + num_slots: 1 + secondary_policy: first + track_air_time: true + global_frame: false + history_length: 4 + debug: false + - name: self_collision + primary: + mode: subtree + pattern: pelvis + entity: robot + exclude: !!python/tuple [] + secondary: + mode: subtree + pattern: pelvis + entity: robot + exclude: !!python/tuple [] + fields: !!python/tuple + - found + - force + reduce: none + num_slots: 1 + secondary_policy: first + track_air_time: false + global_frame: false + history_length: 4 + debug: false + - name: pelvis_height_measure + frame: + type: body + name: pelvis + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 2.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: left_height_scanner + frame: + type: site + name: left_foot + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 1.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: right_height_scanner + frame: + type: site + name: right_foot + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 1.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: terrain_scan + frame: + type: body + name: pelvis + entity: robot + pattern: + size: !!python/tuple + - 1.8 + - 1.2 + resolution: 0.05 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 2.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: true + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: camera + frame: + type: body + name: pelvis + entity: robot + pattern: + width: 80 + height: 60 + fovy: 63.668103675039276 + _camera_name: null + ray_alignment: base + max_distance: 2.5 + exclude_parent_body: false + include_geom_groups: !!python/tuple + - 0 + - 1 + - 2 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + class_type: !!python/name:instinct_mj.sensors.noisy_camera.noisy_grouped_raycaster_camera.NoisyGroupedRayCasterCamera '' + min_distance: 0.1 + mesh_prim_paths: [] + aux_mesh_and_link_names: {} + mesh_filter_max_hops: 24 + mesh_filter_epsilon: 0.0001 + offset: + pos: !!python/tuple + - 0.0 + - 0.018 + - -0.1 + rot: !!python/tuple + - 0.8660254037844387 + - 0.0 + - 0.49999999999999994 + - 0.0 + convention: world + data_types: + - distance_to_image_plane + update_period: 0.03333333333333333 + depth_clipping_behavior: max + focal_length: 1.0 + horizontal_aperture: 1.6555983034386739 + vertical_aperture: 1.2416987275790055 + horizontal_aperture_offset: 0.0 + vertical_aperture_offset: 0.0 + visualizer_cfg: + prim_path: /Visuals/RayCaster + markers: + hit: !!python/object/apply:types.SimpleNamespace + state: + radius: 0.02 + color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 1.0 + frame: !!python/object/apply:types.SimpleNamespace + state: + scale: !!python/tuple + - 0.1 + - 0.1 + - 0.1 + noise_pipeline: + crop_and_resize: + func: !!python/name:instinct_mj.utils.noise.noise_model.crop_and_resize '' + device: cuda:0 + crop_region: !!python/tuple + - 0 + - 0 + - 10 + - 10 + resize_shape: !!python/tuple + - 30 + - 30 + gaussian_blur: + func: !!python/name:instinct_mj.utils.noise.noise_model.gaussian_blur_noise '' + device: cuda:0 + kernel_size: 3 + sigma: 1 + depth_normalization: + func: !!python/name:instinct_mj.utils.noise.noise_model.depth_normalization '' + device: cuda:0 + depth_range: !!python/tuple + - 0.0 + - 2.5 + normalize: true + output_range: !!python/tuple + - 0.0 + - 1.0 + data_histories: + distance_to_image_plane_noised: 17 + - name: undesired_contact_forces + primary: + mode: body + pattern: .* + entity: robot + exclude: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + secondary: null + fields: !!python/tuple + - found + - force + reduce: netforce + num_slots: 1 + secondary_policy: first + track_air_time: false + global_frame: false + history_length: 3 + debug: false + extent: 2.0 + spec_fn: null +observations: + critic: + terms: + base_ang_vel: + func: &id001 !!python/name:mjlab.envs.mdp.observations.builtin_sensor '' + params: + sensor_name: robot/imu_ang_vel + noise: + operation: add + _tensor_cache: {} + n_min: -0.25 + n_max: 0.25 + clip: null + scale: 0.25 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + projected_gravity: + func: &id002 !!python/name:mjlab.envs.mdp.observations.projected_gravity '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + velocity_commands: + func: &id003 !!python/name:mjlab.envs.mdp.observations.generated_commands '' + params: + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_pos_rel: + func: &id004 !!python/name:mjlab.envs.mdp.observations.joint_pos_rel '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_vel_rel: + func: &id005 !!python/name:mjlab.envs.mdp.observations.joint_vel_rel '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -1.5 + n_max: 1.5 + clip: null + scale: 0.05 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + last_action: + func: &id006 !!python/name:mjlab.envs.mdp.observations.last_action '' + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + gait_phase: + func: &id007 !!python/name:src.tasks.velocity.mdp.observations.phase '' + params: + period: 0.9 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + base_lin_vel: + func: *id001 + params: + sensor_name: robot/imu_lin_vel + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + true_base_velocity: + func: !!python/name:mjlab.envs.mdp.observations.base_lin_vel '' + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_height: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_height '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_air_time: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_air_time '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_contact: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_contact '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_contact_forces: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_contact_forces '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + knee_reference: + func: !!python/name:src.tasks.velocity.mdp.rewards.get_desired_knee_angle '' + params: + period: 0.9 + offset: + - 0.0 + - 0.5 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + height_scan: + func: !!python/name:mjlab.envs.mdp.observations.height_scan '' + params: + sensor_name: terrain_scan + miss_value: 2.0 + noise: null + clip: !!python/tuple + - 0.0 + - 2.0 + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + foothold_target: + func: !!python/name:src.tasks.velocity.mdp.observations.foothold_target '' + params: + command_name: foothold + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + depth_image: + func: !!python/name:src.tasks.velocity.mdp.observations.DepthImageFFTLowpass '' + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: !!python/tuple + - 0 + - 1 + debug_vis: false + mask_fraction: 0.1 + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + concatenate_terms: false + concatenate_dim: -1 + enable_corruption: false + history_length: null + flatten_history_dim: true + nan_policy: sanitize + nan_check_per_term: true + actor: + terms: + base_ang_vel: + func: *id001 + params: + sensor_name: robot/imu_ang_vel + noise: + operation: add + _tensor_cache: {} + n_min: -0.25 + n_max: 0.25 + clip: null + scale: 0.25 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + projected_gravity: + func: *id002 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + velocity_commands: + func: *id003 + params: + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_pos_rel: + func: *id004 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_vel_rel: + func: *id005 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -1.5 + n_max: 1.5 + clip: null + scale: 0.05 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + last_action: + func: *id006 + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + gait_phase: + func: *id007 + params: + period: 0.9 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + depth_image: + func: !!python/name:src.tasks.velocity.mdp.observations.DepthImageFFTLowpass '' + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: !!python/tuple + - 0 + - 1 + debug_vis: false + mask_fraction: 0.1 + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + concatenate_terms: false + concatenate_dim: -1 + enable_corruption: true + history_length: null + flatten_history_dim: true + nan_policy: sanitize + nan_check_per_term: true +actions: + joint_pos: + entity_name: robot + clip: null + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + actuator_names: !!python/tuple + - .* + scale: + .*_hip_pitch_joint: 0.6 + .*_hip_roll_joint: 0.6 + .*_hip_yaw_joint: 0.2708333333333333 + .*_knee_pitch_joint: 0.45 + .*_ankle_pitch_joint: 0.15 + .*_ankle_roll_joint: 0.15 + offset: 0.0 + preserve_order: false + use_default_offset: true +events: + reset_base: + func: !!python/name:mjlab.envs.mdp.events.reset_root_state_uniform '' + params: + pose_range: + x: !!python/tuple + - -0.5 + - 0.5 + y: !!python/tuple + - -0.5 + - 0.5 + z: !!python/tuple + - 0.0 + - 0.0 + yaw: !!python/tuple + - -3.14 + - 3.14 + mode: reset + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + reset_robot_joints: + func: !!python/name:mjlab.envs.mdp.events.reset_joints_by_offset '' + params: + position_range: !!python/tuple + - -0.1 + - 0.1 + velocity_range: !!python/tuple + - -0.5 + - 0.5 + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + mode: reset + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + push_robot: + func: !!python/name:mjlab.envs.mdp.events.push_by_setting_velocity '' + params: + velocity_range: + x: !!python/tuple + - -0.5 + - 0.5 + y: !!python/tuple + - -0.5 + - 0.5 + z: !!python/tuple + - -0.4 + - 0.4 + roll: !!python/tuple + - -0.52 + - 0.52 + pitch: !!python/tuple + - -0.52 + - 0.52 + yaw: !!python/tuple + - -0.78 + - 0.78 + mode: interval + interval_range_s: !!python/tuple + - 5.0 + - 6.0 + is_global_time: false + min_step_count_between_reset: 0 + foot_friction: + func: !!python/name:mjlab.envs.mdp.dr.geom.geom_friction '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: !!python/tuple + - left_ankle_roll_link_collision_1 + - left_ankle_roll_link_collision_2 + - left_ankle_roll_link_collision_3 + - left_ankle_roll_link_collision_4 + - left_ankle_roll_link_collision_5 + - left_ankle_roll_link_collision_6 + - left_ankle_roll_link_collision_7 + - left_ankle_roll_link_collision_8 + - left_ankle_roll_link_collision_9 + - left_ankle_roll_link_collision_10 + - right_ankle_roll_link_collision_1 + - right_ankle_roll_link_collision_2 + - right_ankle_roll_link_collision_3 + - right_ankle_roll_link_collision_4 + - right_ankle_roll_link_collision_5 + - right_ankle_roll_link_collision_6 + - right_ankle_roll_link_collision_7 + - right_ankle_roll_link_collision_8 + - right_ankle_roll_link_collision_9 + - right_ankle_roll_link_collision_10 + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: abs + ranges: !!python/tuple + - 0.3 + - 1.6 + shared_random: true + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + encoder_bias: + func: !!python/name:mjlab.envs.mdp.dr.joint.encoder_bias '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + bias_range: !!python/tuple + - -0.015 + - 0.015 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + base_com: + func: &id008 !!python/name:mjlab.envs.mdp.dr.body.body_com_offset '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: + 0: !!python/tuple + - -0.05 + - 0.05 + 1: !!python/tuple + - -0.05 + - 0.05 + 2: !!python/tuple + - -0.05 + - 0.05 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + body_com: + func: *id008 + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - ^(?!waist_yaw_link$).* + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: + 0: !!python/tuple + - -0.03 + - 0.03 + 1: !!python/tuple + - -0.03 + - 0.03 + 2: !!python/tuple + - -0.03 + - 0.03 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + base_mass: + func: &id009 !!python/name:mjlab.envs.mdp.dr.body.body_mass '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: !!python/tuple + - -4.0 + - 4.0 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + body_mass: + func: *id009 + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - ^(?!waist_yaw_link$).* + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.9 + - 1.1 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_actuator_gains: + func: !!python/name:mjlab.envs.mdp.dr.actuator.pd_gains '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + kp_range: !!python/tuple + - 0.7 + - 1.1 + kd_range: !!python/tuple + - 0.7 + - 1.1 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_limit: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_limits '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.94 + - 1.06 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_stiffness: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_stiffness '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.7 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_frictionloss: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_friction '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.1 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_armature: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_armature '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.2 + - 5.0 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_damping: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_damping '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.7 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_ray_offsets: + func: !!python/name:instinct_mj.envs.mdp.events.randomization.randomize_ray_offsets '' + params: + asset_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + offset_pose_ranges: + x: !!python/tuple + - -0.01 + - 0.01 + y: !!python/tuple + - -0.01 + - 0.01 + z: !!python/tuple + - -0.03 + - 0.01 + roll: !!python/tuple + - -0.03490658503988659 + - 0.03490658503988659 + pitch: !!python/tuple + - -0.17453292519943295 + - 0.17453292519943295 + yaw: !!python/tuple + - -0.03490658503988659 + - 0.03490658503988659 + distribution: uniform + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 +seed: 42 +sim: + nconmax: 128 + njmax: 700 + ls_parallel: true + contact_sensor_maxmatch: 500 + mujoco: + timestep: 0.005 + integrator: implicitfast + impratio: 1.0 + cone: pyramidal + jacobian: auto + solver: newton + iterations: 10 + tolerance: 1.0e-08 + ls_iterations: 20 + ls_tolerance: 0.01 + ccd_iterations: 500 + gravity: !!python/tuple + - 0.0 + - 0.0 + - -9.81 + disableflags: !!python/tuple [] + enableflags: !!python/tuple [] + nan_guard: + enabled: false + buffer_size: 100 + output_dir: /tmp/mjlab/nan_dumps + max_envs_to_dump: 5 +viewer: + lookat: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + distance: 3.0 + fovy: null + elevation: -5.0 + azimuth: 90.0 + origin_type: !!python/object/apply:mjlab.viewer.viewer_config.OriginType + - 4 + entity_name: robot + body_name: waist_yaw_link + env_idx: 0 + max_extra_envs: 2 + enable_reflections: true + enable_shadows: true + height: 240 + width: 320 +episode_length_s: 20.0 +rewards: + track_linear_velocity: + func: !!python/name:src.tasks.velocity.mdp.rewards.track_linear_velocity '' + params: + command_name: twist + std: 0.5 + weight: 3.5 + track_angular_velocity: + func: !!python/name:src.tasks.velocity.mdp.rewards.track_angular_velocity '' + params: + command_name: twist + std: 0.7071067811865476 + weight: 3.0 + flat_orientation: + func: !!python/name:mjlab.envs.mdp.rewards.flat_orientation_l2 '' + params: {} + weight: -7.0 + pelvis_orientation_l2: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.link_orientation '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: pelvis + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -3.0 + joint_deviation_hip: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.joint_deviation_square '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .*_hip_yaw_joint + - .*_hip_roll_joint + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.3 + ang_vel_xy_l2: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.ang_vel_xy_l2 '' + params: {} + weight: -0.1 + dof_torques_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_torques_l2 '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .*_hip_.* + - .*_knee_.* + - .*_ankle_.* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0e-08 + dof_vel_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_vel_l2 '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -5.0e-07 + feet_flat_ori: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.feet_orientation_contact '' + params: + sensor_name: feet_ground_contact + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.01 + body_ang_vel: + func: !!python/name:src.tasks.velocity.mdp.rewards.body_angular_velocity_penalty '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.05 + angular_momentum: + func: !!python/name:src.tasks.velocity.mdp.rewards.angular_momentum_penalty '' + params: + sensor_name: robot/root_angmom + weight: -0.001 + is_terminated: + func: !!python/name:mjlab.envs.mdp.rewards.is_terminated '' + params: {} + weight: -200.0 + joint_acc_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_acc_l2 '' + params: {} + weight: -5.0e-07 + joint_pos_limits: + func: &id010 !!python/name:mjlab.envs.mdp.rewards.joint_pos_limits '' + params: {} + weight: -1.0 + action_rate_l2: + func: !!python/name:mjlab.envs.mdp.rewards.action_rate_l2 '' + params: {} + weight: -0.8 + foot_gait: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_gait '' + params: + period: 0.9 + offset: + - 0.0 + - 0.5 + threshold: 0.6 + command_threshold: 0.1 + command_name: twist + sensor_name: feet_ground_contact + weight: 2.0 + feet_double_support: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_double_support '' + params: + sensor_name: feet_ground_contact + period: 0.9 + offset: + - 0.0 + - 0.5 + threshold: 0.6 + command_name: twist + cmd_threshold: 0.1 + ds_match_weight: 1.0 + weight: 1.5 + foot_slip: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_slip '' + params: + sensor_name: feet_ground_contact + command_name: twist + command_threshold: 0.1 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.4 + feet_close_xy: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_close_xy_gauss '' + params: + threshold: 0.2 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + std: 0.22360679774997896 + weight: 1.0 + soft_landing: + func: !!python/name:src.tasks.velocity.mdp.rewards.soft_landing '' + params: + sensor_name: feet_ground_contact + command_name: twist + command_threshold: 0.1 + weight: -0.001 + dont_wait: + func: !!python/name:src.tasks.velocity.mdp.rewards.dont_wait '' + params: + command_name: twist + cmd_threshold: 0.1 + weight: -1.0 + stand_still: + func: !!python/name:src.tasks.velocity.mdp.rewards.stand_still '' + params: + command_name: twist + command_threshold: 0.1 + asset_cfg: + name: robot + joint_names: .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0 + self_collisions: + func: !!python/name:src.tasks.velocity.mdp.rewards.self_collision_cost '' + params: + sensor_name: self_collision + force_threshold: 10.0 + weight: -2.0 + feet_air_time: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_air_time '' + params: + sensor_name: feet_ground_contact + threshold: 0.36000000000000004 + command_name: twist + command_threshold: 0.1 + weight: 1.0 + feet_air_time_biped: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_air_time_positive_biped '' + params: + command_name: twist + sensor_name: feet_ground_contact + threshold: 0.52 + weight: 2.0 + terrain_foot_clearance: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_foot_clearance_cost '' + params: + target_clearance: 0.06 + left_terrain_sensor: left_height_scanner + right_terrain_sensor: right_height_scanner + command_name: twist + command_threshold: 0.05 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.5 + terrain_stumble: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_stumble_cost '' + params: + sensor_cfg: + name: feet_ground_contact + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + velocity_threshold: 0.15 + weight: -0.5 + terrain_base_height: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_base_height_l2_cost '' + params: + target_height: 0.9 + base_terrain_sensor: pelvis_height_measure + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.5 + feet_slide: + func: !!python/name:instinct_mj.tasks.parkour.mdp.rewards.feet_slide '' + params: + sensor_name: feet_ground_contact + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + threshold: 1.0 + weight: -0.4 + dof_pos_limits: + func: *id010 + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0 + foothold_tracking: + func: !!python/name:src.tasks.velocity.mdp.rewards.foothold_tracking '' + params: + command_name: foothold + sigma_stages: + - !!python/tuple + - 10.0 + - 5.0 + - !!python/tuple + - 20.0 + - 10.0 + - !!python/tuple + - 30.0 + - 15.0 + stage_step_counts: + - 0 + - 96000 + - 192000 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + sensor_name: feet_ground_contact + velocity_command_name: twist + velocity_command_threshold: 0.1 + weight: 2.1 +terminations: + time_out: + func: !!python/name:mjlab.envs.mdp.terminations.time_out '' + params: {} + time_out: true + fell_over: + func: !!python/name:mjlab.envs.mdp.terminations.bad_orientation '' + params: + limit_angle: 1.2217304763960306 + time_out: false + nan_term: + func: !!python/name:mjlab.envs.mdp.terminations.nan_detection '' + params: {} + time_out: false + base_height: + func: !!python/name:src.tasks.velocity.mdp.rewards.root_height_below_minimum_terrain '' + params: + minimum_height: 0.3 + terrain_sensor_name: pelvis_height_measure + time_out: false +commands: + twist: + resampling_time_range: !!python/tuple + - 3.0 + - 8.0 + debug_vis: true + entity_name: robot + heading_command: false + heading_control_stiffness: 0.5 + rel_standing_envs: 0.05 + rel_heading_envs: 1.0 + rel_world_envs: 0.0 + rel_forward_envs: 0.0 + init_velocity_prob: 0.0 + ranges: + lin_vel_x: !!python/tuple + - 0.0 + - 1.0 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.5 + - 0.5 + heading: null + viz: + z_offset: 1.15 + scale: 0.5 + foothold: + resampling_time_range: !!python/tuple + - 1000000000.0 + - 1000000000.0 + debug_vis: false + entity_name: robot + terrain_sensor_name: terrain_scan + contact_sensor_name: feet_ground_contact + velocity_command_name: twist + foot_site_names: !!python/tuple + - left_foot + - right_foot + gait_period: 0.9 + gait_action_name: gait_freq + nominal_height_m: 0.9 + lateral_inter_foot_m: 0.22 + foot_footprint_m: !!python/tuple + - 0.25 + - 0.1 + search_window_m: !!python/tuple + - 0.6 + - 0.6 + elevation_size_m: !!python/tuple + - 1.8 + - 1.2 + elevation_resolution_m: 0.05 + alpha_pos: 1.0 + alpha_dcm: 0.5 + alpha_steepness: 0.6 + alpha_flatness: 4.0 + alpha_height: 6.0 + alpha_climb_bonus: 1.5 + lateral_pos_weight: 2.5 + max_step_height_m: 0.25 + climb_velocity_threshold: 0.1 + standing_threshold: 0.1 + min_step_height_m: 0.05 + max_step_velocity_m_s: 0.5 + apex_clearance_m: 0.05 + clearance_scale: 0.5 + max_clearance_m: 0.2 + pre_apex_lower_window: 0.05 + pre_apex_upper_window: 0.05 + post_apex_lower_window: 0.1 + post_apex_upper_window: 0.15 + terrain_decision_threshold: 0.1 +curriculum: + terrain_levels: + func: !!python/name:src.tasks.velocity.mdp.curriculums.terrain_levels_vel '' + params: + command_name: twist + command_vel: + func: !!python/name:src.tasks.velocity.mdp.curriculums.commands_vel '' + params: + command_name: twist + velocity_stages: + - step: 0 + lin_vel_x: !!python/tuple + - 0.0 + - 0.5 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.2 + - 0.2 + - step: 120000 + lin_vel_x: !!python/tuple + - 0.0 + - 1.0 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.5 + - 0.5 +metrics: + mean_action_acc: + func: !!python/name:mjlab.envs.mdp.metrics.mean_action_acc '' + params: {} + per_substep: false + reduce: mean +recorders: {} +is_finite_horizon: false +auto_reset: true +scale_rewards_by_dt: true diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/env_cfgs.py b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/env_cfgs.py new file mode 100644 index 0000000000000000000000000000000000000000..29089b5f5af0e3df29b5cbf63f61fd363ef389ab --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/params/env_cfgs.py @@ -0,0 +1,2716 @@ +"""VinRobotics VR-M3 12DOF (lower-body only) velocity environment configurations. + +Self-contained: this module builds the full `ManagerBasedRlEnvCfg` inline +rather than deriving from `src.tasks.velocity.velocity_env_cfg`, so changes +to the shared factory do not silently affect VR-M3 12DOF training. +""" + +import math +from copy import deepcopy +from dataclasses import dataclass, replace +import numpy as np + +import instinct_mj.envs.mdp as instinct_mdp + +# import instinct_mj.tasks.locomotion.mdp as instinct_locomotion_mdp +try: + import instinct_mj.tasks.parkour.mdp as instinct_parkour_mdp +except ImportError: + instinct_parkour_mdp = None # type: ignore[assignment] +from instinct_mj.sensors.noisy_camera import NoisyGroupedRayCasterCameraCfg +from instinct_mj.utils.noise import ( + CropAndResizeCfg, + DepthArtifactNoiseCfg, + DepthContourNoiseCfg, + DepthNormalizationCfg, + DepthSkyArtifactNoiseCfg, + GaussianBlurNoiseCfg, + RangeBasedGaussianNoiseCfg, + StereoTooCloseNoiseCfg, +) +from mjlab.envs import ManagerBasedRlEnvCfg +from mjlab.envs import mdp as envs_mdp +from mjlab.envs.mdp import dr +from mjlab.envs.mdp.actions import JointPositionActionCfg +from mjlab.managers.action_manager import ActionTermCfg +from mjlab.managers.command_manager import CommandTermCfg +from mjlab.managers.curriculum_manager import CurriculumTermCfg +from mjlab.managers.event_manager import EventTermCfg +from mjlab.managers.metrics_manager import MetricsTermCfg +from mjlab.managers.observation_manager import ObservationGroupCfg, ObservationTermCfg +from mjlab.managers.reward_manager import RewardTermCfg +from mjlab.managers.scene_entity_config import SceneEntityCfg +from mjlab.managers.termination_manager import TerminationTermCfg +from mjlab.scene import SceneCfg +from mjlab.sensor import ( + ContactMatch, + ContactSensorCfg, + GridPatternCfg, + ObjRef, + PinholeCameraPatternCfg, + RayCastSensorCfg, +) + +from mjlab.sim import MujocoCfg, SimulationCfg +from mjlab.tasks.velocity.mdp import UniformVelocityCommandCfg +from mjlab.terrains import TerrainEntityCfg, SubTerrainCfg +from mjlab.terrains.config import ROUGH_TERRAINS_CFG +from mjlab.utils.noise import UniformNoiseCfg as Unoise +from mjlab.viewer import ViewerConfig + +import src.tasks.velocity.mdp as mdp +from src.assets.robots import ( + VR_M3_12DOF_ACTION_SCALE, + get_vr_m3_12dof_implicit_actuator_robot_cfg, + vr_m3_12dof_joint_pos_action_scale, + vr_m3_12dof_joint_vel_action_scale, +) +from src.tasks.velocity.terrains.config import PERCEPTIVE_TERRAINS_CFG +from src.envs import MultiCriticManagerBasedRlEnvCfg + +## +# VR-M3 12DOF specific constants +## + +# 12DOF keeps the upper body kinematically but with no actuated joints, so +# `waist_yaw_link` (the torso-equivalent body) is still referenceable. +TORSO_BODY = "waist_yaw_link" + +FOOT_SITES = ("left_foot", "right_foot") +FOOT_LINK_NAMES = ("left_ankle_roll_link", "right_ankle_roll_link") + +# Same foot geometry as the fullbody XML: 10 collision geoms per ankle_roll_link. +FOOT_GEOMS = tuple( + f"{side}_ankle_roll_link_collision_{i}" + for side in ("left", "right") + for i in range(1, 11) +) + +# 12DOF only actuates legs; waist and upper body have no actuators, so the +# pose reward only lists the leg-joint regexes. +POSE_STD_STANDING: dict[str, float] = {".*": 0.05} +POSE_STD_WALKING: dict[str, float] = { + r".*hip_pitch.*": 0.5, + r".*hip_roll.*": 0.15, + r".*hip_yaw.*": 0.15, + r".*knee.*": 0.5, + r".*ankle_pitch.*": 0.15, + r".*ankle_roll.*": 0.1, +} +POSE_STD_RUNNING: dict[str, float] = { + r".*hip_pitch.*": 0.5, + r".*hip_roll.*": 0.25, + r".*hip_yaw.*": 0.25, + r".*knee.*": 0.5, + r".*ankle_pitch.*": 0.25, + r".*ankle_roll.*": 0.1, +} + +GAIT_CYCLE_PERIOD = 0.9 + + +@dataclass +class VelocityEnvCfg(ManagerBasedRlEnvCfg): + def __post_init__(self): + pass + + +def vr_m3_12dof_rough_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF rough terrain velocity configuration.""" + + ## + # Sensors + ## + + feet_ground_cfg = ContactSensorCfg( + name="feet_ground_contact", + primary=ContactMatch( + mode="subtree", + pattern=r"^(left_ankle_roll_link|right_ankle_roll_link)$", + entity="robot", + ), + secondary=ContactMatch(mode="body", pattern="terrain"), + fields=("found", "force"), + reduce="netforce", + num_slots=1, + track_air_time=True, + history_length=4, + ) + self_collision_cfg = ContactSensorCfg( + name="self_collision", + primary=ContactMatch(mode="subtree", pattern="pelvis", entity="robot"), + secondary=ContactMatch(mode="subtree", pattern="pelvis", entity="robot"), + fields=("found", "force"), + reduce="none", + num_slots=1, + history_length=4, + ) + + ## + # Observations + ## + + actor_terms = { + "base_ang_vel": ObservationTermCfg( + func=mdp.builtin_sensor, + scale=0.25, + params={"sensor_name": "robot/imu_ang_vel"}, + noise=Unoise(n_min=-0.25, n_max=0.25), + history_length=5, + flatten_history_dim=True, + ), + "projected_gravity": ObservationTermCfg( + func=mdp.projected_gravity, + noise=Unoise(n_min=-0.05, n_max=0.05), + history_length=5, + flatten_history_dim=True, + ), + "velocity_commands": ObservationTermCfg( + func=mdp.generated_commands, + params={"command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ), + "joint_pos_rel": ObservationTermCfg( + func=mdp.joint_pos_rel, + noise=Unoise(n_min=-0.05, n_max=0.05), + history_length=5, + flatten_history_dim=True, + ), + "joint_vel_rel": ObservationTermCfg( + func=mdp.joint_vel_rel, + scale=0.05, + noise=Unoise(n_min=-1.5, n_max=1.5), + history_length=5, + flatten_history_dim=True, + ), + "last_action": ObservationTermCfg( + func=mdp.last_action, history_length=5, flatten_history_dim=True + ), + "gait_phase": ObservationTermCfg( + func=mdp.phase, + params={"period": GAIT_CYCLE_PERIOD, "command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ), + } + + critic_terms = { + **actor_terms, + "base_lin_vel": ObservationTermCfg( + func=mdp.builtin_sensor, + params={"sensor_name": "robot/imu_lin_vel"}, + history_length=5, + flatten_history_dim=True, + ), + "true_base_velocity": ObservationTermCfg( + func=envs_mdp.base_lin_vel, + history_length=5, + flatten_history_dim=True, + ), + "foot_height": ObservationTermCfg( + func=mdp.foot_height, + params={"asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES)}, + history_length=5, + flatten_history_dim=True, + ), + "foot_air_time": ObservationTermCfg( + func=mdp.foot_air_time, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "foot_contact": ObservationTermCfg( + func=mdp.foot_contact, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "foot_contact_forces": ObservationTermCfg( + func=mdp.foot_contact_forces, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "knee_reference": ObservationTermCfg( + func=mdp.get_desired_knee_angle, + params={ + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "command_name": "twist", + }, + history_length=5, + flatten_history_dim=True, + ), + } + + observations = { + "actor": ObservationGroupCfg( + terms=actor_terms, + concatenate_terms=True, + enable_corruption=True, + # history_length=5, + nan_policy="sanitize", + nan_check_per_term=True, + ), + "critic": ObservationGroupCfg( + terms=critic_terms, + concatenate_terms=True, + enable_corruption=False, + # history_length=5, + nan_policy="sanitize", + nan_check_per_term=True, + ), + } + + ## + # Metrics + ## + + metrics = { + "mean_action_acc": MetricsTermCfg(func=mdp.mean_action_acc), + } + + ## + # Actions + ## + + actions: dict[str, ActionTermCfg] = { + "joint_pos": JointPositionActionCfg( + entity_name="robot", + actuator_names=(".*",), + scale=VR_M3_12DOF_ACTION_SCALE, + use_default_offset=True, + ) + } + + ## + # Commands + ## + + commands: dict[str, CommandTermCfg] = { + "twist": UniformVelocityCommandCfg( + entity_name="robot", + resampling_time_range=(3.0, 8.0), + rel_standing_envs=0.05, + heading_command=False, + heading_control_stiffness=0.5, + debug_vis=True, + ranges=UniformVelocityCommandCfg.Ranges( + lin_vel_x=(-1.0, 2.0), + lin_vel_y=(-1.0, 1.0), + ang_vel_z=(-1.0, 1.0), + heading=None, + ), + ), + } + twist_cmd = commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.viz.z_offset = 1.15 + + ## + # Events + ## + + events = { + "reset_base": EventTermCfg( + func=mdp.reset_root_state_uniform, + mode="reset", + params={ + "pose_range": { + "x": (-0.5, 0.5), + "y": (-0.5, 0.5), + "z": (0.0, 0.0), + "yaw": (-3.14, 3.14), + }, + # "discrete_yaws": [0.0, math.pi / 2, math.pi, -math.pi / 2], # [0.0, math.pi / 2, math.pi, -math.pi / 2], + }, + ), + "reset_robot_joints": EventTermCfg( + func=mdp.reset_joints_by_offset, + mode="reset", + params={ + "position_range": (-0.1, 0.1), + "velocity_range": (-0.5, 0.5), + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + }, + ), + "push_robot": EventTermCfg( + func=mdp.push_by_setting_velocity, + mode="interval", + interval_range_s=(5.0, 6.0), + params={ + "velocity_range": { + "x": (-0.5, 0.5), + "y": (-0.5, 0.5), + "z": (-0.4, 0.4), + "roll": (-0.52, 0.52), + "pitch": (-0.52, 0.52), + "yaw": (-0.78, 0.78), + }, + }, + ), + "foot_friction": EventTermCfg( + mode="startup", + func=dr.geom_friction, + params={ + "asset_cfg": SceneEntityCfg("robot", geom_names=FOOT_GEOMS), + "operation": "abs", + "ranges": (0.3, 1.6), + "shared_random": True, + }, + ), + "encoder_bias": EventTermCfg( + mode="startup", + func=dr.encoder_bias, + params={ + "asset_cfg": SceneEntityCfg("robot"), + "bias_range": (-0.015, 0.015), + }, + ), + "base_com": EventTermCfg( + mode="startup", + func=dr.body_com_offset, + params={ + "asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,)), + "operation": "add", + "ranges": { + 0: (-0.05, 0.05), + 1: (-0.05, 0.05), + 2: (-0.05, 0.05), + }, + }, + ), + "body_com": EventTermCfg( + mode="startup", + func=dr.body_ipos, + params={ + "asset_cfg": SceneEntityCfg( + "robot", body_names=("^(?!waist_yaw_link$).*",) + ), + "operation": "add", + "ranges": { + 0: (-0.03, 0.03), + 1: (-0.03, 0.03), + 2: (-0.03, 0.03), + }, + }, + ), + "base_mass": EventTermCfg( + mode="startup", + func=dr.body_mass, + params={ + "asset_cfg": SceneEntityCfg("robot", body_names=("waist_yaw_link",)), + "operation": "add", + "ranges": (-4.0, 4.0), + }, + ), + "body_mass": EventTermCfg( + mode="startup", + func=dr.body_mass, + params={ + "asset_cfg": SceneEntityCfg( + "robot", body_names=("^(?!waist_yaw_link$).*",) + ), + "operation": "scale", + "ranges": (0.9, 1.1), + }, + ), + "randomize_actuator_gains": EventTermCfg( + func=dr.pd_gains, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "kp_range": (0.7, 1.1), + "kd_range": (0.7, 1.1), + }, + ), + "randomize_joint_limit": EventTermCfg( + mode="startup", + func=dr.joint_limits, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.94, 1.06), + }, + ), + "randomize_joint_stiffness": EventTermCfg( + mode="startup", + func=dr.joint_stiffness, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.7, 1.3), + }, + ), + "randomize_joint_frictionloss": EventTermCfg( + mode="startup", + func=dr.joint_friction, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.1, 1.3), + }, + ), + "randomize_joint_armature": EventTermCfg( + mode="startup", + func=dr.joint_armature, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.2, 5.0), + }, + ), + "randomize_joint_damping": EventTermCfg( + mode="startup", + func=dr.joint_damping, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.7, 1.3), + }, + ), + } + + ## + # Rewards + ## + + rewards = { + "track_linear_velocity": RewardTermCfg( + func=mdp.track_linear_velocity, + weight=2.0, + params={"command_name": "twist", "std": math.sqrt(0.25)}, + ), + "track_angular_velocity": RewardTermCfg( + func=mdp.track_angular_velocity, + weight=2.0, + params={"command_name": "twist", "std": math.sqrt(0.5)}, + ), + "body_orientation_l2": RewardTermCfg( + func=mdp.body_orientation_l2, + weight=-5.0, + params={"asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,))}, + ), + "pose": RewardTermCfg( + func=mdp.variable_posture, + weight=1.0, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), + "command_name": "twist", + "std_standing": POSE_STD_STANDING, + "std_walking": POSE_STD_WALKING, + "std_running": POSE_STD_RUNNING, + "walking_threshold": 0.1, + "running_threshold": 0.7, + }, + ), + "flat_orientation": RewardTermCfg(func=mdp.flat_orientation_l2, weight=-7.0), + "pelvis_orientation_l2": RewardTermCfg( + func=mdp.link_orientation, + weight=-3.0, + params={"asset_cfg": SceneEntityCfg("robot", body_names="pelvis")}, + ), + "joint_deviation_hip": RewardTermCfg( + func=mdp.joint_deviation_square, + weight=-0.1, + params={ + "asset_cfg": SceneEntityCfg( + "robot", + joint_names=(".*_hip_yaw_joint", ".*_hip_roll_joint"), + ) + }, + ), + "ang_vel_xy_l2": RewardTermCfg( + func=mdp.ang_vel_xy_l2, + weight=-0.05, + ), + "dof_torques_l2": RewardTermCfg( + func=mdp.joint_torques_l2, + weight=-1.0e-8, + params={ + "asset_cfg": SceneEntityCfg( + "robot", + joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + ) + }, + ), + "dof_vel_l2": RewardTermCfg( + func=mdp.joint_vel_l2, + weight=-1.0e-8, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + "feet_flat_ori": RewardTermCfg( + func=mdp.feet_orientation_contact, + weight=-0.01, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + }, + ), + "body_ang_vel": RewardTermCfg( + func=mdp.body_angular_velocity_penalty, + weight=-0.05, + params={"asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,))}, + ), + "angular_momentum": RewardTermCfg( + func=mdp.angular_momentum_penalty, + weight=-0.025, + params={"sensor_name": "robot/root_angmom"}, + ), + "is_terminated": RewardTermCfg(func=mdp.is_terminated, weight=-200.0), + "joint_acc_l2": RewardTermCfg(func=mdp.joint_acc_l2, weight=-2.5e-7), + "joint_pos_limits": RewardTermCfg(func=mdp.joint_pos_limits, weight=-5.0), + "action_rate_l2": RewardTermCfg(func=mdp.action_rate_l2, weight=-0.5), + "foot_gait": RewardTermCfg( + func=mdp.feet_gait, + weight=1.0, + params={ + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "threshold": 0.6, + "command_threshold": 0.1, + "command_name": "twist", + "sensor_name": "feet_ground_contact", + }, + ), + "feet_double_support": RewardTermCfg( + func=mdp.feet_double_support, + weight=2.0, + params={ + "sensor_name": "feet_ground_contact", + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "threshold": 0.6, + "command_name": "twist", + "cmd_threshold": 0.1, + "ds_match_weight": 1.0, + }, + ), + "foot_clearance": RewardTermCfg( + func=mdp.feet_clearance, + weight=-1.0, + params={ + "target_height": 0.10, + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES), + }, + ), + "foot_slip": RewardTermCfg( + func=mdp.feet_slip, + weight=-0.25, + params={ + "sensor_name": "feet_ground_contact", + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES), + }, + ), + "feet_close_xy": RewardTermCfg( + func=mdp.feet_close_xy_gauss, + weight=1.0, + params={ + "threshold": 0.2, + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "std": math.sqrt(0.05), + }, + ), + "soft_landing": RewardTermCfg( + func=mdp.soft_landing, + weight=-1e-3, + params={ + "sensor_name": "feet_ground_contact", + "command_name": "twist", + "command_threshold": 0.1, + }, + ), + "dont_wait": RewardTermCfg( + func=mdp.dont_wait, + weight=-0.5, + params={ + "command_name": "twist", + "cmd_threshold": 0.1, + }, + ), + "stand_still": RewardTermCfg( + func=mdp.stand_still, + weight=-1.0, + params={ + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), + }, + ), + "self_collisions": RewardTermCfg( + func=mdp.self_collision_cost, + weight=-1.0, + params={"sensor_name": self_collision_cfg.name, "force_threshold": 10.0}, + ), + "feet_air_time": RewardTermCfg( + func=mdp.feet_air_time, + weight=1.0, + params={ + "sensor_name": "feet_ground_contact", + "threshold": (1.0 - 0.6) * GAIT_CYCLE_PERIOD, # 0.48 s + "command_name": "twist", + "command_threshold": 0.1, + }, + ), + "feet_air_time_biped": RewardTermCfg( + func=mdp.feet_air_time_positive_biped, + weight=1.5, + params={ + "command_name": "twist", + "sensor_name": "feet_ground_contact", + "threshold": 0.52, + }, + ), + } + + ## + # Terminations + ## + + terminations = { + "time_out": TerminationTermCfg(func=mdp.time_out, time_out=True), + "fell_over": TerminationTermCfg( + func=mdp.bad_orientation, + params={"limit_angle": math.radians(70.0)}, + ), + "nan_term": TerminationTermCfg( + func=mdp.nan_detection, + time_out=False, + ), + } + + ## + # Curriculum + ## + + curriculum = { + "terrain_levels": CurriculumTermCfg( + func=mdp.terrain_levels_vel, + params={"command_name": "twist"}, + ), + "command_vel": CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (-0.5, 1.0), + "lin_vel_y": (-0.5, 0.5), + "ang_vel_z": (-0.5, 0.5), + }, + { + "step": 5000 * 24, + "lin_vel_x": (-0.7, 1.5), + "lin_vel_y": (-0.7, 0.7), + "ang_vel_z": (-0.7, 0.7), + }, + { + "step": 7000 * 24, + "lin_vel_x": (-1.0, 2.0), + "lin_vel_y": (-1.0, 1.0), + "ang_vel_z": (-1.0, 1.0), + }, + # { + # "step": 9000 * 24, + # "lin_vel_x": (-1.0, 3.0), + # "lin_vel_y": (-1.0, 1.0), + # "ang_vel_z": (-1.0, 1.0), + # }, + ], + }, + ), + } + + ## + # Scene + terrain + ## + + terrain_generator = replace(ROUGH_TERRAINS_CFG) + terrain_generator.curriculum = True + terrain = TerrainEntityCfg( + terrain_type="generator", + terrain_generator=terrain_generator, + max_init_terrain_level=5, + ) + + scene = SceneCfg( + terrain=terrain, + entities={"robot": get_vr_m3_12dof_implicit_actuator_robot_cfg()}, + sensors=(feet_ground_cfg, self_collision_cfg), + num_envs=1, + extent=2.0, + ) + + ## + # Assemble + ## + + cfg = VelocityEnvCfg( + scene=scene, + observations=observations, + actions=actions, + commands=commands, + events=events, + rewards=rewards, + terminations=terminations, + curriculum=curriculum, + metrics=metrics, + viewer=ViewerConfig( + origin_type=ViewerConfig.OriginType.ASSET_BODY, + entity_name="robot", + body_name=TORSO_BODY, + distance=3.0, + elevation=-5.0, + azimuth=90.0, + ), + sim=SimulationCfg( + # VR-M3 has ~1.4x the foot collision geoms of G1 (10/side vs 7/side); + # rough terrain randomization can push the contact count up, so + # nconmax is raised from G1's 48 to 512. + nconmax=512, + njmax=1500, + contact_sensor_maxmatch=500, + mujoco=MujocoCfg( + timestep=0.005, + iterations=10, + ls_iterations=20, + ccd_iterations=500, + ), + ), + decimation=4, + episode_length_s=20.0, + ) + + # Play mode overrides. + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["actor"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + return cfg + + +def vr_m3_12dof_flat_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF flat terrain velocity configuration.""" + cfg = vr_m3_12dof_rough_env_cfg(play=play) + cfg.rewards.pop("flat_orientation", None) + cfg.rewards.pop("pelvis_orientation_l2", None) + cfg.rewards.pop("joint_deviation_hip", None) + cfg.rewards.pop("ang_vel_xy_l2", None) + cfg.rewards.pop("dof_torques_l2", None) + cfg.rewards.pop("dof_vel_l2", None) + cfg.rewards.pop("feet_flat_ori", None) + # VR-M3 has ~1.4x the foot collision geoms of G1, so njmax needs headroom. + cfg.sim.njmax = 600 + cfg.sim.mujoco.ccd_iterations = 50 + cfg.sim.contact_sensor_maxmatch = 64 + cfg.sim.nconmax = None + + # Switch to flat terrain. + assert cfg.scene.terrain is not None + cfg.scene.terrain.terrain_type = "plane" + cfg.scene.terrain.terrain_generator = None + + # Remove raycast sensor and height scan (no terrain to scan). + cfg.scene.sensors = tuple( + s for s in (cfg.scene.sensors or ()) if s.name != "terrain_scan" + ) + # del cfg.observations["actor"].terms["height_scan"] + # del cfg.observations["critic"].terms["height_scan"] + cfg.observations["actor"].terms.pop("height_scan", None) + cfg.observations["critic"].terms.pop("height_scan", None) + + cfg.curriculum.pop("terrain_levels", None) + + if play: + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (-0.5, 2.0) + twist_cmd.ranges.lin_vel_y = (-0.5, 0.5) + twist_cmd.ranges.ang_vel_z = (-0.5, 0.5) + + return cfg + + +def vr_m3_12dof_perceptive_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF perceptive locomotion configuration with height-map.""" + cfg = vr_m3_12dof_rough_env_cfg(play=play) + + site_names = ("left_foot", "right_foot") + + # Auto-size contact buffers for complex terrain geometry. + cfg.sim.njmax = 700 + cfg.sim.mujoco.ccd_iterations = 500 + cfg.sim.contact_sensor_maxmatch = 500 + cfg.sim.nconmax = 128 + + # Swap terrain generator to perceptive preset (deepcopy to avoid mutation). + assert cfg.scene.terrain is not None + cfg.scene.terrain.terrain_generator = deepcopy(PERCEPTIVE_TERRAINS_CFG) + + if not play: + cfg.scene.terrain.terrain_generator.curriculum = True + + pelvis_height_measure = RayCastSensorCfg( + name="pelvis_height_measure", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=2.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + left_height_scanner = RayCastSensorCfg( + name="left_height_scanner", + frame=ObjRef(type="site", name="left_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=1.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + right_height_scanner = RayCastSensorCfg( + name="right_height_scanner", + frame=ObjRef(type="site", name="right_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=1.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + + # --- Gradient sensors (3x3 grid for foot edge detection) --- + left_foot_gradient = RayCastSensorCfg( + name="left_foot_gradient", + frame=ObjRef(type="site", name="left_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.2, 0.1), + resolution=0.1, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=1.0, + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + right_foot_gradient = RayCastSensorCfg( + name="right_foot_gradient", + frame=ObjRef(type="site", name="right_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.2, 0.1), + resolution=0.1, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=1.0, + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + pelvis_height_measure, + left_height_scanner, + right_height_scanner, + left_foot_gradient, + right_foot_gradient, + ) + + # --- Terrain-aware reward terms --- + cfg.rewards["terrain_foot_clearance"] = RewardTermCfg( + func=mdp.terrain_foot_clearance_cost, + weight=-0.5, + params={ + "target_clearance": 0.06, + "left_terrain_sensor": "left_height_scanner", + "right_terrain_sensor": "right_height_scanner", + "command_name": "twist", + "command_threshold": 0.05, + "asset_cfg": SceneEntityCfg("robot", site_names=site_names), + }, + ) + + cfg.rewards["terrain_stumble"] = RewardTermCfg( + func=mdp.terrain_stumble_cost, + weight=-1.0, + params={ + "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "velocity_threshold": 0.15, + }, + ) + + # cfg.rewards["step_accuracy"] = RewardTermCfg( + # func=custom_mdp.step_accuracy, + # weight=1.0, + # params={ + # "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "patch_name": "target", + # "std": 0.15, + # }, + # ) + + cfg.rewards["terrain_base_height"] = RewardTermCfg( + func=mdp.terrain_base_height_l2_cost, + weight=-1.0, + params={ + "target_height": 0.9, + "base_terrain_sensor": "pelvis_height_measure", + "asset_cfg": SceneEntityCfg("robot"), + }, + ) + + cfg.rewards["foot_edge"] = RewardTermCfg( + func=mdp.foot_edge_cost, + weight=-0.5, + params={ + "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + "left_gradient_sensor": "left_foot_gradient", + "right_gradient_sensor": "right_foot_gradient", + "gradient_threshold": 0.3, + "asset_cfg": SceneEntityCfg("robot", body_names=[r".*ankle_roll.*"]), + }, + ) + + # cfg.rewards["feet_at_plane"] = RewardTermCfg( + # func=parkour_mdp.feet_at_plane, + # weight=-0.1, + # params={ + # "contact_sensor_name": "feet_ground_contact", + # "left_height_scanner_name": "left_height_scanner", # matches your sensor + # "right_height_scanner_name": "right_height_scanner", # matches your sensor + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "height_offset": 0.06, + # }, + # ) + + # --- Terrain-aware termination --- + cfg.terminations["base_height"] = TerminationTermCfg( + func=mdp.root_height_below_minimum_terrain, + params={ + "minimum_height": 0.3, + "terrain_sensor_name": "pelvis_height_measure", + }, + ) + + if play: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + return cfg + + +def vr_m3_12dof_height_map_env_cfg(play: bool = False) -> VelocityEnvCfg: + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(0.6, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + cfg.scene.sensors = cfg.scene.sensors + (terrain_scan,) + + # --- Asymmetric actor-critic observations --- + # Actor: add terrain_scan with noise (proprioception terms inherited from base). + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + # func=custom_mdp.height_scan_custom, + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + noise=Unoise(n_min=-0.1, n_max=0.1), + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic: add terrain_scan (no noise, privileged) and true base velocity. + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + # func=custom_mdp.height_scan_custom, + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + history_length=5, + ) + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 2.5 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -5e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 1.0 + cfg.rewards["feet_double_support"].weight = 2.0 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -0.5 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 1.5 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards["foot_edge"].weight = -0.5 + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["actor"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_depth_map_env_cfg( + play: bool = False, +) -> VelocityEnvCfg: + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(1.8, 1.2), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + depth_camera = NoisyGroupedRayCasterCameraCfg( + name="camera", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + # RealSense depth camera D435 + # Intrinsics from camera_info: fx = fy = 386.56719970703125 at 640x480 + pattern=PinholeCameraPatternCfg( + height=int(480 / 8), + width=int(640 / 8), + fovy=2 + * math.degrees(math.atan(480 / 2 / 386.56719970703125)), # ~63.67 deg + ), + focal_length=1.0, + horizontal_aperture=640.0 / 386.56719970703125, # fovx ~79.24 deg + vertical_aperture=480.0 / 386.56719970703125, # fovy ~63.67 deg + ray_alignment="base", + include_geom_groups=(0, 1, 2), + exclude_parent_body=False, + offset=NoisyGroupedRayCasterCameraCfg.OffsetCfg( + pos=(0.00, 0.018, -0.1), + rot=( + math.cos(math.radians(60) / 2), # w + 0.0, # x + math.sin(math.radians(60) / 2), # y (pitch 60 deg about Y) + 0.0, # z + ), + convention="world", + ), + data_types=["distance_to_image_plane"], + depth_clipping_behavior="max", # clip to the maximum value + mesh_filter_max_hops=24, + noise_pipeline={ + "crop_and_resize": CropAndResizeCfg( + # (top, bottom, left, right), height/2 and centering width/2 + crop_region=(0, 0, 10, 10), + resize_shape=(30, 30), + ), + "gaussian_blur": GaussianBlurNoiseCfg(kernel_size=3, sigma=1), + "depth_normalization": DepthNormalizationCfg( + depth_range=(0.0, 2.5), + normalize=True, + output_range=(0.0, 1.0), + ), + }, + data_histories={"distance_to_image_plane_noised": 17}, + update_period=1 / 30, + min_distance=0.1, + max_distance=2.5, + debug_vis=play, + ) + undesired_contact_cfg = ContactSensorCfg( + name="undesired_contact_forces", + primary=ContactMatch( + mode="body", + pattern=".*", + entity="robot", + exclude=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + fields=("found", "force"), + reduce="netforce", + track_air_time=False, + history_length=3, + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + terrain_scan, + depth_camera, + undesired_contact_cfg, + ) + + cfg.events["randomize_ray_offsets"] = EventTermCfg( + func=instinct_mdp.randomize_ray_offsets, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("camera"), + "offset_pose_ranges": { + "x": (-0.01, 0.01), + "y": (-0.01, 0.01), + "z": (-0.03, 0.01), + "roll": (-math.radians(2), math.radians(2)), + "pitch": (-math.radians(10), math.radians(10)), + "yaw": (-math.radians(2), math.radians(2)), + }, + "distribution": "uniform", + }, + ) + + cfg.observations["actor"].concatenate_terms = False + cfg.observations["critic"].concatenate_terms = False + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + ) + + cfg.observations["actor"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + cfg.observations["critic"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + # Add "policy" alias for actor obs (Instinct runner expects "policy"). + actor_obs_cfg = cfg.observations.pop("actor") + cfg.observations["policy"] = actor_obs_cfg + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 2.0 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards["foot_edge"].weight = -0.5 + + cfg.rewards = { + **cfg.rewards, + "feet_slide": RewardTermCfg( + func=instinct_parkour_mdp.feet_slide, + weight=-0.4, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "threshold": 1.0, + }, + ), + # "joint_deviation_hip": RewardTermCfg( + # func=instinct_mdp.joint_deviation_square, + # weight=-0.3, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_yaw_joint", ".*_hip_roll_joint"), + # ) + # }, + # ), + # "ang_vel_xy_l2": RewardTermCfg( + # func=instinct_parkour_mdp.ang_vel_xy_l2, + # weight=-0.05, + # ), + # "dof_torques_l2": RewardTermCfg( + # func=instinct_parkour_mdp.joint_torques_l2, + # weight=-1.0e-7, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ) + # }, + # ), + # "dof_vel_l2": RewardTermCfg( + # func=envs_mdp.joint_vel_l2, + # weight=-5.0e-7, + # params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + # ), + # "feet_flat_ori": RewardTermCfg( + # func=instinct_parkour_mdp.feet_orientation_contact, + # weight=-0.01, + # params={ + # "sensor_name": "feet_ground_contact", + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # }, + # ), + # "feet_close_xy": RewardTermCfg( + # func=instinct_parkour_mdp.feet_close_xy_gauss, + # weight=1.0, + # params={ + # "threshold": 0.2, + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "std": math.sqrt(0.05), + # }, + # ), + # "energy": RewardTermCfg( + # func=parkour_mdp.rewards.motors_power_square, + # weight=-1.0e-8, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ), + # "normalize_by_stiffness": True, + # }, + # ), + "dof_pos_limits": RewardTermCfg( + func=envs_mdp.joint_pos_limits, + weight=-1.0, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + # "flat_orientation": RewardTermCfg(func=mdp.flat_orientation_l2, weight=-7.0), + # "pelvis_orientation_l2": RewardTermCfg( + # func=instinct_parkour_mdp.link_orientation, + # weight=-3.0, + # params={"asset_cfg": SceneEntityCfg("robot", body_names="pelvis")}, + # ), + } + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["policy"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_foothold_env_cfg(play: bool = False) -> VelocityEnvCfg: + """FastStair Stage 1 — planner-guided pre-training (paper §III-B.3). + + Extends ``vr_m3_12dof_height_map_env_cfg`` with: + + - A 1.8 × 1.2 m elevation map at 5 cm resolution (paper §III-C). + - The DCM-based foothold planner exposed as a ``FootholdCommand``. + - The exponential foothold-tracking reward with weight 0.6 (Table I §III-B.2). + - A privileged ``foothold_target`` observation on the critic. + - Velocity range restricted to the paper's pre-train regime + ``[-0.3, 1.0]`` m/s in x. + - Stage 1 reward weights from Table I. + """ + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(1.8, 1.2), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0,), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + depth_camera = NoisyGroupedRayCasterCameraCfg( + name="camera", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + # RealSense depth camera D435 + # Intrinsics from camera_info: fx = fy = 386.56719970703125 at 640x480 + pattern=PinholeCameraPatternCfg( + height=int(480 / 8), + width=int(640 / 8), + fovy=2 + * math.degrees(math.atan(480 / 2 / 386.56719970703125)), # ~63.67 deg + ), + focal_length=1.0, + horizontal_aperture=640.0 / 386.56719970703125, # fovx ~79.24 deg + vertical_aperture=480.0 / 386.56719970703125, # fovy ~63.67 deg + ray_alignment="base", + include_geom_groups=(0, 1, 2), + exclude_parent_body=False, + # TODO: double check with Offset from URDF + offset=NoisyGroupedRayCasterCameraCfg.OffsetCfg( + pos=(0.00, 0.018, -0.1), + rot=( + math.cos(math.radians(60) / 2), # w + 0.0, # x + math.sin(math.radians(60) / 2), # y (pitch 30 deg about Y) + 0.0, # z + ), + convention="world", + ), + data_types=["distance_to_image_plane"], + depth_clipping_behavior="max", # clip to the maximum value + mesh_filter_max_hops=24, + noise_pipeline={ + "crop_and_resize": CropAndResizeCfg( + # (top, bottom, left, right), height/2 and centering width/2 + crop_region=(0, 0, 10, 10), + resize_shape=(30, 30), + ), + "gaussian_blur": GaussianBlurNoiseCfg(kernel_size=3, sigma=1), + "depth_normalization": DepthNormalizationCfg( + depth_range=(0.0, 2.5), + normalize=True, + output_range=(0.0, 1.0), + ), + }, + data_histories={"distance_to_image_plane_noised": 17}, + update_period=1 / 30, + min_distance=0.1, + max_distance=2.5, + debug_vis=play, + ) + undesired_contact_cfg = ContactSensorCfg( + name="undesired_contact_forces", + primary=ContactMatch( + mode="body", + pattern=".*", + entity="robot", + exclude=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + fields=("found", "force"), + reduce="netforce", + track_air_time=False, + history_length=3, + ) + + cfg.scene.sensors = tuple( + s + for s in (cfg.scene.sensors or ()) + if s.name not in ("left_foot_gradient", "right_foot_gradient") + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + terrain_scan, + depth_camera, + undesired_contact_cfg, + ) + + cfg.events["randomize_ray_offsets"] = EventTermCfg( + func=instinct_mdp.randomize_ray_offsets, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("camera"), + "offset_pose_ranges": { + "x": (-0.01, 0.01), + "y": (-0.01, 0.01), + "z": (-0.03, 0.01), + "roll": (-math.radians(2), math.radians(2)), + "pitch": (-math.radians(10), math.radians(10)), + "yaw": (-math.radians(2), math.radians(2)), + }, + "distribution": "uniform", + }, + ) + + # Foothold command — the planner output. + cfg.commands["foothold"] = mdp.FootholdCommandCfg( + entity_name="robot", + terrain_sensor_name="terrain_scan", + contact_sensor_name="feet_ground_contact", + velocity_command_name="twist", + foot_site_names=FOOT_SITES, + gait_period=GAIT_CYCLE_PERIOD, + nominal_height_m=0.9, + lateral_inter_foot_m=0.22, + foot_footprint_m=(0.25, 0.10), + search_window_m=(0.6, 0.6), + elevation_size_m=(1.8, 1.2), + elevation_resolution_m=0.05, + alpha_pos=1.0, + alpha_dcm=0.5, + # Safety-aware terrain scoring (max-pool steepness + footprint + # flatness + soft height feasibility + climb bonus). See + # ``DCMFootholdPlanner`` docstring for the rationale. + alpha_steepness=0.6, + alpha_flatness=4.0, + alpha_height=6.0, + alpha_climb_bonus=1.5, + lateral_pos_weight=2.5, + max_step_height_m=0.25, + climb_velocity_threshold=0.1, + standing_threshold=0.1, + # Adaptive Bézier clearance: 5 cm base on flat ground, +0.5 m/m of + # step height, capped at 20 cm. + apex_clearance_m=0.05, + clearance_scale=0.5, + max_clearance_m=0.20, + pre_apex_lower_window=0.05, + pre_apex_upper_window=0.05, + post_apex_lower_window=0.1, + post_apex_upper_window=0.15, + terrain_decision_threshold=0.1, + debug_vis=play, + ) + + cfg.observations["actor"].concatenate_terms = False + cfg.observations["critic"].concatenate_terms = False + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + ) + + # Privileged critic observation: planner output (body frame). + cfg.observations["critic"].terms["foothold_target"] = ObservationTermCfg( + func=mdp.foothold_target, + params={"command_name": "foothold"}, + ) + + cfg.observations["actor"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + cfg.observations["critic"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + # add "policy" alias for actor obs for instinct compatibility + actor_obs_cfg = cfg.observations.pop("actor") + cfg.observations["policy"] = actor_obs_cfg + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # Pre-train velocity range (paper §III-B.3). + # twist_cmd = cfg.commands["twist"] + # assert isinstance(twist_cmd, UniformVelocityCommandCfg) + # twist_cmd.ranges = UniformVelocityCommandCfg.Ranges( + # lin_vel_x=(-0.3, 1.0), + # lin_vel_y=(-0.3, 0.3), + # ang_vel_z=(-1.0, 1.0), + # heading=None, + # ) + # twist_cmd.resampling_time_range = (8.0, 12.0) + # cfg.curriculum.pop("command_vel", None) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 2.0 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + # cfg.rewards["foot_edge"].weight = -0.5 + cfg.rewards.pop("foot_edge", None) + + cfg.rewards = { + **cfg.rewards, + "feet_slide": RewardTermCfg( + func=instinct_parkour_mdp.feet_slide, + weight=-0.4, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "threshold": 1.0, + }, + ), + # "energy": RewardTermCfg( + # func=parkour_mdp.rewards.motors_power_square, + # weight=-1.0e-8, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ), + # "normalize_by_stiffness": True, + # }, + # ), + "dof_pos_limits": RewardTermCfg( + func=envs_mdp.joint_pos_limits, + weight=-1.0, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + } + + cfg.rewards["foothold_tracking"] = RewardTermCfg( + func=mdp.foothold_tracking, + weight=2.1, + params={ + "command_name": "foothold", + "sigma_stages": [(10.0, 5.0), (20.0, 10.0), (30.0, 15.0)], + "stage_step_counts": [0, 4_000 * 24, 8_000 * 24], + "asset_cfg": SceneEntityCfg( + "robot", + site_names=FOOT_SITES, + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "sensor_name": "feet_ground_contact", + "velocity_command_name": "twist", + "velocity_command_threshold": 0.1, + # "log_csv_path": "foothold_tracking_rewards.csv" if play else None, + }, + ) + # cfg.rewards["track_linear_velocity"].weight = 1.0 + # if "action_rate_l2" in cfg.rewards: + # cfg.rewards["action_rate_l2"].weight = -2.5e-3 + # if "joint_acc_l2" in cfg.rewards: + # cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + # if "dof_torques_l2" in cfg.rewards: + # cfg.rewards["dof_torques_l2"].weight = -4.0e-7 + # if "dof_vel_l2" in cfg.rewards: + # cfg.rewards["dof_vel_l2"].weight = -2.5e-7 + # if "foot_edge" in cfg.rewards: + # cfg.rewards["foot_edge"].weight = -1.5 + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["policy"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_ga_phl_env_cfg(play: bool = False) -> VelocityEnvCfg: + """GA-PHL perceptive locomotion config for VR-M3 12DOF. + + Implements arXiv:2512.07464 (Gait-Adaptive Perceptive Humanoid Locomotion + with Real-Time Under-Base Terrain Reconstruction): + + - Downward-facing under-base depth camera (§III-E): replaces the 60° forward + camera with a 90° downward camera, covering the critical foot-support region. + - Omnidirectional velocity commands with a 3-stage curriculum (§IV-B). + - Reward weights matched to paper Table I as closely as possible using the + existing reward functions in this codebase. + + Based on ``vr_m3_12dof_foothold_env_cfg`` (inherits foothold planner, terrain + scan, depth image obs, and domain randomisation). Not implemented here because + they require framework-level extensions: + - U-Net height-map reconstruction (separate offline model). + - Successive Teacher-Student runner (runner-level, not env-level). + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_map_as_grid, + params={ + "sensor_name": "terrain_scan", + "miss_value": 2.0, + "use_grid": True, + "num_cols": int((1.8 + 1e-6) / 0.05) + 1, + "num_rows": int((1.2 + 1e-6) / 0.05) + 1, + }, + clip=(0.0, 2.0), + history_length=1, + flatten_history_dim=False, + ) + + cfg.observations["critic"].terms.pop("depth_image") + + cfg.commands["foothold"] = mdp.FootholdCommandCfg( + entity_name="robot", + terrain_sensor_name="terrain_scan", + contact_sensor_name="feet_ground_contact", + velocity_command_name="twist", + foot_site_names=FOOT_SITES, + gait_period="policy", + gait_action_name="gait_freq", + nominal_height_m=0.9, + lateral_inter_foot_m=0.18, + foot_footprint_m=(0.20, 0.10), + search_window_m=(0.6, 0.6), + elevation_size_m=(1.8, 1.2), + elevation_resolution_m=0.05, + alpha_pos=1.0, + alpha_dcm=0.5, + # Safety-aware terrain scoring (max-pool steepness + footprint + # flatness + soft height feasibility + climb bonus). See + # ``DCMFootholdPlanner`` docstring for the rationale. + alpha_steepness=0.6, + alpha_flatness=4.0, + alpha_height=6.0, + alpha_climb_bonus=1.5, + lateral_pos_weight=2.5, + max_step_height_m=0.25, + climb_velocity_threshold=0.1, + standing_threshold=0.1, + # Adaptive Bézier clearance: 5 cm base on flat ground, +0.5 m/m of + # step height, capped at 20 cm. + apex_clearance_m=0.05, + clearance_scale=0.5, + max_clearance_m=0.20, + pre_apex_lower_window=0.05, + pre_apex_upper_window=0.05, + post_apex_lower_window=0.1, + post_apex_upper_window=0.15, + terrain_decision_threshold=0.1, + debug_vis=play, + ) + + cfg.rewards["foothold_tracking"] = RewardTermCfg( + func=mdp.foothold_tracking, + weight=2.0, + params={ + "command_name": "foothold", + "sigma_stages": [(10.0, 5.0), (20.0, 10.0), (30.0, 15.0)], + "stage_step_counts": [0, 4_000 * 24, 8_000 * 24], + "asset_cfg": SceneEntityCfg( + "robot", + site_names=FOOT_SITES, + body_names=FOOT_LINK_NAMES, + ), + "sensor_name": "feet_ground_contact", + "velocity_command_name": "twist", + "velocity_command_threshold": 0.1, + "penalty_scale": 1.0, + # "log_csv_path": "foothold_tracking_rewards.csv" if play else None, + }, + ) + + # Route foot_gait and feet_double_support to the learnable phase φ_t so + # the gait reward is consistent with the policy's own internal clock. + cfg.observations["critic"].terms["knee_reference"].params[ + "action_name" + ] = "gait_freq" + cfg.rewards["foot_gait"].params["action_name"] = "gait_freq" + cfg.rewards["feet_double_support"].params["action_name"] = "gait_freq" + cfg.rewards["feet_air_time"].params["action_name"] = "gait_freq" + + cfg.actions["gait_freq"] = mdp.GaitFrequencyActionCfg( + entity_name="robot", + min_frequency=1.0, + max_frequency=1.5, + smooth_alpha=0.2, + default_frequency=1.2, + ) + + # ── 6. Adaptive gait-phase observation (replaces fixed-period phase obs) ── + # Returns [f_t, sin(2π·φ_t), cos(2π·φ_t)] — 3 scalars instead of 2. + # Both policy and critic groups inherit the same proprioceptive terms. + for group_name in ("policy", "critic"): + cfg.observations[group_name].terms.pop("gait_phase", None) + cfg.observations[group_name].terms["adaptive_gait_phase"] = ObservationTermCfg( + func=mdp.adaptive_gait_phase, + params={"action_name": "gait_freq", "command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ) + + # ── 7. Gait action limit penalty ───────────────────────────────────────── + # Small penalty for pushing f_t outside the valid band (paper §III-C). + cfg.rewards["gait_action_limit"] = RewardTermCfg( + func=mdp.gait_action_limit, + weight=-0.25, + params={"action_name": "gait_freq"}, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 4_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for training --- + # cfg.rewards["step_accuracy"].weight = 1.0 + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # NOT work with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-7 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -2.0 + cfg.rewards["self_collisions"].weight = -2.0 + # cfg.rewards["feet_air_time"].weight = 1.0 + # cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["feet_air_time_biped"].weight = 3.0 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards.pop( + "terrain_foot_clearance", None + ) # Not compatible with heightmap-based foothold planning + cfg.rewards.pop("foot_gait", None) # phase-locked, conflicts with foothold planner + cfg.rewards.pop("feet_double_support", None) # same problem + cfg.rewards.pop( + "feet_air_time", None + ) # Remove air time reward which can conflict with foothold planning + + # Experiment with new foothold penalties + cfg.rewards.pop("foot_edge", None) + cfg.rewards["terrain_stumble"].weight = -1.0 + + return cfg + + +def _create_multi_critic_cfg_from_single_critic( + cfg: VelocityEnvCfg, +) -> MultiCriticManagerBasedRlEnvCfg: + """Helper to copy a single-critic config to multi-critic format.""" + new_cfg = MultiCriticManagerBasedRlEnvCfg( + decimation=cfg.decimation, scene=cfg.scene + ) + new_cfg.observations = deepcopy(cfg.observations) + new_cfg.actions = deepcopy(cfg.actions) + new_cfg.events = deepcopy(cfg.events) + new_cfg.sim = deepcopy(cfg.sim) + new_cfg.viewer = deepcopy(cfg.viewer) + new_cfg.episode_length_s = cfg.episode_length_s + new_cfg.rewards = deepcopy(cfg.rewards) + new_cfg.terminations = deepcopy(cfg.terminations) + new_cfg.commands = deepcopy(cfg.commands) + new_cfg.curriculum = deepcopy(cfg.curriculum) + new_cfg.metrics = deepcopy(cfg.metrics) + new_cfg.is_finite_horizon = cfg.is_finite_horizon + new_cfg.scale_rewards_by_dt = cfg.scale_rewards_by_dt + + return new_cfg + + +def _create_critic_terrain_type_mapping( + cfg: MultiCriticManagerBasedRlEnvCfg, + terrain_type_list: list[str] = ["stair", "gap", "rough"], +): + # Use [stair, gap, rough] or [stair_up, stair_down, gap, rough] as the terrain + # types depending on the sub_terrains defined in the terrain generator config. + # In MJLab curriculum mode, each column is deterministically assigned to one + # sub-terrain by `_generate_curriculum_terrains`: + # sub_index = min(where(col / num_cols + 0.001 < cumsum(proportions))) + # `terrain.terrain_types` stores that column index per env, so to bucket envs + # by terrain category we map column_index -> sub_terrain class -> category. + + if terrain_type_list == ["stair", "gap", "rough"]: + terrain_type_mapping: dict[int, list[int]] = { + 0: [], # stair (both up and down) + 1: [], # gap + 2: [], # rough + } + elif terrain_type_list == ["stair_up", "stair_down", "gap", "rough"]: + terrain_type_mapping: dict[int, list[int]] = { + 0: [], # stair_up + 1: [], # stair_down + 2: [], # gap + 3: [], # rough + } + else: + raise ValueError( + "Unsupported terrain_type_list: {}. Only [stair, gap, rough] or " + "[stair_up, stair_down, gap, rough] are supported.".format( + terrain_type_list + ) + ) + + terrain_generator_cfg = cfg.scene.terrain.terrain_generator + if not terrain_generator_cfg.curriculum: + cfg.scene.terrain.terrain_generator.curriculum = True + + sub_terrains: dict[str, SubTerrainCfg] = terrain_generator_cfg.sub_terrains + sub_terrain_cfgs = list(sub_terrains.values()) + proportions = np.array([s.proportion for s in sub_terrain_cfgs], dtype=np.float64) + proportions /= proportions.sum() + cum_proportions = np.cumsum(proportions) + + num_cols = terrain_generator_cfg.num_cols + for col_idx in range(num_cols): + sub_index = int( + np.min(np.where(col_idx / num_cols + 0.001 < cum_proportions)[0]) + ) + class_name = sub_terrain_cfgs[sub_index].__class__.__name__ + if terrain_type_list == ["stair", "gap", "rough"]: + if "Stair" in class_name or "stair" in class_name: + terrain_type_mapping[0].append(col_idx) + elif "Gap" in class_name or "gap" in class_name: + terrain_type_mapping[1].append(col_idx) + else: + terrain_type_mapping[2].append(col_idx) + elif terrain_type_list == ["stair_up", "stair_down", "gap", "rough"]: + if "Stair" in class_name or "stair" in class_name: + if "BoxOpenStairsTerrainCfg" in class_name: + if sub_terrain_cfgs[sub_index].inverted == False: + terrain_type_mapping[0].append(col_idx) # stair_up + else: + terrain_type_mapping[1].append(col_idx) # stair_down + elif "BoxPyramidStairsTerrainCfg" in class_name: + terrain_type_mapping[0].append(col_idx) # stair_up + elif "BoxInvertedPyramidStairsTerrainCfg" in class_name: + terrain_type_mapping[1].append(col_idx) # stair_down + else: + raise ValueError( + "Unsupported stair type in class_name: {}. Only " + "BoxOpenStairsTerrainCfg, BoxPyramidStairsTerrainCfg, and " + "BoxInvertedPyramidStairsTerrainCfg are supported.".format( + class_name + ) + ) + elif class_name == "BoxSteppingStonesTerrainCfg": + terrain_type_mapping[2].append(col_idx) + else: + terrain_type_mapping[3].append(col_idx) + + # Drop empty buckets and re-index keys to be contiguous 0..N-1, so + # critic_labels emitted by the env line up exactly with critic head indices + # (otherwise the model has to clamp OOB labels, silently mis-routing envs). + non_empty = [v for v in terrain_type_mapping.values() if len(v) > 0] + cfg.critic_terrain_type_mapping = {i: v for i, v in enumerate(non_empty)} + if len(cfg.critic_terrain_type_mapping) == 0: + raise ValueError("No valid terrain types found in sub_terrains.") + if len(cfg.critic_terrain_type_mapping) < 2: + raise ValueError( + "At least 2 terrain types are required for multi-critic training." + ) + cfg.num_critics = len(cfg.critic_terrain_type_mapping) + + +def vr_m3_12dof_foothold_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_foothold_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + return cfg + + +def vr_m3_12dof_foothold_sts_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_foothold_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + cfg.observations["teacher_actor"] = deepcopy(cfg.observations["critic"]) + return cfg + + +def vr_m3_12dof_ga_phl_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_ga_phl_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + return cfg + + +def vr_m3_12dof_ga_phl_sts_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_ga_phl_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + cfg.observations["teacher_actor"] = deepcopy(cfg.observations["critic"]) + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 1 — Asymmetric actor-critic sensors + Band-specific DR +# --------------------------------------------------------------------------- + +# Actor sensor: foreground scan (heightmap_site is 0.5 m ahead of pelvis in the +# pelvis body frame, so the grid covers 0–1 m forward and ±0.3 m lateral). +# GridPatternCfg(size=(0.6, 1.0), resolution=0.05) → 13 cols × 21 rows = 273 rays +_HM_NUM_Y = 21 # actor grid rows (fwd/back, y) +_HM_NUM_X = 13 # actor grid cols (left/right, x) + +# Critic sensor: full surrounding scan centered on the pelvis body. +# GridPatternCfg(size=(1.0, 1.0), resolution=0.05) → 21 cols × 21 rows = 441 rays +_HM_CRITIC_NUM_Y = 21 # critic grid rows +_HM_CRITIC_NUM_X = 21 # critic grid cols + + +def vr_m3_12dof_height_map_dwt_dr_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """Asymmetric actor-critic height-map env with DWT band-specific DR. + + Two separate raycasters replace the shared ``terrain_scan``: + + * **Actor** (``terrain_scan_actor``): foreground patch mounted at + ``heightmap_site`` (0.5 m ahead of pelvis), 0.6 × 1.0 m @ 0.05 m + resolution, ``include_geom_groups=(0, 1, 2)`` so the actor can detect + body geometry (self-collision awareness during foothold selection). + The height observation uses DWT band-specific domain randomisation to + simulate the real-sensor high-frequency dropout at stair edges. + + * **Critic** (``terrain_scan_critic``): full surrounding patch mounted at + the pelvis body origin, 1.0 × 1.0 m @ 0.05 m resolution, + ``include_geom_groups=(0,)`` (terrain only — body geometry does not + pollute privileged height values). The critic additionally receives a + log-scaled DWT energy ratio as a terrain-type signal. + """ + from src.tasks.velocity.mdp.terrain_classifier import terrain_energy_ratio + + cfg = vr_m3_12dof_height_map_env_cfg(play=play) + + # Remove the single shared terrain_scan added by the base height-map cfg. + cfg.scene.sensors = tuple(s for s in cfg.scene.sensors if s.name != "terrain_scan") + + # Actor sensor — foreground, groups 0-2 (terrain + body). + terrain_scan_actor = RayCastSensorCfg( + name="terrain_scan_actor", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(0.6, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + # Critic sensor — full surrounding, group 0 only (terrain, no body). + terrain_scan_critic = RayCastSensorCfg( + name="terrain_scan_critic", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(1.0, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0,), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + cfg.scene.sensors = cfg.scene.sensors + (terrain_scan_actor, terrain_scan_critic) + + # Actor obs: DWT band-specific DR from the foreground sensor. + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_scan_dwt_aug, + params={ + "sensor_name": "terrain_scan_actor", + "num_y": _HM_NUM_Y, + "num_x": _HM_NUM_X, + "miss_value": 2.0, + "sigma_hh": 0.15, + "sigma_lh_hl": 0.05, + "sigma_ll": 0.02, + "attenuation_low": 0.3, + "attenuation_high": 1.0, + }, + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic obs: clean surrounding heightmap (privileged, no noise). + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan_critic", "miss_value": 2.0}, + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic obs: DWT energy ratio from the surrounding scan. + cfg.observations["critic"].terms["terrain_energy_ratio"] = ObservationTermCfg( + func=terrain_energy_ratio, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + history_length=5, + ) + + if play: + cfg.observations["actor"].enable_corruption = False + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 2 — DWT Encoder + Band DR +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_full_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT encoder with band-specific DR (Phase 2). + + Extends ``vr_m3_12dof_height_map_dwt_dr_env_cfg`` for use with + ``InstinctOnPolicyRunner`` + ``EncoderActorCritic`` + ``DWTParallelLayer``: + + - Actor ``height_scan``: ``height_scan_dwt_aug_as_grid`` — returns a 2D + ``[B, num_y, num_x]`` grid with band-specific DR applied, so + ``DWTParallelLayer`` can reshape it to ``[B, 1, H, W]`` for + ``DWTHeadModel``. Band DR (σ_hh=0.15, σ_lh_hl=0.05, σ_ll=0.02) + simulates real-sensor high-frequency dropout. + - ``concatenate_terms=False`` on actor (mixed 2-D/1-D terms). + - ``"policy"`` obs-group alias added for the instinct runner. + - Critic unchanged from DWT-DR (clean flat surrounding scan + energy ratio). + """ + from copy import deepcopy as _dc + + cfg = vr_m3_12dof_height_map_dwt_dr_env_cfg(play=play) + + # Band-DR augmented 2D grid for the DWT encoder. + # Returns [B, num_y, num_x]; concatenate_terms=False avoids mixed-rank + # torch.stack — the instinct encoder system processes each component separately. + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_scan_dwt_aug_as_grid, + params={ + "sensor_name": "terrain_scan_actor", + "num_y": _HM_NUM_Y, + "num_x": _HM_NUM_X, + "miss_value": 2.0, + "sigma_hh": 0.15, + "sigma_lh_hl": 0.05, + "sigma_ll": 0.02, + "attenuation_low": 0.3, + "attenuation_high": 1.0, + }, + clip=(0.0, 2.0), + ) + cfg.observations["actor"].concatenate_terms = False + + # "policy" alias for instinct runner (policy_observation_group="policy"). + cfg.observations["policy"] = _dc(cfg.observations["actor"]) + + if play: + cfg.observations["actor"].enable_corruption = False + cfg.observations["policy"].enable_corruption = False + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 3 — Lightweight Obs & Reward Shaping +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_dr_v2_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT-DR v2: Phase 3 observations and reward terms added to the DWT-DR env. + + Builds on ``vr_m3_12dof_height_map_dwt_dr_env_cfg`` with zero architecture + changes. New critic observations (subband energy map, DWT entropy, cross-band + coherence) give the value function richer terrain-type signals at essentially + zero overhead. Both actor and critic gain a richer velocity representation. + Two DWT-based reward terms encourage action smoothness and gait symmetry. + + New critic obs: + * ``subband_energy_map`` — 4-channel squared energy of DWT subbands + * ``dwt_terrain_entropy`` — Shannon entropy of DWT coefficients [B, 1] + * ``dwt_subband_coherence`` — cross-band (LH/HH, HL/HH) coherence [B, 2] + + New actor+critic obs: + * ``base_lin_vel`` replaced by ``base_velocity_dwt_filtered`` [B, 4] + (vel_x, vel_y, vel_z, speed_xy) + + New rewards (both registered with weight=-1.0 — functions return positive): + * ``dwt_action_smoothness`` — penalise high-freq detail energy in actions + * ``dwt_gait_symmetry`` — penalise L/R joint oscillation asymmetry + """ + from src.tasks.velocity.mdp.terrain_classifier import ( + dwt_terrain_entropy, + dwt_subband_coherence, + ) + + cfg = vr_m3_12dof_height_map_dwt_dr_env_cfg(play=play) + + # -- Critic obs: subband energy map (4 × H' × W' flattened) -- + cfg.observations["critic"].terms["subband_energy_map"] = ObservationTermCfg( + func=mdp.subband_energy_map, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic obs: DWT coefficient entropy -- + cfg.observations["critic"].terms["dwt_terrain_entropy"] = ObservationTermCfg( + func=dwt_terrain_entropy, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic obs: cross-band coherence [B, 2] -- + cfg.observations["critic"].terms["dwt_subband_coherence"] = ObservationTermCfg( + func=dwt_subband_coherence, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic: augment base_lin_vel with speed_xy for richer velocity signal [B, 4] -- + # Actor has no linear velocity term (not available from real-robot sensors); + # only the critic gets this privileged signal during training. + cfg.observations["critic"].terms["base_lin_vel"] = ObservationTermCfg( + func=mdp.base_velocity_dwt_filtered, + params={"asset_cfg": SceneEntityCfg("robot")}, + ) + + # -- DWT action smoothness penalty (positive metric, negative weight in cfg) -- + cfg.rewards["dwt_action_smoothness"] = RewardTermCfg( + func=mdp.dwt_action_smoothness, + params={"action_name": "joint_pos", "lambda_hf": 0.01}, + weight=-1.0, + ) + + # -- DWT gait symmetry penalty (positive metric, negative weight in cfg) -- + cfg.rewards["dwt_gait_symmetry"] = RewardTermCfg( + func=mdp.dwt_gait_symmetry, + params={ + "left_cfg": SceneEntityCfg("robot", joint_names=r"left_.*"), + "right_cfg": SceneEntityCfg("robot", joint_names=r"right_.*"), + "lambda_sym": 0.01, + }, + weight=-1.0, + ) + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 4 — 1D Temporal DWT for Proprioceptive Signals +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_proprioceptive_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 4: temporal DWT obs for proprioceptive signals on top of DWT-DR-v2. + + Builds on ``vr_m3_12dof_height_map_dwt_dr_v2_env_cfg`` with zero architecture + and no history_length changes. Adds four new obs terms and one new reward: + + New **actor** obs (deployable — no privileged sensors): + * ``imu_dwt_filtered`` [B, 12] — DWT slow-trend + noise-energy of IMU history + * ``joint_history_dwt`` [B, 48] — DWT slow-trend + fast-transient energy of joint history + + New **critic** obs (privileged / training-only): + * ``grf_dwt_features`` [B, 12] — contact onset-sharpness from foot-force history + + New reward (register with weight=-1.0 to penalise oscillatory GRF): + * ``dwt_contact_quality`` — level-1 DWT HF energy in normal GRF + + All DWT terms use level=1 with the existing history_length=5, which satisfies + the Db4 minimum signal length (T>=4). Increase history_length and level to 2 + (requires T>=5 at level 1 and T>=9 for the level-2 recursion) for finer + frequency resolution. + """ + cfg = vr_m3_12dof_height_map_dwt_dr_v2_env_cfg(play=play) + + # -- Actor obs: DWT-compressed IMU (angular velocity + projected gravity) -- + # base_ang_vel and projected_gravity are already in actor_terms (h=5) and + # will be processed BEFORE this term in the obs group dict, populating their + # history buffers before imu_dwt_filtered reads them. + cfg.observations["actor"].terms["imu_dwt_filtered"] = ObservationTermCfg( + func=mdp.imu_dwt_filtered, + params={"obs_group": "actor", "level": 1}, + ) + + # -- Actor obs: DWT-compressed joint history (position + velocity) -- + cfg.observations["actor"].terms["joint_history_dwt"] = ObservationTermCfg( + func=mdp.joint_history_dwt, + params={"obs_group": "actor", "level": 1}, + ) + + # -- Critic obs: GRF onset-sharpness (critic-only; not deployable) -- + # foot_contact_forces is already in critic_terms (h=5); grf_dwt_features + # is appended AFTER it so the buffer is already updated when this runs. + cfg.observations["critic"].terms["grf_dwt_features"] = ObservationTermCfg( + func=mdp.grf_dwt_features, + params={"obs_group": "critic", "level": 1}, + ) + + # -- Reward: penalise oscillatory GRF (smooth, controlled foot placement) -- + cfg.rewards["dwt_contact_quality"] = RewardTermCfg( + func=mdp.dwt_contact_quality_reward, + params={"sensor_name": "feet_ground_contact", "lambda_quality": 0.005}, + weight=-1.0, + ) + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 5 — Depth Image DWT Encoder +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_depth_map_dwt_enc_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 5: depth map task using DepthDWTHeadModel encoder. + + Observation pipeline is identical to ``vr_m3_12dof_depth_map_env_cfg``. + The DWT encoding happens entirely in the network (``DWTParallelLayer`` + + ``DepthDWTHeadModel`` configured in ``vr_m3_12dof_depth_map_dwt_enc_rl_cfg``). + + Adds ``depth_obstacle_channel`` [B, 225] to the policy obs group as a + pre-computed DWT-based obstacle proximity feature (edge energy × inv-depth). + """ + cfg = vr_m3_12dof_depth_map_env_cfg(play=play) + + cfg.observations["policy"].terms["depth_obstacle_channel"] = ObservationTermCfg( + func=mdp.depth_obstacle_channel, + params={ + "sensor_cfg": SceneEntityCfg("camera"), + "image_h": 30, + "image_w": 30, + "data_type": "distance_to_image_plane_noised", + }, + noise=None, + ) + + return cfg + + +def vr_m3_12dof_foothold_depth_map_dwt_enc_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 5 variant on the foothold base: DepthDWTHeadModel encoder + foothold planner. + + Inherits from ``vr_m3_12dof_foothold_env_cfg`` which already provides the depth + camera, "policy" obs alias, DCM foothold command, and foothold rewards. + + Adds ``depth_obstacle_channel`` [B, 225] to the policy obs group. + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["policy"].terms["depth_obstacle_channel"] = ObservationTermCfg( + func=mdp.depth_obstacle_channel, + params={ + "sensor_cfg": SceneEntityCfg("camera"), + "image_h": 30, + "image_w": 30, + "data_type": "distance_to_image_plane_noised", + }, + noise=None, + ) + + return cfg + +def vr_m3_12dof_foothold_fdf_env_cfg( + play: bool = False, + mask_fraction: float = 0.7, +) -> MultiCriticManagerBasedRlEnvCfg: + """Foothold task with Frequency-Domain Filtering (FDF) on the depth image. + + Replaces the raw delayed depth-image term from ``vr_m3_12dof_foothold_env_cfg`` + with an FFT-based low-pass filtered version (``mdp.depth_image_fft_lowpass_cls``): + a 2D FFT is applied per frame and the outer ``mask_fraction`` of the frequency + spectrum (by radial distance from the DC bin) is zeroed before reconstructing via + inverse FFT. A higher ``mask_fraction`` removes more high-frequency terrain/ + obstacle detail, simulating a lower-bandwidth depth sensor. + + To sweep masking strength (e.g. 0.1 / 0.3 / 0.5 / 0.7), edit this default. + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["actor"] = cfg.observations.pop("policy") + + for group in ("actor", "critic"): + base_term = cfg.observations[group].terms["depth_image"] + cfg.observations[group].terms["depth_image"] = replace( + base_term, + func=mdp.depth_image_fft_lowpass_cls(), + params={**base_term.params, "mask_fraction": mask_fraction}, + ) + + return cfg diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/policy.onnx b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/policy.onnx new file mode 100644 index 0000000000000000000000000000000000000000..7ce909bd38bb3cb717b4364b6ab47a907f70325e --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-07-29_vr_m3_12dof_dwt_foothold/policy.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0a6dc9fd1b43567f7b9a530eaac5671977f55d0826d5b6bbddba6c466f937ba +size 18840693 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560131.worker-4.1989917.0 b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560131.worker-4.1989917.0 new file mode 100644 index 0000000000000000000000000000000000000000..8ad9253f8ed9d8df38042cd80d46fd69ce471548 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560131.worker-4.1989917.0 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e8364b04f52ae3eb953d3ca2196c5a400cb51ae8336db20766c3ab086de6a70 +size 146762550 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff new file mode 100644 index 0000000000000000000000000000000000000000..2969a03e6c8b31a6e0be0a6117195e9961ba3a03 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff @@ -0,0 +1,30 @@ +--- git commit --- +59c3c413a30c0a375f2365e7f02a02e5023b9634 + + +--- git status --- +On branch dev/fdf +Your branch is up to date with 'origin/dev/fdf'. + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: src/tasks/velocity/config/vr_m3_12dof/__init__.py + +no changes added to commit (use "git add" and/or "git commit -a") + + +--- git diff --- +diff --git a/src/tasks/velocity/config/vr_m3_12dof/__init__.py b/src/tasks/velocity/config/vr_m3_12dof/__init__.py +index a6e8d27..62586d9 100644 +--- a/src/tasks/velocity/config/vr_m3_12dof/__init__.py ++++ b/src/tasks/velocity/config/vr_m3_12dof/__init__.py +@@ -203,7 +203,7 @@ except (AttributeError, ImportError): + # Frequency Domain Filtering + register_mjlab_task( + task_id="VR-M3-12DOF-Foothold-FDF", +- env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(), ++ env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(mask_fraction=0.3), + play_env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(play=True), + rl_cfg=vr_m3_12dof_foothold_fdf_vr_rsl_rl_runner_cfg(), + runner_cls=VelocityOnPolicyRunner, \ No newline at end of file diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff new file mode 100644 index 0000000000000000000000000000000000000000..7d752229105146469e937c736f4169b4e7cde8e5 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff @@ -0,0 +1,12 @@ +--- git commit --- +13b0b308e7cd73f7d4188a8a3cde9a98db717e0f + + +--- git status --- +On branch main +Your branch is up to date with 'origin/main'. + +nothing to commit, working tree clean + + +--- git diff --- diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_0.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_0.pt new file mode 100644 index 0000000000000000000000000000000000000000..10a534bff97d76493c3b35f5482e061e23a6fe53 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_0.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:359fa0fc00befdc760c682bcb14069a49784881a0604f55f923778f0aedd95c4 +size 125693797 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_1000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_1000.pt new file mode 100644 index 0000000000000000000000000000000000000000..a16f235da9fa0c663748e8658f4f933564f29ebf --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_1000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a980e161595f7547b0eed3ae1c5ed2d3a8bbbe804b8e559e060e33e45a89ba5 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_10000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_10000.pt new file mode 100644 index 0000000000000000000000000000000000000000..48cb5145ad9adae88247516a3e11a93b3c702180 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_10000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b965d38a90c0e7bd9aedc09704225441c8e09e41e7b51fa46b50af573746a83f +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_11000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_11000.pt new file mode 100644 index 0000000000000000000000000000000000000000..3a1b5eb58a7a898ce46584394f1a208f9d6749bf --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_11000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:975cdf7d445ddb6af8504ae2adc6925d2f9afc7bcd77f0e26355a0bb2054013e +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_12000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_12000.pt new file mode 100644 index 0000000000000000000000000000000000000000..b267cf401c3b814975e41f6bce57ba6bdb5ba949 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_12000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce14bc1418b45f548fb629836fc1ee9dbcdc29006f82aab17f7db07e59657335 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_13000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_13000.pt new file mode 100644 index 0000000000000000000000000000000000000000..e275f2c11c69ed11cd180d7f3f18e9e2e8d32a5c --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_13000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:195a9c489f79d28e5efa16eed8f17408ec7ddf64c9a6ca4d43772ccc4ee94a60 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_14000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_14000.pt new file mode 100644 index 0000000000000000000000000000000000000000..623c64426daf87f3384b513bcc6172109d6dfef3 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_14000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90d672c88d0af3b7d837c44f2a380a1a8c2f9440e391a056207da9241a5353b2 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_15000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_15000.pt new file mode 100644 index 0000000000000000000000000000000000000000..fcd7bdb10ecc55724dd2b1fd57bdb271d42ef07b --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_15000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d524c01e3f587e003da5474e46a7ec60c597b51f89190a4c0252122e3527bb9d +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_16000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_16000.pt new file mode 100644 index 0000000000000000000000000000000000000000..23f02919f98ff8aa6b4c8646e2125bdd8fc4b49c --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_16000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76b4877b75e7a4161c857cfc43812a5313f684446732b5e934f92ac605cd1104 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_17000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_17000.pt new file mode 100644 index 0000000000000000000000000000000000000000..d7e74ed2ff737ba995a42143dd831291bca4d9a9 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_17000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d8b8adea5abcda480ca6ee72f4031c11478423845aafe6ba64dae2be03b647a +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_18000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_18000.pt new file mode 100644 index 0000000000000000000000000000000000000000..8a2a43350930e9485826e3fca67d891f6b7bdf44 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_18000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4bff6eb912673d400934a4ef0657bd511d90f459672655374c662eff8219328e +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_19000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_19000.pt new file mode 100644 index 0000000000000000000000000000000000000000..586b1963b7ae40fb2b7be2bcbc1928c680949d82 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_19000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:685f90810d24d8a428ba9363ed930a202b423a67198523b32bc6de072862050c +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_2000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_2000.pt new file mode 100644 index 0000000000000000000000000000000000000000..11c4b72c3bc7be7ddd9cd29df2638294db2d0ce5 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_2000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fa69c6561c2b6b3e15192f35adeec79845bcf18e6a1c01d01c45d7f2428f005 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_20000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_20000.pt new file mode 100644 index 0000000000000000000000000000000000000000..e2f54b3794abe7614d8576ea382527d5b5bb955b --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_20000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1e8cc8d63e4b4d418358164d89b0de6aefddd792d7f2e43b5def13b264c05cd +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_21000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_21000.pt new file mode 100644 index 0000000000000000000000000000000000000000..370e41fabaf29c05636893f5c7d318c265c349bf --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_21000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eaa612f790eafb041046c2388bfc89610aa8830735d8f7784d1ebbeae72a9305 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_22000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_22000.pt new file mode 100644 index 0000000000000000000000000000000000000000..3bbce28cadf22eff6085023cbad7b3619abc0740 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_22000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f96e1181992e7aba14c473884c5e3d28dcbddfba397a5e858071dc43311e8b6d +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_23000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_23000.pt new file mode 100644 index 0000000000000000000000000000000000000000..50f389687aaff90b1281e7515291d8cfb5640831 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_23000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a35730c187f92f31f42a2c4e069f5ab72bc1fce96164d3f2d13e7cc7b0a7dc69 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_24000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_24000.pt new file mode 100644 index 0000000000000000000000000000000000000000..7102062aef14226f087352cf4c9cee4d2105828d --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_24000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c043381a50f30efde7dec1e0385257758536116b87c582bed05e5870f46ae27 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_25000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_25000.pt new file mode 100644 index 0000000000000000000000000000000000000000..e3aa646ab6d6dc1f274e72b70d895a3d4572d427 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_25000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86b48547f6a59c93d4bf2be68f46164dcb0c40ca41dae50ec48bf7028081c7e6 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_26000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_26000.pt new file mode 100644 index 0000000000000000000000000000000000000000..d0907752d26c514eb34f3fc6cf6a08e22d0b095c --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_26000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fea8b7a831f00c24ed2bac73c31995e17c2edcb76101b48fa96828e9109b8408 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_27000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_27000.pt new file mode 100644 index 0000000000000000000000000000000000000000..1de83c2bb4ba44d28f480a8d71af89437616e53d --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_27000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5042a2a88a12fc19ca52b3b23086cae86dc244f97bbe599a284d2494a838bcb3 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_28000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_28000.pt new file mode 100644 index 0000000000000000000000000000000000000000..39da55a02695e5c2431a5bc5d3b60ccb83d89983 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_28000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8de4f8ceae8dd77b0879d601497103dab421daf31ba319372f4456ac019fde1 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_29000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_29000.pt new file mode 100644 index 0000000000000000000000000000000000000000..97c64241f43a799c513ff614c1a6b25f5408b596 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_29000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42523c307a05f07381c550e27b4d5e9a2e6251e6ccbc9c9240b36fa340ea2d45 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_3000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_3000.pt new file mode 100644 index 0000000000000000000000000000000000000000..e67a9a256decad0d8caab6fadd3916d86928c853 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_3000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20784e7cfebe0d8e3affe11aeed06ec4336a838d7eb51c3ac2e5625813680ccc +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_30000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_30000.pt new file mode 100644 index 0000000000000000000000000000000000000000..3673d0256e4b959bf914c187148da14292b55cd5 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_30000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df34576431d2b2988cc4ffaca59d34d90c81358a0189798aa4789ae6f190b33d +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_31000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_31000.pt new file mode 100644 index 0000000000000000000000000000000000000000..f4f3d21c5413e7c6ccbe68f81fe556211fc30cf0 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_31000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d709c59432bbd23b5a76c28a79cc25ebb770baf292f538f1601be1345488264 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_32000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_32000.pt new file mode 100644 index 0000000000000000000000000000000000000000..9029e699cdc3c7b965d4c6f2e189e19ab2fe672b --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_32000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c735b30e8aaec287ab1376b322b647c8d16134cf64e18778926b650c0fa9e210 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_33000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_33000.pt new file mode 100644 index 0000000000000000000000000000000000000000..a784bd98a61f21a26f203fd2cc588297b10f9db1 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_33000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a580aea6fd8e0c4331fa5814223384abbe4bc8e61254307596f9f13dcb38f1b4 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_34000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_34000.pt new file mode 100644 index 0000000000000000000000000000000000000000..657212e9ce8bfcf17d579b381a0d40282f35bfca --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_34000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65cb47bd21c4a5b646cdf9f19394c811e841861578e166d70a7795489fc7a66a +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_35000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_35000.pt new file mode 100644 index 0000000000000000000000000000000000000000..f8976d170c4362cb984ca66714196e4a5d72831b --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_35000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40ea356b89eda3618b48340bb99efb8c313b103b973191845d991a0dde27ecd0 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_4000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_4000.pt new file mode 100644 index 0000000000000000000000000000000000000000..ffadd5c74becce12571dfdbb2ac73e363bab39e2 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_4000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ed090132bd12154942c9001f2ad6ae38712598368b3bdf3f5bbe46856f752c4 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_5000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_5000.pt new file mode 100644 index 0000000000000000000000000000000000000000..49ef1563b714d73e880895927e82a605b5091907 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_5000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1200b4cee741d12eb8e0767bd9dde3344d687417a36c1761e8d54c2c5881c317 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_6000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_6000.pt new file mode 100644 index 0000000000000000000000000000000000000000..ff505060a0f5d2349f7e8ac7e4e46336c8c82cc8 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_6000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30aceabf2608911a874076a4017a1763d626856c76ef75e8887c883dc032beb0 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_7000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_7000.pt new file mode 100644 index 0000000000000000000000000000000000000000..1a6321dea5d3de9df0d3fb0aedf45e723d669334 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_7000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f01a353e942f9869393c7ab2b7cab395d70c27bc5e759629cbc4ca3d0b665a0b +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_8000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_8000.pt new file mode 100644 index 0000000000000000000000000000000000000000..57a26ffa7bb8f78086c63a0f56072e0608656d46 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_8000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f279af02199bca227cf55fb60cfe8b55196913f8bea5d83f209515cd1db2e517 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_9000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_9000.pt new file mode 100644 index 0000000000000000000000000000000000000000..6c157a0b69a1486b5a615e0915ce96a049be0802 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/model_9000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c97c36ad6ff0d1c92fec3c0d408467af3f5c3c795de83fa9f3e94b8bce607ac +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/agent.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/agent.yaml new file mode 100644 index 0000000000000000000000000000000000000000..aa9b9f4a68d6235397146bc0edd8227bbcb7d230 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/agent.yaml @@ -0,0 +1,139 @@ +seed: 42 +num_steps_per_env: 24 +max_iterations: 100001 +obs_groups: + actor: + - base_ang_vel + - projected_gravity + - velocity_commands + - joint_pos_rel + - joint_vel_rel + - last_action + - gait_phase + - depth_image + critic: + - base_ang_vel + - projected_gravity + - velocity_commands + - joint_pos_rel + - joint_vel_rel + - last_action + - gait_phase + - base_lin_vel + - true_base_velocity + - foot_height + - foot_air_time + - foot_contact + - foot_contact_forces + - knee_reference + - height_scan + - foothold_target + - depth_image +save_interval: 1000 +experiment_name: vr_m3_12dof_dwt_foothold +run_name: vr_m3_12dof_dwt_foothold +logger: wandb +wandb_project: vr_m3_12dof +wandb_tags: !!python/tuple [] +resume: false +load_run: .* +load_checkpoint: model_.*.pt +clip_actions: null +upload_model: true +class_name: OnPolicyRunner +actor: + hidden_dims: !!python/tuple + - 1024 + - 512 + - 256 + - 128 + activation: elu + obs_normalization: true + cnn_cfg: + output_channels: !!python/tuple + - 32 + - 32 + kernel_size: !!python/tuple + - 3 + - 3 + stride: !!python/tuple + - 1 + - 1 + dilation: !!python/tuple + - 1 + - 1 + padding: 1 + padding_mode: replicate + norm: none + activation: relu + max_pool: false + max_pool_kernel_size: 3 + max_pool_stride: 2 + max_pool_padding: 0 + global_pool: none + head_output_dim: 64 + head_hidden_dims: + - 128 + - 64 + head_activation: relu + head_last_activation: relu + distribution_cfg: + init_std: 1.0 + std_type: scalar +critic: + hidden_dims: !!python/tuple + - 1024 + - 512 + - 256 + - 128 + activation: elu + obs_normalization: true + cnn_cfg: + output_channels: !!python/tuple + - 32 + - 32 + kernel_size: !!python/tuple + - 3 + - 3 + stride: !!python/tuple + - 1 + - 1 + dilation: !!python/tuple + - 1 + - 1 + padding: 1 + padding_mode: replicate + norm: none + activation: relu + max_pool: false + max_pool_kernel_size: 3 + max_pool_stride: 2 + max_pool_padding: 0 + global_pool: none + head_output_dim: 64 + head_hidden_dims: + - 128 + - 64 + head_activation: relu + head_last_activation: relu + distribution_cfg: + init_std: 1.0 + std_type: scalar +algorithm: + num_learning_epochs: 5 + num_mini_batches: 4 + learning_rate: 0.001 + schedule: adaptive + gamma: 0.99 + lam: 0.95 + entropy_coef: 0.005 + desired_kl: 0.01 + max_grad_norm: 1.0 + value_loss_coef: 1.0 + use_clipped_value_loss: true + clip_param: 0.2 + normalize_advantage_per_mini_batch: false + optimizer: adam + rnd_cfg: null + symmetry_cfg: null +multi_gpu: null diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/deploy.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/deploy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d987e43c06480d3971be5ae972f3bed50b1acf6d --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/deploy.yaml @@ -0,0 +1,93 @@ +joint_name: [left_hip_pitch_joint, left_hip_roll_joint, left_hip_yaw_joint, left_knee_pitch_joint, + left_ankle_pitch_joint, left_ankle_roll_joint, right_hip_pitch_joint, right_hip_roll_joint, + right_hip_yaw_joint, right_knee_pitch_joint, right_ankle_pitch_joint, right_ankle_roll_joint] +joint_ids_map: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] +step_dt: 0.02 +stiffness: [150.0, 150.0, 120.0, 200.0, 200.0, 200.0, 150.0, 150.0, 120.0, 200.0, + 200.0, 200.0] +damping: [25.0, 25.0, 4.0, 10.0, 8.0, 8.0, 25.0, 25.0, 4.0, 10.0, 8.0, 8.0] +default_joint_pos: [-0.1, 0.0, 0.0, 0.2, -0.1, 0.0, -0.1, 0.0, 0.0, 0.2, -0.1, 0.0] +commands: + twist: + ranges: + lin_vel_x: [0.0, 1.0] + lin_vel_y: [0.0, 0.0] + ang_vel_z: [-0.5, 0.5] + heading: null +actions: + JointPositionAction: + clip: null + scale: [0.6, 0.6, 0.271, 0.45, 0.15, 0.15, 0.6, 0.6, 0.271, 0.45, 0.15, 0.15] + offset: [-0.1, 0.0, 0.0, 0.2, -0.1, 0.0, -0.1, 0.0, 0.0, 0.2, -0.1, 0.0] + joint_names: [.*] + joint_ids: null +observations: + base_ang_vel: + params: {sensor_name: robot/imu_ang_vel} + clip: null + scale: [0.25, 0.25, 0.25] + history_length: 5 + projected_gravity: + params: {} + clip: null + scale: [1.0, 1.0, 1.0] + history_length: 5 + velocity_commands: + params: {command_name: twist} + clip: null + scale: [1.0, 1.0, 1.0] + history_length: 5 + joint_pos_rel: + params: {} + clip: null + scale: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + history_length: 5 + joint_vel_rel: + params: {} + clip: null + scale: [0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05] + history_length: 5 + last_action: + params: {} + clip: null + scale: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + history_length: 5 + gait_phase: + params: {period: 0.9, command_name: twist} + clip: null + scale: [1.0, 1.0] + history_length: 5 + depth_image: + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice [null, null, null] + body_names: null + body_ids: !!python/object/apply:builtins.slice [null, null, null] + geom_names: null + geom_ids: !!python/object/apply:builtins.slice [null, null, null] + site_names: null + site_ids: !!python/object/apply:builtins.slice [null, null, null] + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice [null, null, null] + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice [null, null, null] + camera_names: null + camera_ids: !!python/object/apply:builtins.slice [null, null, null] + light_names: null + light_ids: !!python/object/apply:builtins.slice [null, null, null] + material_names: null + material_ids: !!python/object/apply:builtins.slice [null, null, null] + pair_names: null + pair_ids: !!python/object/apply:builtins.slice [null, null, null] + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: [0, 1] + debug_vis: false + mask_fraction: 0.3 + clip: null + scale: [1.0, 1.0, 1.0, 1.0] + history_length: 1 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/env.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/env.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d5d2b220f2e1ff35e014eb19d1d4be29ffad6220 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/env.yaml @@ -0,0 +1,3768 @@ +decimation: 4 +scene: + num_envs: 1024 + env_spacing: 2.0 + terrain: + init_state: + pos: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + rot: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.0 + lin_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + ang_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + joint_pos: + .*: 0.0 + joint_vel: + .*: 0.0 + spec_fn: !!python/name:mjlab.entity.entity.%3Clambda%3E '' + articulation: null + sort_actuators: false + lights: !!python/tuple + - name: sun + body: world + mode: fixed + target: null + type: directional + castshadow: true + pos: !!python/tuple + - 0.0 + - 0.0 + - 1.5 + dir: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + cutoff: 45.0 + exponent: 10.0 + cameras: !!python/tuple [] + textures: !!python/tuple + - name: groundplane + type: 2d + builtin: checker + rgb1: !!python/tuple + - 0.2 + - 0.3 + - 0.4 + rgb2: !!python/tuple + - 0.1 + - 0.2 + - 0.3 + width: 300 + height: 300 + mark: edge + markrgb: !!python/tuple + - 0.8 + - 0.8 + - 0.8 + materials: !!python/tuple + - name: groundplane + rgba: !!python/tuple + - 1.0 + - 1.0 + - 1.0 + - 1.0 + texuniform: true + texrepeat: !!python/tuple + - 4.0 + - 4.0 + reflectance: 0.2 + texture: groundplane + geom_names_expr: !!python/tuple + - terrain$ + collisions: !!python/tuple [] + terrain_type: generator + terrain_generator: + seed: null + curriculum: true + size: !!python/tuple + - 8.0 + - 8.0 + border_width: 1.0 + border_height: 1.0 + num_rows: 10 + num_cols: 14 + color_scheme: height + sub_terrains: + flat: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + pyramid_stairs: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.3 + platform_width: 3.0 + holes: false + pyramid_stairs_med: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.45 + platform_width: 3.0 + holes: false + pyramid_stairs_wide: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.6 + platform_width: 3.0 + holes: false + pyramid_stairs_inv: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.3 + platform_width: 3.0 + holes: false + pyramid_stairs_inv_med: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.45 + platform_width: 3.0 + holes: false + pyramid_stairs_inv_wide: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.6 + platform_width: 3.0 + holes: false + open_stairs_pyramid: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width_range: !!python/tuple + - 0.3 + - 0.6 + platform_width: 3.0 + border_width: 1.0 + step_thickness: 0.05 + inverted: false + open_stairs_bowl: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width_range: !!python/tuple + - 0.3 + - 0.6 + platform_width: 3.0 + border_width: 1.0 + step_thickness: 0.05 + inverted: true + hf_pyramid_slope: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + slope_range: !!python/tuple + - 0.0 + - 0.4 + platform_width: 2.0 + inverted: false + border_width: 0.25 + horizontal_scale: 0.2 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + hf_pyramid_slope_inv: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + slope_range: !!python/tuple + - 0.0 + - 0.4 + platform_width: 2.0 + inverted: true + border_width: 0.25 + horizontal_scale: 0.2 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + stepping_stones: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 30 + patch_radius: 0.2 + max_height_diff: 0.03 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + stone_size_range: !!python/tuple + - 0.4 + - 0.8 + stone_distance_range: !!python/tuple + - 0.2 + - 0.5 + stone_height: 0.2 + stone_height_variation: 0.05 + stone_size_variation: 0.1 + floor_depth: 2.0 + displacement_range: 0.1 + platform_width: 1.0 + border_width: 0.0 + uniform_noise: + proportion: 0.15 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + noise_range: !!python/tuple + - 0.02 + - 0.1 + noise_step: 0.02 + downsampled_scale: null + horizontal_scale: 0.1 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + border_width: 0.25 + difficulty_range: !!python/tuple + - 0.0 + - 1.0 + add_lights: true + env_spacing: 2.0 + max_init_terrain_level: 5 + num_envs: 1024 + entities: + robot: + init_state: + pos: !!python/tuple + - 0 + - 0 + - 0.9 + rot: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.0 + lin_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + ang_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + joint_pos: + .*_hip_pitch_joint: -0.1 + .*_hip_roll_joint: 0.0 + .*_hip_yaw_joint: 0.0 + .*_knee_pitch_joint: 0.2 + .*_ankle_pitch_joint: -0.1 + .*_ankle_roll_joint: 0.0 + joint_vel: + .*: 0.0 + spec_fn: !!python/name:src.assets.robots.vr_m3.vr_m3_12dof_constants.get_spec '' + articulation: + actuators: !!python/tuple + - target_names_expr: !!python/tuple + - .*_hip_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 150.0 + damping: 25.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_hip_roll_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 150.0 + damping: 25.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_hip_yaw_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.02864 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 120.0 + damping: 4.0 + effort_limit: 130.0 + - target_names_expr: !!python/tuple + - .*_knee_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 10.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_ankle_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.03006 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 8.0 + effort_limit: 120.0 + - target_names_expr: !!python/tuple + - .*_ankle_roll_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.03006 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 8.0 + effort_limit: 120.0 + soft_joint_pos_limit_factor: 0.9 + sort_actuators: false + lights: !!python/tuple [] + cameras: !!python/tuple [] + textures: !!python/tuple [] + materials: !!python/tuple [] + collisions: !!python/tuple + - geom_names_expr: !!python/tuple + - .*_collision_\d+ + contype: 1 + conaffinity: 1 + condim: + ^(left|right)_ankle_roll_link_collision_\d+$: 3 + .*_collision_\d+: 1 + priority: + ^(left|right)_ankle_roll_link_collision_\d+$: 1 + friction: + ^(left|right)_ankle_roll_link_collision_\d+$: !!python/tuple + - 0.6 + solref: null + solimp: null + margin: null + gap: null + solmix: null + disable_other_geoms: true + sensors: !!python/tuple + - name: feet_ground_contact + primary: + mode: subtree + pattern: ^(left_ankle_roll_link|right_ankle_roll_link)$ + entity: robot + exclude: !!python/tuple [] + secondary: + mode: body + pattern: terrain + entity: null + exclude: !!python/tuple [] + fields: !!python/tuple + - found + - force + reduce: netforce + num_slots: 1 + secondary_policy: first + track_air_time: true + global_frame: false + history_length: 4 + debug: false + - name: self_collision + primary: + mode: subtree + pattern: pelvis + entity: robot + exclude: !!python/tuple [] + secondary: + mode: subtree + pattern: pelvis + entity: robot + exclude: !!python/tuple [] + fields: !!python/tuple + - found + - force + reduce: none + num_slots: 1 + secondary_policy: first + track_air_time: false + global_frame: false + history_length: 4 + debug: false + - name: pelvis_height_measure + frame: + type: body + name: pelvis + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 2.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: left_height_scanner + frame: + type: site + name: left_foot + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 1.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: right_height_scanner + frame: + type: site + name: right_foot + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 1.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: terrain_scan + frame: + type: body + name: pelvis + entity: robot + pattern: + size: !!python/tuple + - 1.8 + - 1.2 + resolution: 0.05 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 2.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: true + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: camera + frame: + type: body + name: pelvis + entity: robot + pattern: + width: 80 + height: 60 + fovy: 63.668103675039276 + _camera_name: null + ray_alignment: base + max_distance: 2.5 + exclude_parent_body: false + include_geom_groups: !!python/tuple + - 0 + - 1 + - 2 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + class_type: !!python/name:instinct_mj.sensors.noisy_camera.noisy_grouped_raycaster_camera.NoisyGroupedRayCasterCamera '' + min_distance: 0.1 + mesh_prim_paths: [] + aux_mesh_and_link_names: {} + mesh_filter_max_hops: 24 + mesh_filter_epsilon: 0.0001 + offset: + pos: !!python/tuple + - 0.0 + - 0.018 + - -0.1 + rot: !!python/tuple + - 0.8660254037844387 + - 0.0 + - 0.49999999999999994 + - 0.0 + convention: world + data_types: + - distance_to_image_plane + update_period: 0.03333333333333333 + depth_clipping_behavior: max + focal_length: 1.0 + horizontal_aperture: 1.6555983034386739 + vertical_aperture: 1.2416987275790055 + horizontal_aperture_offset: 0.0 + vertical_aperture_offset: 0.0 + visualizer_cfg: + prim_path: /Visuals/RayCaster + markers: + hit: !!python/object/apply:types.SimpleNamespace + state: + radius: 0.02 + color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 1.0 + frame: !!python/object/apply:types.SimpleNamespace + state: + scale: !!python/tuple + - 0.1 + - 0.1 + - 0.1 + noise_pipeline: + crop_and_resize: + func: !!python/name:instinct_mj.utils.noise.noise_model.crop_and_resize '' + device: cuda:0 + crop_region: !!python/tuple + - 0 + - 0 + - 10 + - 10 + resize_shape: !!python/tuple + - 30 + - 30 + gaussian_blur: + func: !!python/name:instinct_mj.utils.noise.noise_model.gaussian_blur_noise '' + device: cuda:0 + kernel_size: 3 + sigma: 1 + depth_normalization: + func: !!python/name:instinct_mj.utils.noise.noise_model.depth_normalization '' + device: cuda:0 + depth_range: !!python/tuple + - 0.0 + - 2.5 + normalize: true + output_range: !!python/tuple + - 0.0 + - 1.0 + data_histories: + distance_to_image_plane_noised: 17 + - name: undesired_contact_forces + primary: + mode: body + pattern: .* + entity: robot + exclude: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + secondary: null + fields: !!python/tuple + - found + - force + reduce: netforce + num_slots: 1 + secondary_policy: first + track_air_time: false + global_frame: false + history_length: 3 + debug: false + extent: 2.0 + spec_fn: null +observations: + critic: + terms: + base_ang_vel: + func: &id001 !!python/name:mjlab.envs.mdp.observations.builtin_sensor '' + params: + sensor_name: robot/imu_ang_vel + noise: + operation: add + _tensor_cache: {} + n_min: -0.25 + n_max: 0.25 + clip: null + scale: 0.25 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + projected_gravity: + func: &id002 !!python/name:mjlab.envs.mdp.observations.projected_gravity '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + velocity_commands: + func: &id003 !!python/name:mjlab.envs.mdp.observations.generated_commands '' + params: + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_pos_rel: + func: &id004 !!python/name:mjlab.envs.mdp.observations.joint_pos_rel '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_vel_rel: + func: &id005 !!python/name:mjlab.envs.mdp.observations.joint_vel_rel '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -1.5 + n_max: 1.5 + clip: null + scale: 0.05 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + last_action: + func: &id006 !!python/name:mjlab.envs.mdp.observations.last_action '' + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + gait_phase: + func: &id007 !!python/name:src.tasks.velocity.mdp.observations.phase '' + params: + period: 0.9 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + base_lin_vel: + func: *id001 + params: + sensor_name: robot/imu_lin_vel + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + true_base_velocity: + func: !!python/name:mjlab.envs.mdp.observations.base_lin_vel '' + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_height: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_height '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_air_time: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_air_time '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_contact: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_contact '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_contact_forces: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_contact_forces '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + knee_reference: + func: !!python/name:src.tasks.velocity.mdp.rewards.get_desired_knee_angle '' + params: + period: 0.9 + offset: + - 0.0 + - 0.5 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + height_scan: + func: !!python/name:mjlab.envs.mdp.observations.height_scan '' + params: + sensor_name: terrain_scan + miss_value: 2.0 + noise: null + clip: !!python/tuple + - 0.0 + - 2.0 + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + foothold_target: + func: !!python/name:src.tasks.velocity.mdp.observations.foothold_target '' + params: + command_name: foothold + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + depth_image: + func: !!python/name:src.tasks.velocity.mdp.observations.DepthImageFFTLowpass '' + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: !!python/tuple + - 0 + - 1 + debug_vis: false + mask_fraction: 0.3 + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + concatenate_terms: false + concatenate_dim: -1 + enable_corruption: false + history_length: null + flatten_history_dim: true + nan_policy: sanitize + nan_check_per_term: true + actor: + terms: + base_ang_vel: + func: *id001 + params: + sensor_name: robot/imu_ang_vel + noise: + operation: add + _tensor_cache: {} + n_min: -0.25 + n_max: 0.25 + clip: null + scale: 0.25 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + projected_gravity: + func: *id002 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + velocity_commands: + func: *id003 + params: + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_pos_rel: + func: *id004 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_vel_rel: + func: *id005 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -1.5 + n_max: 1.5 + clip: null + scale: 0.05 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + last_action: + func: *id006 + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + gait_phase: + func: *id007 + params: + period: 0.9 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + depth_image: + func: !!python/name:src.tasks.velocity.mdp.observations.DepthImageFFTLowpass '' + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: !!python/tuple + - 0 + - 1 + debug_vis: false + mask_fraction: 0.3 + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + concatenate_terms: false + concatenate_dim: -1 + enable_corruption: true + history_length: null + flatten_history_dim: true + nan_policy: sanitize + nan_check_per_term: true +actions: + joint_pos: + entity_name: robot + clip: null + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + actuator_names: !!python/tuple + - .* + scale: + .*_hip_pitch_joint: 0.6 + .*_hip_roll_joint: 0.6 + .*_hip_yaw_joint: 0.2708333333333333 + .*_knee_pitch_joint: 0.45 + .*_ankle_pitch_joint: 0.15 + .*_ankle_roll_joint: 0.15 + offset: 0.0 + preserve_order: false + use_default_offset: true +events: + reset_base: + func: !!python/name:mjlab.envs.mdp.events.reset_root_state_uniform '' + params: + pose_range: + x: !!python/tuple + - -0.5 + - 0.5 + y: !!python/tuple + - -0.5 + - 0.5 + z: !!python/tuple + - 0.0 + - 0.0 + yaw: !!python/tuple + - -3.14 + - 3.14 + mode: reset + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + reset_robot_joints: + func: !!python/name:mjlab.envs.mdp.events.reset_joints_by_offset '' + params: + position_range: !!python/tuple + - -0.1 + - 0.1 + velocity_range: !!python/tuple + - -0.5 + - 0.5 + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + mode: reset + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + push_robot: + func: !!python/name:mjlab.envs.mdp.events.push_by_setting_velocity '' + params: + velocity_range: + x: !!python/tuple + - -0.5 + - 0.5 + y: !!python/tuple + - -0.5 + - 0.5 + z: !!python/tuple + - -0.4 + - 0.4 + roll: !!python/tuple + - -0.52 + - 0.52 + pitch: !!python/tuple + - -0.52 + - 0.52 + yaw: !!python/tuple + - -0.78 + - 0.78 + mode: interval + interval_range_s: !!python/tuple + - 5.0 + - 6.0 + is_global_time: false + min_step_count_between_reset: 0 + foot_friction: + func: !!python/name:mjlab.envs.mdp.dr.geom.geom_friction '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: !!python/tuple + - left_ankle_roll_link_collision_1 + - left_ankle_roll_link_collision_2 + - left_ankle_roll_link_collision_3 + - left_ankle_roll_link_collision_4 + - left_ankle_roll_link_collision_5 + - left_ankle_roll_link_collision_6 + - left_ankle_roll_link_collision_7 + - left_ankle_roll_link_collision_8 + - left_ankle_roll_link_collision_9 + - left_ankle_roll_link_collision_10 + - right_ankle_roll_link_collision_1 + - right_ankle_roll_link_collision_2 + - right_ankle_roll_link_collision_3 + - right_ankle_roll_link_collision_4 + - right_ankle_roll_link_collision_5 + - right_ankle_roll_link_collision_6 + - right_ankle_roll_link_collision_7 + - right_ankle_roll_link_collision_8 + - right_ankle_roll_link_collision_9 + - right_ankle_roll_link_collision_10 + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: abs + ranges: !!python/tuple + - 0.3 + - 1.6 + shared_random: true + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + encoder_bias: + func: !!python/name:mjlab.envs.mdp.dr.joint.encoder_bias '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + bias_range: !!python/tuple + - -0.015 + - 0.015 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + base_com: + func: &id008 !!python/name:mjlab.envs.mdp.dr.body.body_com_offset '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: + 0: !!python/tuple + - -0.05 + - 0.05 + 1: !!python/tuple + - -0.05 + - 0.05 + 2: !!python/tuple + - -0.05 + - 0.05 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + body_com: + func: *id008 + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - ^(?!waist_yaw_link$).* + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: + 0: !!python/tuple + - -0.03 + - 0.03 + 1: !!python/tuple + - -0.03 + - 0.03 + 2: !!python/tuple + - -0.03 + - 0.03 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + base_mass: + func: &id009 !!python/name:mjlab.envs.mdp.dr.body.body_mass '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: !!python/tuple + - -4.0 + - 4.0 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + body_mass: + func: *id009 + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - ^(?!waist_yaw_link$).* + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.9 + - 1.1 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_actuator_gains: + func: !!python/name:mjlab.envs.mdp.dr.actuator.pd_gains '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + kp_range: !!python/tuple + - 0.7 + - 1.1 + kd_range: !!python/tuple + - 0.7 + - 1.1 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_limit: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_limits '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.94 + - 1.06 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_stiffness: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_stiffness '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.7 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_frictionloss: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_friction '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.1 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_armature: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_armature '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.2 + - 5.0 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_damping: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_damping '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.7 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_ray_offsets: + func: !!python/name:instinct_mj.envs.mdp.events.randomization.randomize_ray_offsets '' + params: + asset_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + offset_pose_ranges: + x: !!python/tuple + - -0.01 + - 0.01 + y: !!python/tuple + - -0.01 + - 0.01 + z: !!python/tuple + - -0.03 + - 0.01 + roll: !!python/tuple + - -0.03490658503988659 + - 0.03490658503988659 + pitch: !!python/tuple + - -0.17453292519943295 + - 0.17453292519943295 + yaw: !!python/tuple + - -0.03490658503988659 + - 0.03490658503988659 + distribution: uniform + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 +seed: 42 +sim: + nconmax: 128 + njmax: 700 + ls_parallel: true + contact_sensor_maxmatch: 500 + mujoco: + timestep: 0.005 + integrator: implicitfast + impratio: 1.0 + cone: pyramidal + jacobian: auto + solver: newton + iterations: 10 + tolerance: 1.0e-08 + ls_iterations: 20 + ls_tolerance: 0.01 + ccd_iterations: 500 + gravity: !!python/tuple + - 0.0 + - 0.0 + - -9.81 + disableflags: !!python/tuple [] + enableflags: !!python/tuple [] + nan_guard: + enabled: false + buffer_size: 100 + output_dir: /tmp/mjlab/nan_dumps + max_envs_to_dump: 5 +viewer: + lookat: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + distance: 3.0 + fovy: null + elevation: -5.0 + azimuth: 90.0 + origin_type: !!python/object/apply:mjlab.viewer.viewer_config.OriginType + - 4 + entity_name: robot + body_name: waist_yaw_link + env_idx: 0 + max_extra_envs: 2 + enable_reflections: true + enable_shadows: true + height: 240 + width: 320 +episode_length_s: 20.0 +rewards: + track_linear_velocity: + func: !!python/name:src.tasks.velocity.mdp.rewards.track_linear_velocity '' + params: + command_name: twist + std: 0.5 + weight: 3.5 + track_angular_velocity: + func: !!python/name:src.tasks.velocity.mdp.rewards.track_angular_velocity '' + params: + command_name: twist + std: 0.7071067811865476 + weight: 3.0 + flat_orientation: + func: !!python/name:mjlab.envs.mdp.rewards.flat_orientation_l2 '' + params: {} + weight: -7.0 + pelvis_orientation_l2: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.link_orientation '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: pelvis + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -3.0 + joint_deviation_hip: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.joint_deviation_square '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .*_hip_yaw_joint + - .*_hip_roll_joint + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.3 + ang_vel_xy_l2: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.ang_vel_xy_l2 '' + params: {} + weight: -0.1 + dof_torques_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_torques_l2 '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .*_hip_.* + - .*_knee_.* + - .*_ankle_.* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0e-08 + dof_vel_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_vel_l2 '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -5.0e-07 + feet_flat_ori: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.feet_orientation_contact '' + params: + sensor_name: feet_ground_contact + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.01 + body_ang_vel: + func: !!python/name:src.tasks.velocity.mdp.rewards.body_angular_velocity_penalty '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.05 + angular_momentum: + func: !!python/name:src.tasks.velocity.mdp.rewards.angular_momentum_penalty '' + params: + sensor_name: robot/root_angmom + weight: -0.001 + is_terminated: + func: !!python/name:mjlab.envs.mdp.rewards.is_terminated '' + params: {} + weight: -200.0 + joint_acc_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_acc_l2 '' + params: {} + weight: -5.0e-07 + joint_pos_limits: + func: &id010 !!python/name:mjlab.envs.mdp.rewards.joint_pos_limits '' + params: {} + weight: -1.0 + action_rate_l2: + func: !!python/name:mjlab.envs.mdp.rewards.action_rate_l2 '' + params: {} + weight: -0.8 + foot_gait: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_gait '' + params: + period: 0.9 + offset: + - 0.0 + - 0.5 + threshold: 0.6 + command_threshold: 0.1 + command_name: twist + sensor_name: feet_ground_contact + weight: 2.0 + feet_double_support: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_double_support '' + params: + sensor_name: feet_ground_contact + period: 0.9 + offset: + - 0.0 + - 0.5 + threshold: 0.6 + command_name: twist + cmd_threshold: 0.1 + ds_match_weight: 1.0 + weight: 1.5 + foot_slip: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_slip '' + params: + sensor_name: feet_ground_contact + command_name: twist + command_threshold: 0.1 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.4 + feet_close_xy: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_close_xy_gauss '' + params: + threshold: 0.2 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + std: 0.22360679774997896 + weight: 1.0 + soft_landing: + func: !!python/name:src.tasks.velocity.mdp.rewards.soft_landing '' + params: + sensor_name: feet_ground_contact + command_name: twist + command_threshold: 0.1 + weight: -0.001 + dont_wait: + func: !!python/name:src.tasks.velocity.mdp.rewards.dont_wait '' + params: + command_name: twist + cmd_threshold: 0.1 + weight: -1.0 + stand_still: + func: !!python/name:src.tasks.velocity.mdp.rewards.stand_still '' + params: + command_name: twist + command_threshold: 0.1 + asset_cfg: + name: robot + joint_names: .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0 + self_collisions: + func: !!python/name:src.tasks.velocity.mdp.rewards.self_collision_cost '' + params: + sensor_name: self_collision + force_threshold: 10.0 + weight: -2.0 + feet_air_time: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_air_time '' + params: + sensor_name: feet_ground_contact + threshold: 0.36000000000000004 + command_name: twist + command_threshold: 0.1 + weight: 1.0 + feet_air_time_biped: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_air_time_positive_biped '' + params: + command_name: twist + sensor_name: feet_ground_contact + threshold: 0.52 + weight: 2.0 + terrain_foot_clearance: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_foot_clearance_cost '' + params: + target_clearance: 0.06 + left_terrain_sensor: left_height_scanner + right_terrain_sensor: right_height_scanner + command_name: twist + command_threshold: 0.05 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.5 + terrain_stumble: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_stumble_cost '' + params: + sensor_cfg: + name: feet_ground_contact + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + velocity_threshold: 0.15 + weight: -0.5 + terrain_base_height: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_base_height_l2_cost '' + params: + target_height: 0.9 + base_terrain_sensor: pelvis_height_measure + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.5 + feet_slide: + func: !!python/name:instinct_mj.tasks.parkour.mdp.rewards.feet_slide '' + params: + sensor_name: feet_ground_contact + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + threshold: 1.0 + weight: -0.4 + dof_pos_limits: + func: *id010 + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0 + foothold_tracking: + func: !!python/name:src.tasks.velocity.mdp.rewards.foothold_tracking '' + params: + command_name: foothold + sigma_stages: + - !!python/tuple + - 10.0 + - 5.0 + - !!python/tuple + - 20.0 + - 10.0 + - !!python/tuple + - 30.0 + - 15.0 + stage_step_counts: + - 0 + - 96000 + - 192000 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + sensor_name: feet_ground_contact + velocity_command_name: twist + velocity_command_threshold: 0.1 + weight: 2.1 +terminations: + time_out: + func: !!python/name:mjlab.envs.mdp.terminations.time_out '' + params: {} + time_out: true + fell_over: + func: !!python/name:mjlab.envs.mdp.terminations.bad_orientation '' + params: + limit_angle: 1.2217304763960306 + time_out: false + nan_term: + func: !!python/name:mjlab.envs.mdp.terminations.nan_detection '' + params: {} + time_out: false + base_height: + func: !!python/name:src.tasks.velocity.mdp.rewards.root_height_below_minimum_terrain '' + params: + minimum_height: 0.3 + terrain_sensor_name: pelvis_height_measure + time_out: false +commands: + twist: + resampling_time_range: !!python/tuple + - 3.0 + - 8.0 + debug_vis: true + entity_name: robot + heading_command: false + heading_control_stiffness: 0.5 + rel_standing_envs: 0.05 + rel_heading_envs: 1.0 + rel_world_envs: 0.0 + rel_forward_envs: 0.0 + init_velocity_prob: 0.0 + ranges: + lin_vel_x: !!python/tuple + - 0.0 + - 1.0 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.5 + - 0.5 + heading: null + viz: + z_offset: 1.15 + scale: 0.5 + foothold: + resampling_time_range: !!python/tuple + - 1000000000.0 + - 1000000000.0 + debug_vis: false + entity_name: robot + terrain_sensor_name: terrain_scan + contact_sensor_name: feet_ground_contact + velocity_command_name: twist + foot_site_names: !!python/tuple + - left_foot + - right_foot + gait_period: 0.9 + gait_action_name: gait_freq + nominal_height_m: 0.9 + lateral_inter_foot_m: 0.22 + foot_footprint_m: !!python/tuple + - 0.25 + - 0.1 + search_window_m: !!python/tuple + - 0.6 + - 0.6 + elevation_size_m: !!python/tuple + - 1.8 + - 1.2 + elevation_resolution_m: 0.05 + alpha_pos: 1.0 + alpha_dcm: 0.5 + alpha_steepness: 0.6 + alpha_flatness: 4.0 + alpha_height: 6.0 + alpha_climb_bonus: 1.5 + lateral_pos_weight: 2.5 + max_step_height_m: 0.25 + climb_velocity_threshold: 0.1 + standing_threshold: 0.1 + min_step_height_m: 0.05 + max_step_velocity_m_s: 0.5 + apex_clearance_m: 0.05 + clearance_scale: 0.5 + max_clearance_m: 0.2 + pre_apex_lower_window: 0.05 + pre_apex_upper_window: 0.05 + post_apex_lower_window: 0.1 + post_apex_upper_window: 0.15 + terrain_decision_threshold: 0.1 +curriculum: + terrain_levels: + func: !!python/name:src.tasks.velocity.mdp.curriculums.terrain_levels_vel '' + params: + command_name: twist + command_vel: + func: !!python/name:src.tasks.velocity.mdp.curriculums.commands_vel '' + params: + command_name: twist + velocity_stages: + - step: 0 + lin_vel_x: !!python/tuple + - 0.0 + - 0.5 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.2 + - 0.2 + - step: 120000 + lin_vel_x: !!python/tuple + - 0.0 + - 1.0 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.5 + - 0.5 +metrics: + mean_action_acc: + func: !!python/name:mjlab.envs.mdp.metrics.mean_action_acc '' + params: {} + per_substep: false + reduce: mean +recorders: {} +is_finite_horizon: false +auto_reset: true +scale_rewards_by_dt: true diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/env_cfgs.py b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/env_cfgs.py new file mode 100644 index 0000000000000000000000000000000000000000..29089b5f5af0e3df29b5cbf63f61fd363ef389ab --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/params/env_cfgs.py @@ -0,0 +1,2716 @@ +"""VinRobotics VR-M3 12DOF (lower-body only) velocity environment configurations. + +Self-contained: this module builds the full `ManagerBasedRlEnvCfg` inline +rather than deriving from `src.tasks.velocity.velocity_env_cfg`, so changes +to the shared factory do not silently affect VR-M3 12DOF training. +""" + +import math +from copy import deepcopy +from dataclasses import dataclass, replace +import numpy as np + +import instinct_mj.envs.mdp as instinct_mdp + +# import instinct_mj.tasks.locomotion.mdp as instinct_locomotion_mdp +try: + import instinct_mj.tasks.parkour.mdp as instinct_parkour_mdp +except ImportError: + instinct_parkour_mdp = None # type: ignore[assignment] +from instinct_mj.sensors.noisy_camera import NoisyGroupedRayCasterCameraCfg +from instinct_mj.utils.noise import ( + CropAndResizeCfg, + DepthArtifactNoiseCfg, + DepthContourNoiseCfg, + DepthNormalizationCfg, + DepthSkyArtifactNoiseCfg, + GaussianBlurNoiseCfg, + RangeBasedGaussianNoiseCfg, + StereoTooCloseNoiseCfg, +) +from mjlab.envs import ManagerBasedRlEnvCfg +from mjlab.envs import mdp as envs_mdp +from mjlab.envs.mdp import dr +from mjlab.envs.mdp.actions import JointPositionActionCfg +from mjlab.managers.action_manager import ActionTermCfg +from mjlab.managers.command_manager import CommandTermCfg +from mjlab.managers.curriculum_manager import CurriculumTermCfg +from mjlab.managers.event_manager import EventTermCfg +from mjlab.managers.metrics_manager import MetricsTermCfg +from mjlab.managers.observation_manager import ObservationGroupCfg, ObservationTermCfg +from mjlab.managers.reward_manager import RewardTermCfg +from mjlab.managers.scene_entity_config import SceneEntityCfg +from mjlab.managers.termination_manager import TerminationTermCfg +from mjlab.scene import SceneCfg +from mjlab.sensor import ( + ContactMatch, + ContactSensorCfg, + GridPatternCfg, + ObjRef, + PinholeCameraPatternCfg, + RayCastSensorCfg, +) + +from mjlab.sim import MujocoCfg, SimulationCfg +from mjlab.tasks.velocity.mdp import UniformVelocityCommandCfg +from mjlab.terrains import TerrainEntityCfg, SubTerrainCfg +from mjlab.terrains.config import ROUGH_TERRAINS_CFG +from mjlab.utils.noise import UniformNoiseCfg as Unoise +from mjlab.viewer import ViewerConfig + +import src.tasks.velocity.mdp as mdp +from src.assets.robots import ( + VR_M3_12DOF_ACTION_SCALE, + get_vr_m3_12dof_implicit_actuator_robot_cfg, + vr_m3_12dof_joint_pos_action_scale, + vr_m3_12dof_joint_vel_action_scale, +) +from src.tasks.velocity.terrains.config import PERCEPTIVE_TERRAINS_CFG +from src.envs import MultiCriticManagerBasedRlEnvCfg + +## +# VR-M3 12DOF specific constants +## + +# 12DOF keeps the upper body kinematically but with no actuated joints, so +# `waist_yaw_link` (the torso-equivalent body) is still referenceable. +TORSO_BODY = "waist_yaw_link" + +FOOT_SITES = ("left_foot", "right_foot") +FOOT_LINK_NAMES = ("left_ankle_roll_link", "right_ankle_roll_link") + +# Same foot geometry as the fullbody XML: 10 collision geoms per ankle_roll_link. +FOOT_GEOMS = tuple( + f"{side}_ankle_roll_link_collision_{i}" + for side in ("left", "right") + for i in range(1, 11) +) + +# 12DOF only actuates legs; waist and upper body have no actuators, so the +# pose reward only lists the leg-joint regexes. +POSE_STD_STANDING: dict[str, float] = {".*": 0.05} +POSE_STD_WALKING: dict[str, float] = { + r".*hip_pitch.*": 0.5, + r".*hip_roll.*": 0.15, + r".*hip_yaw.*": 0.15, + r".*knee.*": 0.5, + r".*ankle_pitch.*": 0.15, + r".*ankle_roll.*": 0.1, +} +POSE_STD_RUNNING: dict[str, float] = { + r".*hip_pitch.*": 0.5, + r".*hip_roll.*": 0.25, + r".*hip_yaw.*": 0.25, + r".*knee.*": 0.5, + r".*ankle_pitch.*": 0.25, + r".*ankle_roll.*": 0.1, +} + +GAIT_CYCLE_PERIOD = 0.9 + + +@dataclass +class VelocityEnvCfg(ManagerBasedRlEnvCfg): + def __post_init__(self): + pass + + +def vr_m3_12dof_rough_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF rough terrain velocity configuration.""" + + ## + # Sensors + ## + + feet_ground_cfg = ContactSensorCfg( + name="feet_ground_contact", + primary=ContactMatch( + mode="subtree", + pattern=r"^(left_ankle_roll_link|right_ankle_roll_link)$", + entity="robot", + ), + secondary=ContactMatch(mode="body", pattern="terrain"), + fields=("found", "force"), + reduce="netforce", + num_slots=1, + track_air_time=True, + history_length=4, + ) + self_collision_cfg = ContactSensorCfg( + name="self_collision", + primary=ContactMatch(mode="subtree", pattern="pelvis", entity="robot"), + secondary=ContactMatch(mode="subtree", pattern="pelvis", entity="robot"), + fields=("found", "force"), + reduce="none", + num_slots=1, + history_length=4, + ) + + ## + # Observations + ## + + actor_terms = { + "base_ang_vel": ObservationTermCfg( + func=mdp.builtin_sensor, + scale=0.25, + params={"sensor_name": "robot/imu_ang_vel"}, + noise=Unoise(n_min=-0.25, n_max=0.25), + history_length=5, + flatten_history_dim=True, + ), + "projected_gravity": ObservationTermCfg( + func=mdp.projected_gravity, + noise=Unoise(n_min=-0.05, n_max=0.05), + history_length=5, + flatten_history_dim=True, + ), + "velocity_commands": ObservationTermCfg( + func=mdp.generated_commands, + params={"command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ), + "joint_pos_rel": ObservationTermCfg( + func=mdp.joint_pos_rel, + noise=Unoise(n_min=-0.05, n_max=0.05), + history_length=5, + flatten_history_dim=True, + ), + "joint_vel_rel": ObservationTermCfg( + func=mdp.joint_vel_rel, + scale=0.05, + noise=Unoise(n_min=-1.5, n_max=1.5), + history_length=5, + flatten_history_dim=True, + ), + "last_action": ObservationTermCfg( + func=mdp.last_action, history_length=5, flatten_history_dim=True + ), + "gait_phase": ObservationTermCfg( + func=mdp.phase, + params={"period": GAIT_CYCLE_PERIOD, "command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ), + } + + critic_terms = { + **actor_terms, + "base_lin_vel": ObservationTermCfg( + func=mdp.builtin_sensor, + params={"sensor_name": "robot/imu_lin_vel"}, + history_length=5, + flatten_history_dim=True, + ), + "true_base_velocity": ObservationTermCfg( + func=envs_mdp.base_lin_vel, + history_length=5, + flatten_history_dim=True, + ), + "foot_height": ObservationTermCfg( + func=mdp.foot_height, + params={"asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES)}, + history_length=5, + flatten_history_dim=True, + ), + "foot_air_time": ObservationTermCfg( + func=mdp.foot_air_time, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "foot_contact": ObservationTermCfg( + func=mdp.foot_contact, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "foot_contact_forces": ObservationTermCfg( + func=mdp.foot_contact_forces, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "knee_reference": ObservationTermCfg( + func=mdp.get_desired_knee_angle, + params={ + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "command_name": "twist", + }, + history_length=5, + flatten_history_dim=True, + ), + } + + observations = { + "actor": ObservationGroupCfg( + terms=actor_terms, + concatenate_terms=True, + enable_corruption=True, + # history_length=5, + nan_policy="sanitize", + nan_check_per_term=True, + ), + "critic": ObservationGroupCfg( + terms=critic_terms, + concatenate_terms=True, + enable_corruption=False, + # history_length=5, + nan_policy="sanitize", + nan_check_per_term=True, + ), + } + + ## + # Metrics + ## + + metrics = { + "mean_action_acc": MetricsTermCfg(func=mdp.mean_action_acc), + } + + ## + # Actions + ## + + actions: dict[str, ActionTermCfg] = { + "joint_pos": JointPositionActionCfg( + entity_name="robot", + actuator_names=(".*",), + scale=VR_M3_12DOF_ACTION_SCALE, + use_default_offset=True, + ) + } + + ## + # Commands + ## + + commands: dict[str, CommandTermCfg] = { + "twist": UniformVelocityCommandCfg( + entity_name="robot", + resampling_time_range=(3.0, 8.0), + rel_standing_envs=0.05, + heading_command=False, + heading_control_stiffness=0.5, + debug_vis=True, + ranges=UniformVelocityCommandCfg.Ranges( + lin_vel_x=(-1.0, 2.0), + lin_vel_y=(-1.0, 1.0), + ang_vel_z=(-1.0, 1.0), + heading=None, + ), + ), + } + twist_cmd = commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.viz.z_offset = 1.15 + + ## + # Events + ## + + events = { + "reset_base": EventTermCfg( + func=mdp.reset_root_state_uniform, + mode="reset", + params={ + "pose_range": { + "x": (-0.5, 0.5), + "y": (-0.5, 0.5), + "z": (0.0, 0.0), + "yaw": (-3.14, 3.14), + }, + # "discrete_yaws": [0.0, math.pi / 2, math.pi, -math.pi / 2], # [0.0, math.pi / 2, math.pi, -math.pi / 2], + }, + ), + "reset_robot_joints": EventTermCfg( + func=mdp.reset_joints_by_offset, + mode="reset", + params={ + "position_range": (-0.1, 0.1), + "velocity_range": (-0.5, 0.5), + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + }, + ), + "push_robot": EventTermCfg( + func=mdp.push_by_setting_velocity, + mode="interval", + interval_range_s=(5.0, 6.0), + params={ + "velocity_range": { + "x": (-0.5, 0.5), + "y": (-0.5, 0.5), + "z": (-0.4, 0.4), + "roll": (-0.52, 0.52), + "pitch": (-0.52, 0.52), + "yaw": (-0.78, 0.78), + }, + }, + ), + "foot_friction": EventTermCfg( + mode="startup", + func=dr.geom_friction, + params={ + "asset_cfg": SceneEntityCfg("robot", geom_names=FOOT_GEOMS), + "operation": "abs", + "ranges": (0.3, 1.6), + "shared_random": True, + }, + ), + "encoder_bias": EventTermCfg( + mode="startup", + func=dr.encoder_bias, + params={ + "asset_cfg": SceneEntityCfg("robot"), + "bias_range": (-0.015, 0.015), + }, + ), + "base_com": EventTermCfg( + mode="startup", + func=dr.body_com_offset, + params={ + "asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,)), + "operation": "add", + "ranges": { + 0: (-0.05, 0.05), + 1: (-0.05, 0.05), + 2: (-0.05, 0.05), + }, + }, + ), + "body_com": EventTermCfg( + mode="startup", + func=dr.body_ipos, + params={ + "asset_cfg": SceneEntityCfg( + "robot", body_names=("^(?!waist_yaw_link$).*",) + ), + "operation": "add", + "ranges": { + 0: (-0.03, 0.03), + 1: (-0.03, 0.03), + 2: (-0.03, 0.03), + }, + }, + ), + "base_mass": EventTermCfg( + mode="startup", + func=dr.body_mass, + params={ + "asset_cfg": SceneEntityCfg("robot", body_names=("waist_yaw_link",)), + "operation": "add", + "ranges": (-4.0, 4.0), + }, + ), + "body_mass": EventTermCfg( + mode="startup", + func=dr.body_mass, + params={ + "asset_cfg": SceneEntityCfg( + "robot", body_names=("^(?!waist_yaw_link$).*",) + ), + "operation": "scale", + "ranges": (0.9, 1.1), + }, + ), + "randomize_actuator_gains": EventTermCfg( + func=dr.pd_gains, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "kp_range": (0.7, 1.1), + "kd_range": (0.7, 1.1), + }, + ), + "randomize_joint_limit": EventTermCfg( + mode="startup", + func=dr.joint_limits, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.94, 1.06), + }, + ), + "randomize_joint_stiffness": EventTermCfg( + mode="startup", + func=dr.joint_stiffness, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.7, 1.3), + }, + ), + "randomize_joint_frictionloss": EventTermCfg( + mode="startup", + func=dr.joint_friction, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.1, 1.3), + }, + ), + "randomize_joint_armature": EventTermCfg( + mode="startup", + func=dr.joint_armature, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.2, 5.0), + }, + ), + "randomize_joint_damping": EventTermCfg( + mode="startup", + func=dr.joint_damping, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.7, 1.3), + }, + ), + } + + ## + # Rewards + ## + + rewards = { + "track_linear_velocity": RewardTermCfg( + func=mdp.track_linear_velocity, + weight=2.0, + params={"command_name": "twist", "std": math.sqrt(0.25)}, + ), + "track_angular_velocity": RewardTermCfg( + func=mdp.track_angular_velocity, + weight=2.0, + params={"command_name": "twist", "std": math.sqrt(0.5)}, + ), + "body_orientation_l2": RewardTermCfg( + func=mdp.body_orientation_l2, + weight=-5.0, + params={"asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,))}, + ), + "pose": RewardTermCfg( + func=mdp.variable_posture, + weight=1.0, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), + "command_name": "twist", + "std_standing": POSE_STD_STANDING, + "std_walking": POSE_STD_WALKING, + "std_running": POSE_STD_RUNNING, + "walking_threshold": 0.1, + "running_threshold": 0.7, + }, + ), + "flat_orientation": RewardTermCfg(func=mdp.flat_orientation_l2, weight=-7.0), + "pelvis_orientation_l2": RewardTermCfg( + func=mdp.link_orientation, + weight=-3.0, + params={"asset_cfg": SceneEntityCfg("robot", body_names="pelvis")}, + ), + "joint_deviation_hip": RewardTermCfg( + func=mdp.joint_deviation_square, + weight=-0.1, + params={ + "asset_cfg": SceneEntityCfg( + "robot", + joint_names=(".*_hip_yaw_joint", ".*_hip_roll_joint"), + ) + }, + ), + "ang_vel_xy_l2": RewardTermCfg( + func=mdp.ang_vel_xy_l2, + weight=-0.05, + ), + "dof_torques_l2": RewardTermCfg( + func=mdp.joint_torques_l2, + weight=-1.0e-8, + params={ + "asset_cfg": SceneEntityCfg( + "robot", + joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + ) + }, + ), + "dof_vel_l2": RewardTermCfg( + func=mdp.joint_vel_l2, + weight=-1.0e-8, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + "feet_flat_ori": RewardTermCfg( + func=mdp.feet_orientation_contact, + weight=-0.01, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + }, + ), + "body_ang_vel": RewardTermCfg( + func=mdp.body_angular_velocity_penalty, + weight=-0.05, + params={"asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,))}, + ), + "angular_momentum": RewardTermCfg( + func=mdp.angular_momentum_penalty, + weight=-0.025, + params={"sensor_name": "robot/root_angmom"}, + ), + "is_terminated": RewardTermCfg(func=mdp.is_terminated, weight=-200.0), + "joint_acc_l2": RewardTermCfg(func=mdp.joint_acc_l2, weight=-2.5e-7), + "joint_pos_limits": RewardTermCfg(func=mdp.joint_pos_limits, weight=-5.0), + "action_rate_l2": RewardTermCfg(func=mdp.action_rate_l2, weight=-0.5), + "foot_gait": RewardTermCfg( + func=mdp.feet_gait, + weight=1.0, + params={ + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "threshold": 0.6, + "command_threshold": 0.1, + "command_name": "twist", + "sensor_name": "feet_ground_contact", + }, + ), + "feet_double_support": RewardTermCfg( + func=mdp.feet_double_support, + weight=2.0, + params={ + "sensor_name": "feet_ground_contact", + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "threshold": 0.6, + "command_name": "twist", + "cmd_threshold": 0.1, + "ds_match_weight": 1.0, + }, + ), + "foot_clearance": RewardTermCfg( + func=mdp.feet_clearance, + weight=-1.0, + params={ + "target_height": 0.10, + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES), + }, + ), + "foot_slip": RewardTermCfg( + func=mdp.feet_slip, + weight=-0.25, + params={ + "sensor_name": "feet_ground_contact", + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES), + }, + ), + "feet_close_xy": RewardTermCfg( + func=mdp.feet_close_xy_gauss, + weight=1.0, + params={ + "threshold": 0.2, + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "std": math.sqrt(0.05), + }, + ), + "soft_landing": RewardTermCfg( + func=mdp.soft_landing, + weight=-1e-3, + params={ + "sensor_name": "feet_ground_contact", + "command_name": "twist", + "command_threshold": 0.1, + }, + ), + "dont_wait": RewardTermCfg( + func=mdp.dont_wait, + weight=-0.5, + params={ + "command_name": "twist", + "cmd_threshold": 0.1, + }, + ), + "stand_still": RewardTermCfg( + func=mdp.stand_still, + weight=-1.0, + params={ + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), + }, + ), + "self_collisions": RewardTermCfg( + func=mdp.self_collision_cost, + weight=-1.0, + params={"sensor_name": self_collision_cfg.name, "force_threshold": 10.0}, + ), + "feet_air_time": RewardTermCfg( + func=mdp.feet_air_time, + weight=1.0, + params={ + "sensor_name": "feet_ground_contact", + "threshold": (1.0 - 0.6) * GAIT_CYCLE_PERIOD, # 0.48 s + "command_name": "twist", + "command_threshold": 0.1, + }, + ), + "feet_air_time_biped": RewardTermCfg( + func=mdp.feet_air_time_positive_biped, + weight=1.5, + params={ + "command_name": "twist", + "sensor_name": "feet_ground_contact", + "threshold": 0.52, + }, + ), + } + + ## + # Terminations + ## + + terminations = { + "time_out": TerminationTermCfg(func=mdp.time_out, time_out=True), + "fell_over": TerminationTermCfg( + func=mdp.bad_orientation, + params={"limit_angle": math.radians(70.0)}, + ), + "nan_term": TerminationTermCfg( + func=mdp.nan_detection, + time_out=False, + ), + } + + ## + # Curriculum + ## + + curriculum = { + "terrain_levels": CurriculumTermCfg( + func=mdp.terrain_levels_vel, + params={"command_name": "twist"}, + ), + "command_vel": CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (-0.5, 1.0), + "lin_vel_y": (-0.5, 0.5), + "ang_vel_z": (-0.5, 0.5), + }, + { + "step": 5000 * 24, + "lin_vel_x": (-0.7, 1.5), + "lin_vel_y": (-0.7, 0.7), + "ang_vel_z": (-0.7, 0.7), + }, + { + "step": 7000 * 24, + "lin_vel_x": (-1.0, 2.0), + "lin_vel_y": (-1.0, 1.0), + "ang_vel_z": (-1.0, 1.0), + }, + # { + # "step": 9000 * 24, + # "lin_vel_x": (-1.0, 3.0), + # "lin_vel_y": (-1.0, 1.0), + # "ang_vel_z": (-1.0, 1.0), + # }, + ], + }, + ), + } + + ## + # Scene + terrain + ## + + terrain_generator = replace(ROUGH_TERRAINS_CFG) + terrain_generator.curriculum = True + terrain = TerrainEntityCfg( + terrain_type="generator", + terrain_generator=terrain_generator, + max_init_terrain_level=5, + ) + + scene = SceneCfg( + terrain=terrain, + entities={"robot": get_vr_m3_12dof_implicit_actuator_robot_cfg()}, + sensors=(feet_ground_cfg, self_collision_cfg), + num_envs=1, + extent=2.0, + ) + + ## + # Assemble + ## + + cfg = VelocityEnvCfg( + scene=scene, + observations=observations, + actions=actions, + commands=commands, + events=events, + rewards=rewards, + terminations=terminations, + curriculum=curriculum, + metrics=metrics, + viewer=ViewerConfig( + origin_type=ViewerConfig.OriginType.ASSET_BODY, + entity_name="robot", + body_name=TORSO_BODY, + distance=3.0, + elevation=-5.0, + azimuth=90.0, + ), + sim=SimulationCfg( + # VR-M3 has ~1.4x the foot collision geoms of G1 (10/side vs 7/side); + # rough terrain randomization can push the contact count up, so + # nconmax is raised from G1's 48 to 512. + nconmax=512, + njmax=1500, + contact_sensor_maxmatch=500, + mujoco=MujocoCfg( + timestep=0.005, + iterations=10, + ls_iterations=20, + ccd_iterations=500, + ), + ), + decimation=4, + episode_length_s=20.0, + ) + + # Play mode overrides. + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["actor"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + return cfg + + +def vr_m3_12dof_flat_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF flat terrain velocity configuration.""" + cfg = vr_m3_12dof_rough_env_cfg(play=play) + cfg.rewards.pop("flat_orientation", None) + cfg.rewards.pop("pelvis_orientation_l2", None) + cfg.rewards.pop("joint_deviation_hip", None) + cfg.rewards.pop("ang_vel_xy_l2", None) + cfg.rewards.pop("dof_torques_l2", None) + cfg.rewards.pop("dof_vel_l2", None) + cfg.rewards.pop("feet_flat_ori", None) + # VR-M3 has ~1.4x the foot collision geoms of G1, so njmax needs headroom. + cfg.sim.njmax = 600 + cfg.sim.mujoco.ccd_iterations = 50 + cfg.sim.contact_sensor_maxmatch = 64 + cfg.sim.nconmax = None + + # Switch to flat terrain. + assert cfg.scene.terrain is not None + cfg.scene.terrain.terrain_type = "plane" + cfg.scene.terrain.terrain_generator = None + + # Remove raycast sensor and height scan (no terrain to scan). + cfg.scene.sensors = tuple( + s for s in (cfg.scene.sensors or ()) if s.name != "terrain_scan" + ) + # del cfg.observations["actor"].terms["height_scan"] + # del cfg.observations["critic"].terms["height_scan"] + cfg.observations["actor"].terms.pop("height_scan", None) + cfg.observations["critic"].terms.pop("height_scan", None) + + cfg.curriculum.pop("terrain_levels", None) + + if play: + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (-0.5, 2.0) + twist_cmd.ranges.lin_vel_y = (-0.5, 0.5) + twist_cmd.ranges.ang_vel_z = (-0.5, 0.5) + + return cfg + + +def vr_m3_12dof_perceptive_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF perceptive locomotion configuration with height-map.""" + cfg = vr_m3_12dof_rough_env_cfg(play=play) + + site_names = ("left_foot", "right_foot") + + # Auto-size contact buffers for complex terrain geometry. + cfg.sim.njmax = 700 + cfg.sim.mujoco.ccd_iterations = 500 + cfg.sim.contact_sensor_maxmatch = 500 + cfg.sim.nconmax = 128 + + # Swap terrain generator to perceptive preset (deepcopy to avoid mutation). + assert cfg.scene.terrain is not None + cfg.scene.terrain.terrain_generator = deepcopy(PERCEPTIVE_TERRAINS_CFG) + + if not play: + cfg.scene.terrain.terrain_generator.curriculum = True + + pelvis_height_measure = RayCastSensorCfg( + name="pelvis_height_measure", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=2.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + left_height_scanner = RayCastSensorCfg( + name="left_height_scanner", + frame=ObjRef(type="site", name="left_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=1.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + right_height_scanner = RayCastSensorCfg( + name="right_height_scanner", + frame=ObjRef(type="site", name="right_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=1.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + + # --- Gradient sensors (3x3 grid for foot edge detection) --- + left_foot_gradient = RayCastSensorCfg( + name="left_foot_gradient", + frame=ObjRef(type="site", name="left_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.2, 0.1), + resolution=0.1, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=1.0, + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + right_foot_gradient = RayCastSensorCfg( + name="right_foot_gradient", + frame=ObjRef(type="site", name="right_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.2, 0.1), + resolution=0.1, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=1.0, + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + pelvis_height_measure, + left_height_scanner, + right_height_scanner, + left_foot_gradient, + right_foot_gradient, + ) + + # --- Terrain-aware reward terms --- + cfg.rewards["terrain_foot_clearance"] = RewardTermCfg( + func=mdp.terrain_foot_clearance_cost, + weight=-0.5, + params={ + "target_clearance": 0.06, + "left_terrain_sensor": "left_height_scanner", + "right_terrain_sensor": "right_height_scanner", + "command_name": "twist", + "command_threshold": 0.05, + "asset_cfg": SceneEntityCfg("robot", site_names=site_names), + }, + ) + + cfg.rewards["terrain_stumble"] = RewardTermCfg( + func=mdp.terrain_stumble_cost, + weight=-1.0, + params={ + "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "velocity_threshold": 0.15, + }, + ) + + # cfg.rewards["step_accuracy"] = RewardTermCfg( + # func=custom_mdp.step_accuracy, + # weight=1.0, + # params={ + # "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "patch_name": "target", + # "std": 0.15, + # }, + # ) + + cfg.rewards["terrain_base_height"] = RewardTermCfg( + func=mdp.terrain_base_height_l2_cost, + weight=-1.0, + params={ + "target_height": 0.9, + "base_terrain_sensor": "pelvis_height_measure", + "asset_cfg": SceneEntityCfg("robot"), + }, + ) + + cfg.rewards["foot_edge"] = RewardTermCfg( + func=mdp.foot_edge_cost, + weight=-0.5, + params={ + "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + "left_gradient_sensor": "left_foot_gradient", + "right_gradient_sensor": "right_foot_gradient", + "gradient_threshold": 0.3, + "asset_cfg": SceneEntityCfg("robot", body_names=[r".*ankle_roll.*"]), + }, + ) + + # cfg.rewards["feet_at_plane"] = RewardTermCfg( + # func=parkour_mdp.feet_at_plane, + # weight=-0.1, + # params={ + # "contact_sensor_name": "feet_ground_contact", + # "left_height_scanner_name": "left_height_scanner", # matches your sensor + # "right_height_scanner_name": "right_height_scanner", # matches your sensor + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "height_offset": 0.06, + # }, + # ) + + # --- Terrain-aware termination --- + cfg.terminations["base_height"] = TerminationTermCfg( + func=mdp.root_height_below_minimum_terrain, + params={ + "minimum_height": 0.3, + "terrain_sensor_name": "pelvis_height_measure", + }, + ) + + if play: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + return cfg + + +def vr_m3_12dof_height_map_env_cfg(play: bool = False) -> VelocityEnvCfg: + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(0.6, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + cfg.scene.sensors = cfg.scene.sensors + (terrain_scan,) + + # --- Asymmetric actor-critic observations --- + # Actor: add terrain_scan with noise (proprioception terms inherited from base). + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + # func=custom_mdp.height_scan_custom, + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + noise=Unoise(n_min=-0.1, n_max=0.1), + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic: add terrain_scan (no noise, privileged) and true base velocity. + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + # func=custom_mdp.height_scan_custom, + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + history_length=5, + ) + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 2.5 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -5e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 1.0 + cfg.rewards["feet_double_support"].weight = 2.0 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -0.5 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 1.5 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards["foot_edge"].weight = -0.5 + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["actor"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_depth_map_env_cfg( + play: bool = False, +) -> VelocityEnvCfg: + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(1.8, 1.2), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + depth_camera = NoisyGroupedRayCasterCameraCfg( + name="camera", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + # RealSense depth camera D435 + # Intrinsics from camera_info: fx = fy = 386.56719970703125 at 640x480 + pattern=PinholeCameraPatternCfg( + height=int(480 / 8), + width=int(640 / 8), + fovy=2 + * math.degrees(math.atan(480 / 2 / 386.56719970703125)), # ~63.67 deg + ), + focal_length=1.0, + horizontal_aperture=640.0 / 386.56719970703125, # fovx ~79.24 deg + vertical_aperture=480.0 / 386.56719970703125, # fovy ~63.67 deg + ray_alignment="base", + include_geom_groups=(0, 1, 2), + exclude_parent_body=False, + offset=NoisyGroupedRayCasterCameraCfg.OffsetCfg( + pos=(0.00, 0.018, -0.1), + rot=( + math.cos(math.radians(60) / 2), # w + 0.0, # x + math.sin(math.radians(60) / 2), # y (pitch 60 deg about Y) + 0.0, # z + ), + convention="world", + ), + data_types=["distance_to_image_plane"], + depth_clipping_behavior="max", # clip to the maximum value + mesh_filter_max_hops=24, + noise_pipeline={ + "crop_and_resize": CropAndResizeCfg( + # (top, bottom, left, right), height/2 and centering width/2 + crop_region=(0, 0, 10, 10), + resize_shape=(30, 30), + ), + "gaussian_blur": GaussianBlurNoiseCfg(kernel_size=3, sigma=1), + "depth_normalization": DepthNormalizationCfg( + depth_range=(0.0, 2.5), + normalize=True, + output_range=(0.0, 1.0), + ), + }, + data_histories={"distance_to_image_plane_noised": 17}, + update_period=1 / 30, + min_distance=0.1, + max_distance=2.5, + debug_vis=play, + ) + undesired_contact_cfg = ContactSensorCfg( + name="undesired_contact_forces", + primary=ContactMatch( + mode="body", + pattern=".*", + entity="robot", + exclude=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + fields=("found", "force"), + reduce="netforce", + track_air_time=False, + history_length=3, + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + terrain_scan, + depth_camera, + undesired_contact_cfg, + ) + + cfg.events["randomize_ray_offsets"] = EventTermCfg( + func=instinct_mdp.randomize_ray_offsets, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("camera"), + "offset_pose_ranges": { + "x": (-0.01, 0.01), + "y": (-0.01, 0.01), + "z": (-0.03, 0.01), + "roll": (-math.radians(2), math.radians(2)), + "pitch": (-math.radians(10), math.radians(10)), + "yaw": (-math.radians(2), math.radians(2)), + }, + "distribution": "uniform", + }, + ) + + cfg.observations["actor"].concatenate_terms = False + cfg.observations["critic"].concatenate_terms = False + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + ) + + cfg.observations["actor"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + cfg.observations["critic"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + # Add "policy" alias for actor obs (Instinct runner expects "policy"). + actor_obs_cfg = cfg.observations.pop("actor") + cfg.observations["policy"] = actor_obs_cfg + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 2.0 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards["foot_edge"].weight = -0.5 + + cfg.rewards = { + **cfg.rewards, + "feet_slide": RewardTermCfg( + func=instinct_parkour_mdp.feet_slide, + weight=-0.4, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "threshold": 1.0, + }, + ), + # "joint_deviation_hip": RewardTermCfg( + # func=instinct_mdp.joint_deviation_square, + # weight=-0.3, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_yaw_joint", ".*_hip_roll_joint"), + # ) + # }, + # ), + # "ang_vel_xy_l2": RewardTermCfg( + # func=instinct_parkour_mdp.ang_vel_xy_l2, + # weight=-0.05, + # ), + # "dof_torques_l2": RewardTermCfg( + # func=instinct_parkour_mdp.joint_torques_l2, + # weight=-1.0e-7, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ) + # }, + # ), + # "dof_vel_l2": RewardTermCfg( + # func=envs_mdp.joint_vel_l2, + # weight=-5.0e-7, + # params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + # ), + # "feet_flat_ori": RewardTermCfg( + # func=instinct_parkour_mdp.feet_orientation_contact, + # weight=-0.01, + # params={ + # "sensor_name": "feet_ground_contact", + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # }, + # ), + # "feet_close_xy": RewardTermCfg( + # func=instinct_parkour_mdp.feet_close_xy_gauss, + # weight=1.0, + # params={ + # "threshold": 0.2, + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "std": math.sqrt(0.05), + # }, + # ), + # "energy": RewardTermCfg( + # func=parkour_mdp.rewards.motors_power_square, + # weight=-1.0e-8, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ), + # "normalize_by_stiffness": True, + # }, + # ), + "dof_pos_limits": RewardTermCfg( + func=envs_mdp.joint_pos_limits, + weight=-1.0, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + # "flat_orientation": RewardTermCfg(func=mdp.flat_orientation_l2, weight=-7.0), + # "pelvis_orientation_l2": RewardTermCfg( + # func=instinct_parkour_mdp.link_orientation, + # weight=-3.0, + # params={"asset_cfg": SceneEntityCfg("robot", body_names="pelvis")}, + # ), + } + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["policy"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_foothold_env_cfg(play: bool = False) -> VelocityEnvCfg: + """FastStair Stage 1 — planner-guided pre-training (paper §III-B.3). + + Extends ``vr_m3_12dof_height_map_env_cfg`` with: + + - A 1.8 × 1.2 m elevation map at 5 cm resolution (paper §III-C). + - The DCM-based foothold planner exposed as a ``FootholdCommand``. + - The exponential foothold-tracking reward with weight 0.6 (Table I §III-B.2). + - A privileged ``foothold_target`` observation on the critic. + - Velocity range restricted to the paper's pre-train regime + ``[-0.3, 1.0]`` m/s in x. + - Stage 1 reward weights from Table I. + """ + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(1.8, 1.2), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0,), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + depth_camera = NoisyGroupedRayCasterCameraCfg( + name="camera", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + # RealSense depth camera D435 + # Intrinsics from camera_info: fx = fy = 386.56719970703125 at 640x480 + pattern=PinholeCameraPatternCfg( + height=int(480 / 8), + width=int(640 / 8), + fovy=2 + * math.degrees(math.atan(480 / 2 / 386.56719970703125)), # ~63.67 deg + ), + focal_length=1.0, + horizontal_aperture=640.0 / 386.56719970703125, # fovx ~79.24 deg + vertical_aperture=480.0 / 386.56719970703125, # fovy ~63.67 deg + ray_alignment="base", + include_geom_groups=(0, 1, 2), + exclude_parent_body=False, + # TODO: double check with Offset from URDF + offset=NoisyGroupedRayCasterCameraCfg.OffsetCfg( + pos=(0.00, 0.018, -0.1), + rot=( + math.cos(math.radians(60) / 2), # w + 0.0, # x + math.sin(math.radians(60) / 2), # y (pitch 30 deg about Y) + 0.0, # z + ), + convention="world", + ), + data_types=["distance_to_image_plane"], + depth_clipping_behavior="max", # clip to the maximum value + mesh_filter_max_hops=24, + noise_pipeline={ + "crop_and_resize": CropAndResizeCfg( + # (top, bottom, left, right), height/2 and centering width/2 + crop_region=(0, 0, 10, 10), + resize_shape=(30, 30), + ), + "gaussian_blur": GaussianBlurNoiseCfg(kernel_size=3, sigma=1), + "depth_normalization": DepthNormalizationCfg( + depth_range=(0.0, 2.5), + normalize=True, + output_range=(0.0, 1.0), + ), + }, + data_histories={"distance_to_image_plane_noised": 17}, + update_period=1 / 30, + min_distance=0.1, + max_distance=2.5, + debug_vis=play, + ) + undesired_contact_cfg = ContactSensorCfg( + name="undesired_contact_forces", + primary=ContactMatch( + mode="body", + pattern=".*", + entity="robot", + exclude=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + fields=("found", "force"), + reduce="netforce", + track_air_time=False, + history_length=3, + ) + + cfg.scene.sensors = tuple( + s + for s in (cfg.scene.sensors or ()) + if s.name not in ("left_foot_gradient", "right_foot_gradient") + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + terrain_scan, + depth_camera, + undesired_contact_cfg, + ) + + cfg.events["randomize_ray_offsets"] = EventTermCfg( + func=instinct_mdp.randomize_ray_offsets, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("camera"), + "offset_pose_ranges": { + "x": (-0.01, 0.01), + "y": (-0.01, 0.01), + "z": (-0.03, 0.01), + "roll": (-math.radians(2), math.radians(2)), + "pitch": (-math.radians(10), math.radians(10)), + "yaw": (-math.radians(2), math.radians(2)), + }, + "distribution": "uniform", + }, + ) + + # Foothold command — the planner output. + cfg.commands["foothold"] = mdp.FootholdCommandCfg( + entity_name="robot", + terrain_sensor_name="terrain_scan", + contact_sensor_name="feet_ground_contact", + velocity_command_name="twist", + foot_site_names=FOOT_SITES, + gait_period=GAIT_CYCLE_PERIOD, + nominal_height_m=0.9, + lateral_inter_foot_m=0.22, + foot_footprint_m=(0.25, 0.10), + search_window_m=(0.6, 0.6), + elevation_size_m=(1.8, 1.2), + elevation_resolution_m=0.05, + alpha_pos=1.0, + alpha_dcm=0.5, + # Safety-aware terrain scoring (max-pool steepness + footprint + # flatness + soft height feasibility + climb bonus). See + # ``DCMFootholdPlanner`` docstring for the rationale. + alpha_steepness=0.6, + alpha_flatness=4.0, + alpha_height=6.0, + alpha_climb_bonus=1.5, + lateral_pos_weight=2.5, + max_step_height_m=0.25, + climb_velocity_threshold=0.1, + standing_threshold=0.1, + # Adaptive Bézier clearance: 5 cm base on flat ground, +0.5 m/m of + # step height, capped at 20 cm. + apex_clearance_m=0.05, + clearance_scale=0.5, + max_clearance_m=0.20, + pre_apex_lower_window=0.05, + pre_apex_upper_window=0.05, + post_apex_lower_window=0.1, + post_apex_upper_window=0.15, + terrain_decision_threshold=0.1, + debug_vis=play, + ) + + cfg.observations["actor"].concatenate_terms = False + cfg.observations["critic"].concatenate_terms = False + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + ) + + # Privileged critic observation: planner output (body frame). + cfg.observations["critic"].terms["foothold_target"] = ObservationTermCfg( + func=mdp.foothold_target, + params={"command_name": "foothold"}, + ) + + cfg.observations["actor"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + cfg.observations["critic"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + # add "policy" alias for actor obs for instinct compatibility + actor_obs_cfg = cfg.observations.pop("actor") + cfg.observations["policy"] = actor_obs_cfg + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # Pre-train velocity range (paper §III-B.3). + # twist_cmd = cfg.commands["twist"] + # assert isinstance(twist_cmd, UniformVelocityCommandCfg) + # twist_cmd.ranges = UniformVelocityCommandCfg.Ranges( + # lin_vel_x=(-0.3, 1.0), + # lin_vel_y=(-0.3, 0.3), + # ang_vel_z=(-1.0, 1.0), + # heading=None, + # ) + # twist_cmd.resampling_time_range = (8.0, 12.0) + # cfg.curriculum.pop("command_vel", None) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 2.0 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + # cfg.rewards["foot_edge"].weight = -0.5 + cfg.rewards.pop("foot_edge", None) + + cfg.rewards = { + **cfg.rewards, + "feet_slide": RewardTermCfg( + func=instinct_parkour_mdp.feet_slide, + weight=-0.4, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "threshold": 1.0, + }, + ), + # "energy": RewardTermCfg( + # func=parkour_mdp.rewards.motors_power_square, + # weight=-1.0e-8, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ), + # "normalize_by_stiffness": True, + # }, + # ), + "dof_pos_limits": RewardTermCfg( + func=envs_mdp.joint_pos_limits, + weight=-1.0, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + } + + cfg.rewards["foothold_tracking"] = RewardTermCfg( + func=mdp.foothold_tracking, + weight=2.1, + params={ + "command_name": "foothold", + "sigma_stages": [(10.0, 5.0), (20.0, 10.0), (30.0, 15.0)], + "stage_step_counts": [0, 4_000 * 24, 8_000 * 24], + "asset_cfg": SceneEntityCfg( + "robot", + site_names=FOOT_SITES, + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "sensor_name": "feet_ground_contact", + "velocity_command_name": "twist", + "velocity_command_threshold": 0.1, + # "log_csv_path": "foothold_tracking_rewards.csv" if play else None, + }, + ) + # cfg.rewards["track_linear_velocity"].weight = 1.0 + # if "action_rate_l2" in cfg.rewards: + # cfg.rewards["action_rate_l2"].weight = -2.5e-3 + # if "joint_acc_l2" in cfg.rewards: + # cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + # if "dof_torques_l2" in cfg.rewards: + # cfg.rewards["dof_torques_l2"].weight = -4.0e-7 + # if "dof_vel_l2" in cfg.rewards: + # cfg.rewards["dof_vel_l2"].weight = -2.5e-7 + # if "foot_edge" in cfg.rewards: + # cfg.rewards["foot_edge"].weight = -1.5 + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["policy"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_ga_phl_env_cfg(play: bool = False) -> VelocityEnvCfg: + """GA-PHL perceptive locomotion config for VR-M3 12DOF. + + Implements arXiv:2512.07464 (Gait-Adaptive Perceptive Humanoid Locomotion + with Real-Time Under-Base Terrain Reconstruction): + + - Downward-facing under-base depth camera (§III-E): replaces the 60° forward + camera with a 90° downward camera, covering the critical foot-support region. + - Omnidirectional velocity commands with a 3-stage curriculum (§IV-B). + - Reward weights matched to paper Table I as closely as possible using the + existing reward functions in this codebase. + + Based on ``vr_m3_12dof_foothold_env_cfg`` (inherits foothold planner, terrain + scan, depth image obs, and domain randomisation). Not implemented here because + they require framework-level extensions: + - U-Net height-map reconstruction (separate offline model). + - Successive Teacher-Student runner (runner-level, not env-level). + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_map_as_grid, + params={ + "sensor_name": "terrain_scan", + "miss_value": 2.0, + "use_grid": True, + "num_cols": int((1.8 + 1e-6) / 0.05) + 1, + "num_rows": int((1.2 + 1e-6) / 0.05) + 1, + }, + clip=(0.0, 2.0), + history_length=1, + flatten_history_dim=False, + ) + + cfg.observations["critic"].terms.pop("depth_image") + + cfg.commands["foothold"] = mdp.FootholdCommandCfg( + entity_name="robot", + terrain_sensor_name="terrain_scan", + contact_sensor_name="feet_ground_contact", + velocity_command_name="twist", + foot_site_names=FOOT_SITES, + gait_period="policy", + gait_action_name="gait_freq", + nominal_height_m=0.9, + lateral_inter_foot_m=0.18, + foot_footprint_m=(0.20, 0.10), + search_window_m=(0.6, 0.6), + elevation_size_m=(1.8, 1.2), + elevation_resolution_m=0.05, + alpha_pos=1.0, + alpha_dcm=0.5, + # Safety-aware terrain scoring (max-pool steepness + footprint + # flatness + soft height feasibility + climb bonus). See + # ``DCMFootholdPlanner`` docstring for the rationale. + alpha_steepness=0.6, + alpha_flatness=4.0, + alpha_height=6.0, + alpha_climb_bonus=1.5, + lateral_pos_weight=2.5, + max_step_height_m=0.25, + climb_velocity_threshold=0.1, + standing_threshold=0.1, + # Adaptive Bézier clearance: 5 cm base on flat ground, +0.5 m/m of + # step height, capped at 20 cm. + apex_clearance_m=0.05, + clearance_scale=0.5, + max_clearance_m=0.20, + pre_apex_lower_window=0.05, + pre_apex_upper_window=0.05, + post_apex_lower_window=0.1, + post_apex_upper_window=0.15, + terrain_decision_threshold=0.1, + debug_vis=play, + ) + + cfg.rewards["foothold_tracking"] = RewardTermCfg( + func=mdp.foothold_tracking, + weight=2.0, + params={ + "command_name": "foothold", + "sigma_stages": [(10.0, 5.0), (20.0, 10.0), (30.0, 15.0)], + "stage_step_counts": [0, 4_000 * 24, 8_000 * 24], + "asset_cfg": SceneEntityCfg( + "robot", + site_names=FOOT_SITES, + body_names=FOOT_LINK_NAMES, + ), + "sensor_name": "feet_ground_contact", + "velocity_command_name": "twist", + "velocity_command_threshold": 0.1, + "penalty_scale": 1.0, + # "log_csv_path": "foothold_tracking_rewards.csv" if play else None, + }, + ) + + # Route foot_gait and feet_double_support to the learnable phase φ_t so + # the gait reward is consistent with the policy's own internal clock. + cfg.observations["critic"].terms["knee_reference"].params[ + "action_name" + ] = "gait_freq" + cfg.rewards["foot_gait"].params["action_name"] = "gait_freq" + cfg.rewards["feet_double_support"].params["action_name"] = "gait_freq" + cfg.rewards["feet_air_time"].params["action_name"] = "gait_freq" + + cfg.actions["gait_freq"] = mdp.GaitFrequencyActionCfg( + entity_name="robot", + min_frequency=1.0, + max_frequency=1.5, + smooth_alpha=0.2, + default_frequency=1.2, + ) + + # ── 6. Adaptive gait-phase observation (replaces fixed-period phase obs) ── + # Returns [f_t, sin(2π·φ_t), cos(2π·φ_t)] — 3 scalars instead of 2. + # Both policy and critic groups inherit the same proprioceptive terms. + for group_name in ("policy", "critic"): + cfg.observations[group_name].terms.pop("gait_phase", None) + cfg.observations[group_name].terms["adaptive_gait_phase"] = ObservationTermCfg( + func=mdp.adaptive_gait_phase, + params={"action_name": "gait_freq", "command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ) + + # ── 7. Gait action limit penalty ───────────────────────────────────────── + # Small penalty for pushing f_t outside the valid band (paper §III-C). + cfg.rewards["gait_action_limit"] = RewardTermCfg( + func=mdp.gait_action_limit, + weight=-0.25, + params={"action_name": "gait_freq"}, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 4_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for training --- + # cfg.rewards["step_accuracy"].weight = 1.0 + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # NOT work with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-7 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -2.0 + cfg.rewards["self_collisions"].weight = -2.0 + # cfg.rewards["feet_air_time"].weight = 1.0 + # cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["feet_air_time_biped"].weight = 3.0 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards.pop( + "terrain_foot_clearance", None + ) # Not compatible with heightmap-based foothold planning + cfg.rewards.pop("foot_gait", None) # phase-locked, conflicts with foothold planner + cfg.rewards.pop("feet_double_support", None) # same problem + cfg.rewards.pop( + "feet_air_time", None + ) # Remove air time reward which can conflict with foothold planning + + # Experiment with new foothold penalties + cfg.rewards.pop("foot_edge", None) + cfg.rewards["terrain_stumble"].weight = -1.0 + + return cfg + + +def _create_multi_critic_cfg_from_single_critic( + cfg: VelocityEnvCfg, +) -> MultiCriticManagerBasedRlEnvCfg: + """Helper to copy a single-critic config to multi-critic format.""" + new_cfg = MultiCriticManagerBasedRlEnvCfg( + decimation=cfg.decimation, scene=cfg.scene + ) + new_cfg.observations = deepcopy(cfg.observations) + new_cfg.actions = deepcopy(cfg.actions) + new_cfg.events = deepcopy(cfg.events) + new_cfg.sim = deepcopy(cfg.sim) + new_cfg.viewer = deepcopy(cfg.viewer) + new_cfg.episode_length_s = cfg.episode_length_s + new_cfg.rewards = deepcopy(cfg.rewards) + new_cfg.terminations = deepcopy(cfg.terminations) + new_cfg.commands = deepcopy(cfg.commands) + new_cfg.curriculum = deepcopy(cfg.curriculum) + new_cfg.metrics = deepcopy(cfg.metrics) + new_cfg.is_finite_horizon = cfg.is_finite_horizon + new_cfg.scale_rewards_by_dt = cfg.scale_rewards_by_dt + + return new_cfg + + +def _create_critic_terrain_type_mapping( + cfg: MultiCriticManagerBasedRlEnvCfg, + terrain_type_list: list[str] = ["stair", "gap", "rough"], +): + # Use [stair, gap, rough] or [stair_up, stair_down, gap, rough] as the terrain + # types depending on the sub_terrains defined in the terrain generator config. + # In MJLab curriculum mode, each column is deterministically assigned to one + # sub-terrain by `_generate_curriculum_terrains`: + # sub_index = min(where(col / num_cols + 0.001 < cumsum(proportions))) + # `terrain.terrain_types` stores that column index per env, so to bucket envs + # by terrain category we map column_index -> sub_terrain class -> category. + + if terrain_type_list == ["stair", "gap", "rough"]: + terrain_type_mapping: dict[int, list[int]] = { + 0: [], # stair (both up and down) + 1: [], # gap + 2: [], # rough + } + elif terrain_type_list == ["stair_up", "stair_down", "gap", "rough"]: + terrain_type_mapping: dict[int, list[int]] = { + 0: [], # stair_up + 1: [], # stair_down + 2: [], # gap + 3: [], # rough + } + else: + raise ValueError( + "Unsupported terrain_type_list: {}. Only [stair, gap, rough] or " + "[stair_up, stair_down, gap, rough] are supported.".format( + terrain_type_list + ) + ) + + terrain_generator_cfg = cfg.scene.terrain.terrain_generator + if not terrain_generator_cfg.curriculum: + cfg.scene.terrain.terrain_generator.curriculum = True + + sub_terrains: dict[str, SubTerrainCfg] = terrain_generator_cfg.sub_terrains + sub_terrain_cfgs = list(sub_terrains.values()) + proportions = np.array([s.proportion for s in sub_terrain_cfgs], dtype=np.float64) + proportions /= proportions.sum() + cum_proportions = np.cumsum(proportions) + + num_cols = terrain_generator_cfg.num_cols + for col_idx in range(num_cols): + sub_index = int( + np.min(np.where(col_idx / num_cols + 0.001 < cum_proportions)[0]) + ) + class_name = sub_terrain_cfgs[sub_index].__class__.__name__ + if terrain_type_list == ["stair", "gap", "rough"]: + if "Stair" in class_name or "stair" in class_name: + terrain_type_mapping[0].append(col_idx) + elif "Gap" in class_name or "gap" in class_name: + terrain_type_mapping[1].append(col_idx) + else: + terrain_type_mapping[2].append(col_idx) + elif terrain_type_list == ["stair_up", "stair_down", "gap", "rough"]: + if "Stair" in class_name or "stair" in class_name: + if "BoxOpenStairsTerrainCfg" in class_name: + if sub_terrain_cfgs[sub_index].inverted == False: + terrain_type_mapping[0].append(col_idx) # stair_up + else: + terrain_type_mapping[1].append(col_idx) # stair_down + elif "BoxPyramidStairsTerrainCfg" in class_name: + terrain_type_mapping[0].append(col_idx) # stair_up + elif "BoxInvertedPyramidStairsTerrainCfg" in class_name: + terrain_type_mapping[1].append(col_idx) # stair_down + else: + raise ValueError( + "Unsupported stair type in class_name: {}. Only " + "BoxOpenStairsTerrainCfg, BoxPyramidStairsTerrainCfg, and " + "BoxInvertedPyramidStairsTerrainCfg are supported.".format( + class_name + ) + ) + elif class_name == "BoxSteppingStonesTerrainCfg": + terrain_type_mapping[2].append(col_idx) + else: + terrain_type_mapping[3].append(col_idx) + + # Drop empty buckets and re-index keys to be contiguous 0..N-1, so + # critic_labels emitted by the env line up exactly with critic head indices + # (otherwise the model has to clamp OOB labels, silently mis-routing envs). + non_empty = [v for v in terrain_type_mapping.values() if len(v) > 0] + cfg.critic_terrain_type_mapping = {i: v for i, v in enumerate(non_empty)} + if len(cfg.critic_terrain_type_mapping) == 0: + raise ValueError("No valid terrain types found in sub_terrains.") + if len(cfg.critic_terrain_type_mapping) < 2: + raise ValueError( + "At least 2 terrain types are required for multi-critic training." + ) + cfg.num_critics = len(cfg.critic_terrain_type_mapping) + + +def vr_m3_12dof_foothold_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_foothold_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + return cfg + + +def vr_m3_12dof_foothold_sts_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_foothold_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + cfg.observations["teacher_actor"] = deepcopy(cfg.observations["critic"]) + return cfg + + +def vr_m3_12dof_ga_phl_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_ga_phl_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + return cfg + + +def vr_m3_12dof_ga_phl_sts_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_ga_phl_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + cfg.observations["teacher_actor"] = deepcopy(cfg.observations["critic"]) + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 1 — Asymmetric actor-critic sensors + Band-specific DR +# --------------------------------------------------------------------------- + +# Actor sensor: foreground scan (heightmap_site is 0.5 m ahead of pelvis in the +# pelvis body frame, so the grid covers 0–1 m forward and ±0.3 m lateral). +# GridPatternCfg(size=(0.6, 1.0), resolution=0.05) → 13 cols × 21 rows = 273 rays +_HM_NUM_Y = 21 # actor grid rows (fwd/back, y) +_HM_NUM_X = 13 # actor grid cols (left/right, x) + +# Critic sensor: full surrounding scan centered on the pelvis body. +# GridPatternCfg(size=(1.0, 1.0), resolution=0.05) → 21 cols × 21 rows = 441 rays +_HM_CRITIC_NUM_Y = 21 # critic grid rows +_HM_CRITIC_NUM_X = 21 # critic grid cols + + +def vr_m3_12dof_height_map_dwt_dr_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """Asymmetric actor-critic height-map env with DWT band-specific DR. + + Two separate raycasters replace the shared ``terrain_scan``: + + * **Actor** (``terrain_scan_actor``): foreground patch mounted at + ``heightmap_site`` (0.5 m ahead of pelvis), 0.6 × 1.0 m @ 0.05 m + resolution, ``include_geom_groups=(0, 1, 2)`` so the actor can detect + body geometry (self-collision awareness during foothold selection). + The height observation uses DWT band-specific domain randomisation to + simulate the real-sensor high-frequency dropout at stair edges. + + * **Critic** (``terrain_scan_critic``): full surrounding patch mounted at + the pelvis body origin, 1.0 × 1.0 m @ 0.05 m resolution, + ``include_geom_groups=(0,)`` (terrain only — body geometry does not + pollute privileged height values). The critic additionally receives a + log-scaled DWT energy ratio as a terrain-type signal. + """ + from src.tasks.velocity.mdp.terrain_classifier import terrain_energy_ratio + + cfg = vr_m3_12dof_height_map_env_cfg(play=play) + + # Remove the single shared terrain_scan added by the base height-map cfg. + cfg.scene.sensors = tuple(s for s in cfg.scene.sensors if s.name != "terrain_scan") + + # Actor sensor — foreground, groups 0-2 (terrain + body). + terrain_scan_actor = RayCastSensorCfg( + name="terrain_scan_actor", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(0.6, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + # Critic sensor — full surrounding, group 0 only (terrain, no body). + terrain_scan_critic = RayCastSensorCfg( + name="terrain_scan_critic", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(1.0, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0,), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + cfg.scene.sensors = cfg.scene.sensors + (terrain_scan_actor, terrain_scan_critic) + + # Actor obs: DWT band-specific DR from the foreground sensor. + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_scan_dwt_aug, + params={ + "sensor_name": "terrain_scan_actor", + "num_y": _HM_NUM_Y, + "num_x": _HM_NUM_X, + "miss_value": 2.0, + "sigma_hh": 0.15, + "sigma_lh_hl": 0.05, + "sigma_ll": 0.02, + "attenuation_low": 0.3, + "attenuation_high": 1.0, + }, + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic obs: clean surrounding heightmap (privileged, no noise). + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan_critic", "miss_value": 2.0}, + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic obs: DWT energy ratio from the surrounding scan. + cfg.observations["critic"].terms["terrain_energy_ratio"] = ObservationTermCfg( + func=terrain_energy_ratio, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + history_length=5, + ) + + if play: + cfg.observations["actor"].enable_corruption = False + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 2 — DWT Encoder + Band DR +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_full_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT encoder with band-specific DR (Phase 2). + + Extends ``vr_m3_12dof_height_map_dwt_dr_env_cfg`` for use with + ``InstinctOnPolicyRunner`` + ``EncoderActorCritic`` + ``DWTParallelLayer``: + + - Actor ``height_scan``: ``height_scan_dwt_aug_as_grid`` — returns a 2D + ``[B, num_y, num_x]`` grid with band-specific DR applied, so + ``DWTParallelLayer`` can reshape it to ``[B, 1, H, W]`` for + ``DWTHeadModel``. Band DR (σ_hh=0.15, σ_lh_hl=0.05, σ_ll=0.02) + simulates real-sensor high-frequency dropout. + - ``concatenate_terms=False`` on actor (mixed 2-D/1-D terms). + - ``"policy"`` obs-group alias added for the instinct runner. + - Critic unchanged from DWT-DR (clean flat surrounding scan + energy ratio). + """ + from copy import deepcopy as _dc + + cfg = vr_m3_12dof_height_map_dwt_dr_env_cfg(play=play) + + # Band-DR augmented 2D grid for the DWT encoder. + # Returns [B, num_y, num_x]; concatenate_terms=False avoids mixed-rank + # torch.stack — the instinct encoder system processes each component separately. + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_scan_dwt_aug_as_grid, + params={ + "sensor_name": "terrain_scan_actor", + "num_y": _HM_NUM_Y, + "num_x": _HM_NUM_X, + "miss_value": 2.0, + "sigma_hh": 0.15, + "sigma_lh_hl": 0.05, + "sigma_ll": 0.02, + "attenuation_low": 0.3, + "attenuation_high": 1.0, + }, + clip=(0.0, 2.0), + ) + cfg.observations["actor"].concatenate_terms = False + + # "policy" alias for instinct runner (policy_observation_group="policy"). + cfg.observations["policy"] = _dc(cfg.observations["actor"]) + + if play: + cfg.observations["actor"].enable_corruption = False + cfg.observations["policy"].enable_corruption = False + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 3 — Lightweight Obs & Reward Shaping +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_dr_v2_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT-DR v2: Phase 3 observations and reward terms added to the DWT-DR env. + + Builds on ``vr_m3_12dof_height_map_dwt_dr_env_cfg`` with zero architecture + changes. New critic observations (subband energy map, DWT entropy, cross-band + coherence) give the value function richer terrain-type signals at essentially + zero overhead. Both actor and critic gain a richer velocity representation. + Two DWT-based reward terms encourage action smoothness and gait symmetry. + + New critic obs: + * ``subband_energy_map`` — 4-channel squared energy of DWT subbands + * ``dwt_terrain_entropy`` — Shannon entropy of DWT coefficients [B, 1] + * ``dwt_subband_coherence`` — cross-band (LH/HH, HL/HH) coherence [B, 2] + + New actor+critic obs: + * ``base_lin_vel`` replaced by ``base_velocity_dwt_filtered`` [B, 4] + (vel_x, vel_y, vel_z, speed_xy) + + New rewards (both registered with weight=-1.0 — functions return positive): + * ``dwt_action_smoothness`` — penalise high-freq detail energy in actions + * ``dwt_gait_symmetry`` — penalise L/R joint oscillation asymmetry + """ + from src.tasks.velocity.mdp.terrain_classifier import ( + dwt_terrain_entropy, + dwt_subband_coherence, + ) + + cfg = vr_m3_12dof_height_map_dwt_dr_env_cfg(play=play) + + # -- Critic obs: subband energy map (4 × H' × W' flattened) -- + cfg.observations["critic"].terms["subband_energy_map"] = ObservationTermCfg( + func=mdp.subband_energy_map, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic obs: DWT coefficient entropy -- + cfg.observations["critic"].terms["dwt_terrain_entropy"] = ObservationTermCfg( + func=dwt_terrain_entropy, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic obs: cross-band coherence [B, 2] -- + cfg.observations["critic"].terms["dwt_subband_coherence"] = ObservationTermCfg( + func=dwt_subband_coherence, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic: augment base_lin_vel with speed_xy for richer velocity signal [B, 4] -- + # Actor has no linear velocity term (not available from real-robot sensors); + # only the critic gets this privileged signal during training. + cfg.observations["critic"].terms["base_lin_vel"] = ObservationTermCfg( + func=mdp.base_velocity_dwt_filtered, + params={"asset_cfg": SceneEntityCfg("robot")}, + ) + + # -- DWT action smoothness penalty (positive metric, negative weight in cfg) -- + cfg.rewards["dwt_action_smoothness"] = RewardTermCfg( + func=mdp.dwt_action_smoothness, + params={"action_name": "joint_pos", "lambda_hf": 0.01}, + weight=-1.0, + ) + + # -- DWT gait symmetry penalty (positive metric, negative weight in cfg) -- + cfg.rewards["dwt_gait_symmetry"] = RewardTermCfg( + func=mdp.dwt_gait_symmetry, + params={ + "left_cfg": SceneEntityCfg("robot", joint_names=r"left_.*"), + "right_cfg": SceneEntityCfg("robot", joint_names=r"right_.*"), + "lambda_sym": 0.01, + }, + weight=-1.0, + ) + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 4 — 1D Temporal DWT for Proprioceptive Signals +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_proprioceptive_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 4: temporal DWT obs for proprioceptive signals on top of DWT-DR-v2. + + Builds on ``vr_m3_12dof_height_map_dwt_dr_v2_env_cfg`` with zero architecture + and no history_length changes. Adds four new obs terms and one new reward: + + New **actor** obs (deployable — no privileged sensors): + * ``imu_dwt_filtered`` [B, 12] — DWT slow-trend + noise-energy of IMU history + * ``joint_history_dwt`` [B, 48] — DWT slow-trend + fast-transient energy of joint history + + New **critic** obs (privileged / training-only): + * ``grf_dwt_features`` [B, 12] — contact onset-sharpness from foot-force history + + New reward (register with weight=-1.0 to penalise oscillatory GRF): + * ``dwt_contact_quality`` — level-1 DWT HF energy in normal GRF + + All DWT terms use level=1 with the existing history_length=5, which satisfies + the Db4 minimum signal length (T>=4). Increase history_length and level to 2 + (requires T>=5 at level 1 and T>=9 for the level-2 recursion) for finer + frequency resolution. + """ + cfg = vr_m3_12dof_height_map_dwt_dr_v2_env_cfg(play=play) + + # -- Actor obs: DWT-compressed IMU (angular velocity + projected gravity) -- + # base_ang_vel and projected_gravity are already in actor_terms (h=5) and + # will be processed BEFORE this term in the obs group dict, populating their + # history buffers before imu_dwt_filtered reads them. + cfg.observations["actor"].terms["imu_dwt_filtered"] = ObservationTermCfg( + func=mdp.imu_dwt_filtered, + params={"obs_group": "actor", "level": 1}, + ) + + # -- Actor obs: DWT-compressed joint history (position + velocity) -- + cfg.observations["actor"].terms["joint_history_dwt"] = ObservationTermCfg( + func=mdp.joint_history_dwt, + params={"obs_group": "actor", "level": 1}, + ) + + # -- Critic obs: GRF onset-sharpness (critic-only; not deployable) -- + # foot_contact_forces is already in critic_terms (h=5); grf_dwt_features + # is appended AFTER it so the buffer is already updated when this runs. + cfg.observations["critic"].terms["grf_dwt_features"] = ObservationTermCfg( + func=mdp.grf_dwt_features, + params={"obs_group": "critic", "level": 1}, + ) + + # -- Reward: penalise oscillatory GRF (smooth, controlled foot placement) -- + cfg.rewards["dwt_contact_quality"] = RewardTermCfg( + func=mdp.dwt_contact_quality_reward, + params={"sensor_name": "feet_ground_contact", "lambda_quality": 0.005}, + weight=-1.0, + ) + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 5 — Depth Image DWT Encoder +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_depth_map_dwt_enc_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 5: depth map task using DepthDWTHeadModel encoder. + + Observation pipeline is identical to ``vr_m3_12dof_depth_map_env_cfg``. + The DWT encoding happens entirely in the network (``DWTParallelLayer`` + + ``DepthDWTHeadModel`` configured in ``vr_m3_12dof_depth_map_dwt_enc_rl_cfg``). + + Adds ``depth_obstacle_channel`` [B, 225] to the policy obs group as a + pre-computed DWT-based obstacle proximity feature (edge energy × inv-depth). + """ + cfg = vr_m3_12dof_depth_map_env_cfg(play=play) + + cfg.observations["policy"].terms["depth_obstacle_channel"] = ObservationTermCfg( + func=mdp.depth_obstacle_channel, + params={ + "sensor_cfg": SceneEntityCfg("camera"), + "image_h": 30, + "image_w": 30, + "data_type": "distance_to_image_plane_noised", + }, + noise=None, + ) + + return cfg + + +def vr_m3_12dof_foothold_depth_map_dwt_enc_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 5 variant on the foothold base: DepthDWTHeadModel encoder + foothold planner. + + Inherits from ``vr_m3_12dof_foothold_env_cfg`` which already provides the depth + camera, "policy" obs alias, DCM foothold command, and foothold rewards. + + Adds ``depth_obstacle_channel`` [B, 225] to the policy obs group. + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["policy"].terms["depth_obstacle_channel"] = ObservationTermCfg( + func=mdp.depth_obstacle_channel, + params={ + "sensor_cfg": SceneEntityCfg("camera"), + "image_h": 30, + "image_w": 30, + "data_type": "distance_to_image_plane_noised", + }, + noise=None, + ) + + return cfg + +def vr_m3_12dof_foothold_fdf_env_cfg( + play: bool = False, + mask_fraction: float = 0.7, +) -> MultiCriticManagerBasedRlEnvCfg: + """Foothold task with Frequency-Domain Filtering (FDF) on the depth image. + + Replaces the raw delayed depth-image term from ``vr_m3_12dof_foothold_env_cfg`` + with an FFT-based low-pass filtered version (``mdp.depth_image_fft_lowpass_cls``): + a 2D FFT is applied per frame and the outer ``mask_fraction`` of the frequency + spectrum (by radial distance from the DC bin) is zeroed before reconstructing via + inverse FFT. A higher ``mask_fraction`` removes more high-frequency terrain/ + obstacle detail, simulating a lower-bandwidth depth sensor. + + To sweep masking strength (e.g. 0.1 / 0.3 / 0.5 / 0.7), edit this default. + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["actor"] = cfg.observations.pop("policy") + + for group in ("actor", "critic"): + base_term = cfg.observations[group].terms["depth_image"] + cfg.observations[group].terms["depth_image"] = replace( + base_term, + func=mdp.depth_image_fft_lowpass_cls(), + params={**base_term.params, "mask_fraction": mask_fraction}, + ) + + return cfg diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/policy.onnx b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/policy.onnx new file mode 100644 index 0000000000000000000000000000000000000000..c70920d4480bceeedbc5db3d9816e0a552a3ae57 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-08-40_vr_m3_12dof_dwt_foothold/policy.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:541d6fb20373065a57b0ee9d4dcc1ce29cf74622705b455ce09c97d58695af7b +size 18840693 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560227.worker-4.1992129.0 b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560227.worker-4.1992129.0 new file mode 100644 index 0000000000000000000000000000000000000000..a4e5c7108c9ea7f3edd781a09464261270f97b35 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560227.worker-4.1992129.0 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d6bd17f96e6d429fee2bbd714ed2f5073c3b7c470c57b16df4ef84d91b20dc3 +size 65742324 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff new file mode 100644 index 0000000000000000000000000000000000000000..c1a5fc4b7ed94f67a9b8a839c7d5bd06be68dd23 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff @@ -0,0 +1,30 @@ +--- git commit --- +59c3c413a30c0a375f2365e7f02a02e5023b9634 + + +--- git status --- +On branch dev/fdf +Your branch is up to date with 'origin/dev/fdf'. + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: src/tasks/velocity/config/vr_m3_12dof/__init__.py + +no changes added to commit (use "git add" and/or "git commit -a") + + +--- git diff --- +diff --git a/src/tasks/velocity/config/vr_m3_12dof/__init__.py b/src/tasks/velocity/config/vr_m3_12dof/__init__.py +index a6e8d27..3895578 100644 +--- a/src/tasks/velocity/config/vr_m3_12dof/__init__.py ++++ b/src/tasks/velocity/config/vr_m3_12dof/__init__.py +@@ -203,7 +203,7 @@ except (AttributeError, ImportError): + # Frequency Domain Filtering + register_mjlab_task( + task_id="VR-M3-12DOF-Foothold-FDF", +- env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(), ++ env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(mask_fraction=0.5), + play_env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(play=True), + rl_cfg=vr_m3_12dof_foothold_fdf_vr_rsl_rl_runner_cfg(), + runner_cls=VelocityOnPolicyRunner, \ No newline at end of file diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff new file mode 100644 index 0000000000000000000000000000000000000000..7d752229105146469e937c736f4169b4e7cde8e5 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff @@ -0,0 +1,12 @@ +--- git commit --- +13b0b308e7cd73f7d4188a8a3cde9a98db717e0f + + +--- git status --- +On branch main +Your branch is up to date with 'origin/main'. + +nothing to commit, working tree clean + + +--- git diff --- diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_0.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_0.pt new file mode 100644 index 0000000000000000000000000000000000000000..4673723d74a4389f5a6ca4c820b6bc6fa6ac4928 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_0.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:343ad68d3d7505fba570e204906fbfc3c4f85d706dffe4e8d20f43dddc5adb02 +size 125693797 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_1000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_1000.pt new file mode 100644 index 0000000000000000000000000000000000000000..6dc1ea93c3ea9c5c9eebe545cbe435835e79a02f --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_1000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea000f9e4b7f5e9be73712490969d12e7853c5d7cd50bc45a127873677e56bb1 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_10000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_10000.pt new file mode 100644 index 0000000000000000000000000000000000000000..fc3f5cd86a5b13287077cd9d153e97765f01b452 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_10000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:990fbf1925f88d5f2babb8877f564d9936844fdeef1fb00ca9393498e578d96d +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_11000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_11000.pt new file mode 100644 index 0000000000000000000000000000000000000000..377b4e66741427d1b95db2f249f826ff8bc8907a --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_11000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cdf74dc26d20d9f19831dca5e147a322cd3270ca968775a65468e6b46762e87 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_12000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_12000.pt new file mode 100644 index 0000000000000000000000000000000000000000..ae99de085f98a848b9df1ae55a95ab47f88a836a --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_12000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c533cca289131a69ac3c50efdfb953318dad8454b515837714f29ddbaf9e0eb4 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_13000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_13000.pt new file mode 100644 index 0000000000000000000000000000000000000000..58684733f832028998ef84689af308eccd12dfbb --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_13000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa8926fc24eb4448b870df15c9a2a2d723e68f8f1e3d03e21253593790014c27 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_14000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_14000.pt new file mode 100644 index 0000000000000000000000000000000000000000..59230b07aad152d9b5422806d45543e711578014 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_14000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0c66e29f6c8af7273e404a94b8bd1e73b73ae040a578c37f568ab274478d0b8 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_15000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_15000.pt new file mode 100644 index 0000000000000000000000000000000000000000..6a58c70978edbd71d779717969a5520d46ed7409 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_15000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:855cf9c958210230b2213dafa7ea3735e0d4decda3130de244dd5b2cb1627485 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_2000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_2000.pt new file mode 100644 index 0000000000000000000000000000000000000000..160ad1cb3e4a933e644113f7eb32e863bbccaa29 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_2000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61e8b637d92ab211b48fdd4d93e72be52d4ede74003970a079fd5ec30b6db90e +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_3000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_3000.pt new file mode 100644 index 0000000000000000000000000000000000000000..9817aa41fd1e04fe353f45504886f2daab1f11d1 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_3000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9acea881ec3df4ad886589c82c02bc5b2927ca3fe21ccb212e0a085ae082e075 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_4000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_4000.pt new file mode 100644 index 0000000000000000000000000000000000000000..249308acdf45278fc3089c5cdcd85254e293c86d --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_4000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0494cc341e0229ec1926fa7b6df1f6b0476ce97646d2d421fce0d15da2c1e52b +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_5000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_5000.pt new file mode 100644 index 0000000000000000000000000000000000000000..ac9c19403a9878dd60827d102e5398c499c68aac --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_5000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0432d3b3e06285079e9f2b6b4a26cf95d05ee5faaeec041bd2539a679d534fdf +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_6000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_6000.pt new file mode 100644 index 0000000000000000000000000000000000000000..47e34aba00308c8cbe7c1a4fa0158e75298a8358 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_6000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0460881914612b35e6b91c8292237225dfdf384b44688ed68d55fc64c6c3678 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_7000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_7000.pt new file mode 100644 index 0000000000000000000000000000000000000000..d971629972f19dc996a848b360f47ed32cb510dc --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_7000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d303fe6c3385ee0e24d82c5db96ad54c8c6423b51a00d96edfc7dd8e73049b0e +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_8000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_8000.pt new file mode 100644 index 0000000000000000000000000000000000000000..700a758717286249d65a0baf93176d825468f69d --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_8000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f446be905dbb03e3410c83cf861fcc62684ba4a089ce3b2756ab5d44a4e0416 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_9000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_9000.pt new file mode 100644 index 0000000000000000000000000000000000000000..e0dd8ae78925e622758c4b437efff95863831e5a --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/model_9000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:469612ace2e04c7a6f7bd0bbf3b65d13a52ab1e1a5108a2d75dd520a0f7b9b14 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/agent.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/agent.yaml new file mode 100644 index 0000000000000000000000000000000000000000..aa9b9f4a68d6235397146bc0edd8227bbcb7d230 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/agent.yaml @@ -0,0 +1,139 @@ +seed: 42 +num_steps_per_env: 24 +max_iterations: 100001 +obs_groups: + actor: + - base_ang_vel + - projected_gravity + - velocity_commands + - joint_pos_rel + - joint_vel_rel + - last_action + - gait_phase + - depth_image + critic: + - base_ang_vel + - projected_gravity + - velocity_commands + - joint_pos_rel + - joint_vel_rel + - last_action + - gait_phase + - base_lin_vel + - true_base_velocity + - foot_height + - foot_air_time + - foot_contact + - foot_contact_forces + - knee_reference + - height_scan + - foothold_target + - depth_image +save_interval: 1000 +experiment_name: vr_m3_12dof_dwt_foothold +run_name: vr_m3_12dof_dwt_foothold +logger: wandb +wandb_project: vr_m3_12dof +wandb_tags: !!python/tuple [] +resume: false +load_run: .* +load_checkpoint: model_.*.pt +clip_actions: null +upload_model: true +class_name: OnPolicyRunner +actor: + hidden_dims: !!python/tuple + - 1024 + - 512 + - 256 + - 128 + activation: elu + obs_normalization: true + cnn_cfg: + output_channels: !!python/tuple + - 32 + - 32 + kernel_size: !!python/tuple + - 3 + - 3 + stride: !!python/tuple + - 1 + - 1 + dilation: !!python/tuple + - 1 + - 1 + padding: 1 + padding_mode: replicate + norm: none + activation: relu + max_pool: false + max_pool_kernel_size: 3 + max_pool_stride: 2 + max_pool_padding: 0 + global_pool: none + head_output_dim: 64 + head_hidden_dims: + - 128 + - 64 + head_activation: relu + head_last_activation: relu + distribution_cfg: + init_std: 1.0 + std_type: scalar +critic: + hidden_dims: !!python/tuple + - 1024 + - 512 + - 256 + - 128 + activation: elu + obs_normalization: true + cnn_cfg: + output_channels: !!python/tuple + - 32 + - 32 + kernel_size: !!python/tuple + - 3 + - 3 + stride: !!python/tuple + - 1 + - 1 + dilation: !!python/tuple + - 1 + - 1 + padding: 1 + padding_mode: replicate + norm: none + activation: relu + max_pool: false + max_pool_kernel_size: 3 + max_pool_stride: 2 + max_pool_padding: 0 + global_pool: none + head_output_dim: 64 + head_hidden_dims: + - 128 + - 64 + head_activation: relu + head_last_activation: relu + distribution_cfg: + init_std: 1.0 + std_type: scalar +algorithm: + num_learning_epochs: 5 + num_mini_batches: 4 + learning_rate: 0.001 + schedule: adaptive + gamma: 0.99 + lam: 0.95 + entropy_coef: 0.005 + desired_kl: 0.01 + max_grad_norm: 1.0 + value_loss_coef: 1.0 + use_clipped_value_loss: true + clip_param: 0.2 + normalize_advantage_per_mini_batch: false + optimizer: adam + rnd_cfg: null + symmetry_cfg: null +multi_gpu: null diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/deploy.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/deploy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..00688c1b56e85526218711c9461faba9d7830f7c --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/deploy.yaml @@ -0,0 +1,93 @@ +joint_name: [left_hip_pitch_joint, left_hip_roll_joint, left_hip_yaw_joint, left_knee_pitch_joint, + left_ankle_pitch_joint, left_ankle_roll_joint, right_hip_pitch_joint, right_hip_roll_joint, + right_hip_yaw_joint, right_knee_pitch_joint, right_ankle_pitch_joint, right_ankle_roll_joint] +joint_ids_map: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] +step_dt: 0.02 +stiffness: [150.0, 150.0, 120.0, 200.0, 200.0, 200.0, 150.0, 150.0, 120.0, 200.0, + 200.0, 200.0] +damping: [25.0, 25.0, 4.0, 10.0, 8.0, 8.0, 25.0, 25.0, 4.0, 10.0, 8.0, 8.0] +default_joint_pos: [-0.1, 0.0, 0.0, 0.2, -0.1, 0.0, -0.1, 0.0, 0.0, 0.2, -0.1, 0.0] +commands: + twist: + ranges: + lin_vel_x: [0.0, 1.0] + lin_vel_y: [0.0, 0.0] + ang_vel_z: [-0.5, 0.5] + heading: null +actions: + JointPositionAction: + clip: null + scale: [0.6, 0.6, 0.271, 0.45, 0.15, 0.15, 0.6, 0.6, 0.271, 0.45, 0.15, 0.15] + offset: [-0.1, 0.0, 0.0, 0.2, -0.1, 0.0, -0.1, 0.0, 0.0, 0.2, -0.1, 0.0] + joint_names: [.*] + joint_ids: null +observations: + base_ang_vel: + params: {sensor_name: robot/imu_ang_vel} + clip: null + scale: [0.25, 0.25, 0.25] + history_length: 5 + projected_gravity: + params: {} + clip: null + scale: [1.0, 1.0, 1.0] + history_length: 5 + velocity_commands: + params: {command_name: twist} + clip: null + scale: [1.0, 1.0, 1.0] + history_length: 5 + joint_pos_rel: + params: {} + clip: null + scale: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + history_length: 5 + joint_vel_rel: + params: {} + clip: null + scale: [0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05] + history_length: 5 + last_action: + params: {} + clip: null + scale: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + history_length: 5 + gait_phase: + params: {period: 0.9, command_name: twist} + clip: null + scale: [1.0, 1.0] + history_length: 5 + depth_image: + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice [null, null, null] + body_names: null + body_ids: !!python/object/apply:builtins.slice [null, null, null] + geom_names: null + geom_ids: !!python/object/apply:builtins.slice [null, null, null] + site_names: null + site_ids: !!python/object/apply:builtins.slice [null, null, null] + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice [null, null, null] + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice [null, null, null] + camera_names: null + camera_ids: !!python/object/apply:builtins.slice [null, null, null] + light_names: null + light_ids: !!python/object/apply:builtins.slice [null, null, null] + material_names: null + material_ids: !!python/object/apply:builtins.slice [null, null, null] + pair_names: null + pair_ids: !!python/object/apply:builtins.slice [null, null, null] + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: [0, 1] + debug_vis: false + mask_fraction: 0.5 + clip: null + scale: [1.0, 1.0, 1.0, 1.0] + history_length: 1 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/env.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/env.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5e9facaa301598562c00e57067b0b6c81424487e --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/env.yaml @@ -0,0 +1,3768 @@ +decimation: 4 +scene: + num_envs: 1024 + env_spacing: 2.0 + terrain: + init_state: + pos: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + rot: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.0 + lin_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + ang_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + joint_pos: + .*: 0.0 + joint_vel: + .*: 0.0 + spec_fn: !!python/name:mjlab.entity.entity.%3Clambda%3E '' + articulation: null + sort_actuators: false + lights: !!python/tuple + - name: sun + body: world + mode: fixed + target: null + type: directional + castshadow: true + pos: !!python/tuple + - 0.0 + - 0.0 + - 1.5 + dir: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + cutoff: 45.0 + exponent: 10.0 + cameras: !!python/tuple [] + textures: !!python/tuple + - name: groundplane + type: 2d + builtin: checker + rgb1: !!python/tuple + - 0.2 + - 0.3 + - 0.4 + rgb2: !!python/tuple + - 0.1 + - 0.2 + - 0.3 + width: 300 + height: 300 + mark: edge + markrgb: !!python/tuple + - 0.8 + - 0.8 + - 0.8 + materials: !!python/tuple + - name: groundplane + rgba: !!python/tuple + - 1.0 + - 1.0 + - 1.0 + - 1.0 + texuniform: true + texrepeat: !!python/tuple + - 4.0 + - 4.0 + reflectance: 0.2 + texture: groundplane + geom_names_expr: !!python/tuple + - terrain$ + collisions: !!python/tuple [] + terrain_type: generator + terrain_generator: + seed: null + curriculum: true + size: !!python/tuple + - 8.0 + - 8.0 + border_width: 1.0 + border_height: 1.0 + num_rows: 10 + num_cols: 14 + color_scheme: height + sub_terrains: + flat: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + pyramid_stairs: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.3 + platform_width: 3.0 + holes: false + pyramid_stairs_med: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.45 + platform_width: 3.0 + holes: false + pyramid_stairs_wide: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.6 + platform_width: 3.0 + holes: false + pyramid_stairs_inv: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.3 + platform_width: 3.0 + holes: false + pyramid_stairs_inv_med: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.45 + platform_width: 3.0 + holes: false + pyramid_stairs_inv_wide: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.6 + platform_width: 3.0 + holes: false + open_stairs_pyramid: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width_range: !!python/tuple + - 0.3 + - 0.6 + platform_width: 3.0 + border_width: 1.0 + step_thickness: 0.05 + inverted: false + open_stairs_bowl: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width_range: !!python/tuple + - 0.3 + - 0.6 + platform_width: 3.0 + border_width: 1.0 + step_thickness: 0.05 + inverted: true + hf_pyramid_slope: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + slope_range: !!python/tuple + - 0.0 + - 0.4 + platform_width: 2.0 + inverted: false + border_width: 0.25 + horizontal_scale: 0.2 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + hf_pyramid_slope_inv: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + slope_range: !!python/tuple + - 0.0 + - 0.4 + platform_width: 2.0 + inverted: true + border_width: 0.25 + horizontal_scale: 0.2 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + stepping_stones: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 30 + patch_radius: 0.2 + max_height_diff: 0.03 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + stone_size_range: !!python/tuple + - 0.4 + - 0.8 + stone_distance_range: !!python/tuple + - 0.2 + - 0.5 + stone_height: 0.2 + stone_height_variation: 0.05 + stone_size_variation: 0.1 + floor_depth: 2.0 + displacement_range: 0.1 + platform_width: 1.0 + border_width: 0.0 + uniform_noise: + proportion: 0.15 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + noise_range: !!python/tuple + - 0.02 + - 0.1 + noise_step: 0.02 + downsampled_scale: null + horizontal_scale: 0.1 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + border_width: 0.25 + difficulty_range: !!python/tuple + - 0.0 + - 1.0 + add_lights: true + env_spacing: 2.0 + max_init_terrain_level: 5 + num_envs: 1024 + entities: + robot: + init_state: + pos: !!python/tuple + - 0 + - 0 + - 0.9 + rot: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.0 + lin_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + ang_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + joint_pos: + .*_hip_pitch_joint: -0.1 + .*_hip_roll_joint: 0.0 + .*_hip_yaw_joint: 0.0 + .*_knee_pitch_joint: 0.2 + .*_ankle_pitch_joint: -0.1 + .*_ankle_roll_joint: 0.0 + joint_vel: + .*: 0.0 + spec_fn: !!python/name:src.assets.robots.vr_m3.vr_m3_12dof_constants.get_spec '' + articulation: + actuators: !!python/tuple + - target_names_expr: !!python/tuple + - .*_hip_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 150.0 + damping: 25.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_hip_roll_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 150.0 + damping: 25.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_hip_yaw_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.02864 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 120.0 + damping: 4.0 + effort_limit: 130.0 + - target_names_expr: !!python/tuple + - .*_knee_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 10.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_ankle_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.03006 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 8.0 + effort_limit: 120.0 + - target_names_expr: !!python/tuple + - .*_ankle_roll_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.03006 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 8.0 + effort_limit: 120.0 + soft_joint_pos_limit_factor: 0.9 + sort_actuators: false + lights: !!python/tuple [] + cameras: !!python/tuple [] + textures: !!python/tuple [] + materials: !!python/tuple [] + collisions: !!python/tuple + - geom_names_expr: !!python/tuple + - .*_collision_\d+ + contype: 1 + conaffinity: 1 + condim: + ^(left|right)_ankle_roll_link_collision_\d+$: 3 + .*_collision_\d+: 1 + priority: + ^(left|right)_ankle_roll_link_collision_\d+$: 1 + friction: + ^(left|right)_ankle_roll_link_collision_\d+$: !!python/tuple + - 0.6 + solref: null + solimp: null + margin: null + gap: null + solmix: null + disable_other_geoms: true + sensors: !!python/tuple + - name: feet_ground_contact + primary: + mode: subtree + pattern: ^(left_ankle_roll_link|right_ankle_roll_link)$ + entity: robot + exclude: !!python/tuple [] + secondary: + mode: body + pattern: terrain + entity: null + exclude: !!python/tuple [] + fields: !!python/tuple + - found + - force + reduce: netforce + num_slots: 1 + secondary_policy: first + track_air_time: true + global_frame: false + history_length: 4 + debug: false + - name: self_collision + primary: + mode: subtree + pattern: pelvis + entity: robot + exclude: !!python/tuple [] + secondary: + mode: subtree + pattern: pelvis + entity: robot + exclude: !!python/tuple [] + fields: !!python/tuple + - found + - force + reduce: none + num_slots: 1 + secondary_policy: first + track_air_time: false + global_frame: false + history_length: 4 + debug: false + - name: pelvis_height_measure + frame: + type: body + name: pelvis + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 2.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: left_height_scanner + frame: + type: site + name: left_foot + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 1.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: right_height_scanner + frame: + type: site + name: right_foot + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 1.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: terrain_scan + frame: + type: body + name: pelvis + entity: robot + pattern: + size: !!python/tuple + - 1.8 + - 1.2 + resolution: 0.05 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 2.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: true + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: camera + frame: + type: body + name: pelvis + entity: robot + pattern: + width: 80 + height: 60 + fovy: 63.668103675039276 + _camera_name: null + ray_alignment: base + max_distance: 2.5 + exclude_parent_body: false + include_geom_groups: !!python/tuple + - 0 + - 1 + - 2 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + class_type: !!python/name:instinct_mj.sensors.noisy_camera.noisy_grouped_raycaster_camera.NoisyGroupedRayCasterCamera '' + min_distance: 0.1 + mesh_prim_paths: [] + aux_mesh_and_link_names: {} + mesh_filter_max_hops: 24 + mesh_filter_epsilon: 0.0001 + offset: + pos: !!python/tuple + - 0.0 + - 0.018 + - -0.1 + rot: !!python/tuple + - 0.8660254037844387 + - 0.0 + - 0.49999999999999994 + - 0.0 + convention: world + data_types: + - distance_to_image_plane + update_period: 0.03333333333333333 + depth_clipping_behavior: max + focal_length: 1.0 + horizontal_aperture: 1.6555983034386739 + vertical_aperture: 1.2416987275790055 + horizontal_aperture_offset: 0.0 + vertical_aperture_offset: 0.0 + visualizer_cfg: + prim_path: /Visuals/RayCaster + markers: + hit: !!python/object/apply:types.SimpleNamespace + state: + radius: 0.02 + color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 1.0 + frame: !!python/object/apply:types.SimpleNamespace + state: + scale: !!python/tuple + - 0.1 + - 0.1 + - 0.1 + noise_pipeline: + crop_and_resize: + func: !!python/name:instinct_mj.utils.noise.noise_model.crop_and_resize '' + device: cuda:0 + crop_region: !!python/tuple + - 0 + - 0 + - 10 + - 10 + resize_shape: !!python/tuple + - 30 + - 30 + gaussian_blur: + func: !!python/name:instinct_mj.utils.noise.noise_model.gaussian_blur_noise '' + device: cuda:0 + kernel_size: 3 + sigma: 1 + depth_normalization: + func: !!python/name:instinct_mj.utils.noise.noise_model.depth_normalization '' + device: cuda:0 + depth_range: !!python/tuple + - 0.0 + - 2.5 + normalize: true + output_range: !!python/tuple + - 0.0 + - 1.0 + data_histories: + distance_to_image_plane_noised: 17 + - name: undesired_contact_forces + primary: + mode: body + pattern: .* + entity: robot + exclude: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + secondary: null + fields: !!python/tuple + - found + - force + reduce: netforce + num_slots: 1 + secondary_policy: first + track_air_time: false + global_frame: false + history_length: 3 + debug: false + extent: 2.0 + spec_fn: null +observations: + critic: + terms: + base_ang_vel: + func: &id001 !!python/name:mjlab.envs.mdp.observations.builtin_sensor '' + params: + sensor_name: robot/imu_ang_vel + noise: + operation: add + _tensor_cache: {} + n_min: -0.25 + n_max: 0.25 + clip: null + scale: 0.25 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + projected_gravity: + func: &id002 !!python/name:mjlab.envs.mdp.observations.projected_gravity '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + velocity_commands: + func: &id003 !!python/name:mjlab.envs.mdp.observations.generated_commands '' + params: + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_pos_rel: + func: &id004 !!python/name:mjlab.envs.mdp.observations.joint_pos_rel '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_vel_rel: + func: &id005 !!python/name:mjlab.envs.mdp.observations.joint_vel_rel '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -1.5 + n_max: 1.5 + clip: null + scale: 0.05 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + last_action: + func: &id006 !!python/name:mjlab.envs.mdp.observations.last_action '' + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + gait_phase: + func: &id007 !!python/name:src.tasks.velocity.mdp.observations.phase '' + params: + period: 0.9 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + base_lin_vel: + func: *id001 + params: + sensor_name: robot/imu_lin_vel + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + true_base_velocity: + func: !!python/name:mjlab.envs.mdp.observations.base_lin_vel '' + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_height: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_height '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_air_time: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_air_time '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_contact: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_contact '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_contact_forces: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_contact_forces '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + knee_reference: + func: !!python/name:src.tasks.velocity.mdp.rewards.get_desired_knee_angle '' + params: + period: 0.9 + offset: + - 0.0 + - 0.5 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + height_scan: + func: !!python/name:mjlab.envs.mdp.observations.height_scan '' + params: + sensor_name: terrain_scan + miss_value: 2.0 + noise: null + clip: !!python/tuple + - 0.0 + - 2.0 + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + foothold_target: + func: !!python/name:src.tasks.velocity.mdp.observations.foothold_target '' + params: + command_name: foothold + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + depth_image: + func: !!python/name:src.tasks.velocity.mdp.observations.DepthImageFFTLowpass '' + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: !!python/tuple + - 0 + - 1 + debug_vis: false + mask_fraction: 0.5 + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + concatenate_terms: false + concatenate_dim: -1 + enable_corruption: false + history_length: null + flatten_history_dim: true + nan_policy: sanitize + nan_check_per_term: true + actor: + terms: + base_ang_vel: + func: *id001 + params: + sensor_name: robot/imu_ang_vel + noise: + operation: add + _tensor_cache: {} + n_min: -0.25 + n_max: 0.25 + clip: null + scale: 0.25 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + projected_gravity: + func: *id002 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + velocity_commands: + func: *id003 + params: + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_pos_rel: + func: *id004 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_vel_rel: + func: *id005 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -1.5 + n_max: 1.5 + clip: null + scale: 0.05 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + last_action: + func: *id006 + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + gait_phase: + func: *id007 + params: + period: 0.9 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + depth_image: + func: !!python/name:src.tasks.velocity.mdp.observations.DepthImageFFTLowpass '' + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: !!python/tuple + - 0 + - 1 + debug_vis: false + mask_fraction: 0.5 + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + concatenate_terms: false + concatenate_dim: -1 + enable_corruption: true + history_length: null + flatten_history_dim: true + nan_policy: sanitize + nan_check_per_term: true +actions: + joint_pos: + entity_name: robot + clip: null + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + actuator_names: !!python/tuple + - .* + scale: + .*_hip_pitch_joint: 0.6 + .*_hip_roll_joint: 0.6 + .*_hip_yaw_joint: 0.2708333333333333 + .*_knee_pitch_joint: 0.45 + .*_ankle_pitch_joint: 0.15 + .*_ankle_roll_joint: 0.15 + offset: 0.0 + preserve_order: false + use_default_offset: true +events: + reset_base: + func: !!python/name:mjlab.envs.mdp.events.reset_root_state_uniform '' + params: + pose_range: + x: !!python/tuple + - -0.5 + - 0.5 + y: !!python/tuple + - -0.5 + - 0.5 + z: !!python/tuple + - 0.0 + - 0.0 + yaw: !!python/tuple + - -3.14 + - 3.14 + mode: reset + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + reset_robot_joints: + func: !!python/name:mjlab.envs.mdp.events.reset_joints_by_offset '' + params: + position_range: !!python/tuple + - -0.1 + - 0.1 + velocity_range: !!python/tuple + - -0.5 + - 0.5 + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + mode: reset + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + push_robot: + func: !!python/name:mjlab.envs.mdp.events.push_by_setting_velocity '' + params: + velocity_range: + x: !!python/tuple + - -0.5 + - 0.5 + y: !!python/tuple + - -0.5 + - 0.5 + z: !!python/tuple + - -0.4 + - 0.4 + roll: !!python/tuple + - -0.52 + - 0.52 + pitch: !!python/tuple + - -0.52 + - 0.52 + yaw: !!python/tuple + - -0.78 + - 0.78 + mode: interval + interval_range_s: !!python/tuple + - 5.0 + - 6.0 + is_global_time: false + min_step_count_between_reset: 0 + foot_friction: + func: !!python/name:mjlab.envs.mdp.dr.geom.geom_friction '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: !!python/tuple + - left_ankle_roll_link_collision_1 + - left_ankle_roll_link_collision_2 + - left_ankle_roll_link_collision_3 + - left_ankle_roll_link_collision_4 + - left_ankle_roll_link_collision_5 + - left_ankle_roll_link_collision_6 + - left_ankle_roll_link_collision_7 + - left_ankle_roll_link_collision_8 + - left_ankle_roll_link_collision_9 + - left_ankle_roll_link_collision_10 + - right_ankle_roll_link_collision_1 + - right_ankle_roll_link_collision_2 + - right_ankle_roll_link_collision_3 + - right_ankle_roll_link_collision_4 + - right_ankle_roll_link_collision_5 + - right_ankle_roll_link_collision_6 + - right_ankle_roll_link_collision_7 + - right_ankle_roll_link_collision_8 + - right_ankle_roll_link_collision_9 + - right_ankle_roll_link_collision_10 + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: abs + ranges: !!python/tuple + - 0.3 + - 1.6 + shared_random: true + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + encoder_bias: + func: !!python/name:mjlab.envs.mdp.dr.joint.encoder_bias '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + bias_range: !!python/tuple + - -0.015 + - 0.015 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + base_com: + func: &id008 !!python/name:mjlab.envs.mdp.dr.body.body_com_offset '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: + 0: !!python/tuple + - -0.05 + - 0.05 + 1: !!python/tuple + - -0.05 + - 0.05 + 2: !!python/tuple + - -0.05 + - 0.05 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + body_com: + func: *id008 + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - ^(?!waist_yaw_link$).* + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: + 0: !!python/tuple + - -0.03 + - 0.03 + 1: !!python/tuple + - -0.03 + - 0.03 + 2: !!python/tuple + - -0.03 + - 0.03 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + base_mass: + func: &id009 !!python/name:mjlab.envs.mdp.dr.body.body_mass '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: !!python/tuple + - -4.0 + - 4.0 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + body_mass: + func: *id009 + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - ^(?!waist_yaw_link$).* + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.9 + - 1.1 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_actuator_gains: + func: !!python/name:mjlab.envs.mdp.dr.actuator.pd_gains '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + kp_range: !!python/tuple + - 0.7 + - 1.1 + kd_range: !!python/tuple + - 0.7 + - 1.1 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_limit: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_limits '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.94 + - 1.06 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_stiffness: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_stiffness '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.7 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_frictionloss: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_friction '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.1 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_armature: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_armature '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.2 + - 5.0 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_damping: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_damping '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.7 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_ray_offsets: + func: !!python/name:instinct_mj.envs.mdp.events.randomization.randomize_ray_offsets '' + params: + asset_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + offset_pose_ranges: + x: !!python/tuple + - -0.01 + - 0.01 + y: !!python/tuple + - -0.01 + - 0.01 + z: !!python/tuple + - -0.03 + - 0.01 + roll: !!python/tuple + - -0.03490658503988659 + - 0.03490658503988659 + pitch: !!python/tuple + - -0.17453292519943295 + - 0.17453292519943295 + yaw: !!python/tuple + - -0.03490658503988659 + - 0.03490658503988659 + distribution: uniform + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 +seed: 42 +sim: + nconmax: 128 + njmax: 700 + ls_parallel: true + contact_sensor_maxmatch: 500 + mujoco: + timestep: 0.005 + integrator: implicitfast + impratio: 1.0 + cone: pyramidal + jacobian: auto + solver: newton + iterations: 10 + tolerance: 1.0e-08 + ls_iterations: 20 + ls_tolerance: 0.01 + ccd_iterations: 500 + gravity: !!python/tuple + - 0.0 + - 0.0 + - -9.81 + disableflags: !!python/tuple [] + enableflags: !!python/tuple [] + nan_guard: + enabled: false + buffer_size: 100 + output_dir: /tmp/mjlab/nan_dumps + max_envs_to_dump: 5 +viewer: + lookat: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + distance: 3.0 + fovy: null + elevation: -5.0 + azimuth: 90.0 + origin_type: !!python/object/apply:mjlab.viewer.viewer_config.OriginType + - 4 + entity_name: robot + body_name: waist_yaw_link + env_idx: 0 + max_extra_envs: 2 + enable_reflections: true + enable_shadows: true + height: 240 + width: 320 +episode_length_s: 20.0 +rewards: + track_linear_velocity: + func: !!python/name:src.tasks.velocity.mdp.rewards.track_linear_velocity '' + params: + command_name: twist + std: 0.5 + weight: 3.5 + track_angular_velocity: + func: !!python/name:src.tasks.velocity.mdp.rewards.track_angular_velocity '' + params: + command_name: twist + std: 0.7071067811865476 + weight: 3.0 + flat_orientation: + func: !!python/name:mjlab.envs.mdp.rewards.flat_orientation_l2 '' + params: {} + weight: -7.0 + pelvis_orientation_l2: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.link_orientation '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: pelvis + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -3.0 + joint_deviation_hip: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.joint_deviation_square '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .*_hip_yaw_joint + - .*_hip_roll_joint + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.3 + ang_vel_xy_l2: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.ang_vel_xy_l2 '' + params: {} + weight: -0.1 + dof_torques_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_torques_l2 '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .*_hip_.* + - .*_knee_.* + - .*_ankle_.* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0e-08 + dof_vel_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_vel_l2 '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -5.0e-07 + feet_flat_ori: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.feet_orientation_contact '' + params: + sensor_name: feet_ground_contact + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.01 + body_ang_vel: + func: !!python/name:src.tasks.velocity.mdp.rewards.body_angular_velocity_penalty '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.05 + angular_momentum: + func: !!python/name:src.tasks.velocity.mdp.rewards.angular_momentum_penalty '' + params: + sensor_name: robot/root_angmom + weight: -0.001 + is_terminated: + func: !!python/name:mjlab.envs.mdp.rewards.is_terminated '' + params: {} + weight: -200.0 + joint_acc_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_acc_l2 '' + params: {} + weight: -5.0e-07 + joint_pos_limits: + func: &id010 !!python/name:mjlab.envs.mdp.rewards.joint_pos_limits '' + params: {} + weight: -1.0 + action_rate_l2: + func: !!python/name:mjlab.envs.mdp.rewards.action_rate_l2 '' + params: {} + weight: -0.8 + foot_gait: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_gait '' + params: + period: 0.9 + offset: + - 0.0 + - 0.5 + threshold: 0.6 + command_threshold: 0.1 + command_name: twist + sensor_name: feet_ground_contact + weight: 2.0 + feet_double_support: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_double_support '' + params: + sensor_name: feet_ground_contact + period: 0.9 + offset: + - 0.0 + - 0.5 + threshold: 0.6 + command_name: twist + cmd_threshold: 0.1 + ds_match_weight: 1.0 + weight: 1.5 + foot_slip: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_slip '' + params: + sensor_name: feet_ground_contact + command_name: twist + command_threshold: 0.1 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.4 + feet_close_xy: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_close_xy_gauss '' + params: + threshold: 0.2 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + std: 0.22360679774997896 + weight: 1.0 + soft_landing: + func: !!python/name:src.tasks.velocity.mdp.rewards.soft_landing '' + params: + sensor_name: feet_ground_contact + command_name: twist + command_threshold: 0.1 + weight: -0.001 + dont_wait: + func: !!python/name:src.tasks.velocity.mdp.rewards.dont_wait '' + params: + command_name: twist + cmd_threshold: 0.1 + weight: -1.0 + stand_still: + func: !!python/name:src.tasks.velocity.mdp.rewards.stand_still '' + params: + command_name: twist + command_threshold: 0.1 + asset_cfg: + name: robot + joint_names: .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0 + self_collisions: + func: !!python/name:src.tasks.velocity.mdp.rewards.self_collision_cost '' + params: + sensor_name: self_collision + force_threshold: 10.0 + weight: -2.0 + feet_air_time: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_air_time '' + params: + sensor_name: feet_ground_contact + threshold: 0.36000000000000004 + command_name: twist + command_threshold: 0.1 + weight: 1.0 + feet_air_time_biped: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_air_time_positive_biped '' + params: + command_name: twist + sensor_name: feet_ground_contact + threshold: 0.52 + weight: 2.0 + terrain_foot_clearance: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_foot_clearance_cost '' + params: + target_clearance: 0.06 + left_terrain_sensor: left_height_scanner + right_terrain_sensor: right_height_scanner + command_name: twist + command_threshold: 0.05 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.5 + terrain_stumble: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_stumble_cost '' + params: + sensor_cfg: + name: feet_ground_contact + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + velocity_threshold: 0.15 + weight: -0.5 + terrain_base_height: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_base_height_l2_cost '' + params: + target_height: 0.9 + base_terrain_sensor: pelvis_height_measure + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.5 + feet_slide: + func: !!python/name:instinct_mj.tasks.parkour.mdp.rewards.feet_slide '' + params: + sensor_name: feet_ground_contact + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + threshold: 1.0 + weight: -0.4 + dof_pos_limits: + func: *id010 + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0 + foothold_tracking: + func: !!python/name:src.tasks.velocity.mdp.rewards.foothold_tracking '' + params: + command_name: foothold + sigma_stages: + - !!python/tuple + - 10.0 + - 5.0 + - !!python/tuple + - 20.0 + - 10.0 + - !!python/tuple + - 30.0 + - 15.0 + stage_step_counts: + - 0 + - 96000 + - 192000 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + sensor_name: feet_ground_contact + velocity_command_name: twist + velocity_command_threshold: 0.1 + weight: 2.1 +terminations: + time_out: + func: !!python/name:mjlab.envs.mdp.terminations.time_out '' + params: {} + time_out: true + fell_over: + func: !!python/name:mjlab.envs.mdp.terminations.bad_orientation '' + params: + limit_angle: 1.2217304763960306 + time_out: false + nan_term: + func: !!python/name:mjlab.envs.mdp.terminations.nan_detection '' + params: {} + time_out: false + base_height: + func: !!python/name:src.tasks.velocity.mdp.rewards.root_height_below_minimum_terrain '' + params: + minimum_height: 0.3 + terrain_sensor_name: pelvis_height_measure + time_out: false +commands: + twist: + resampling_time_range: !!python/tuple + - 3.0 + - 8.0 + debug_vis: true + entity_name: robot + heading_command: false + heading_control_stiffness: 0.5 + rel_standing_envs: 0.05 + rel_heading_envs: 1.0 + rel_world_envs: 0.0 + rel_forward_envs: 0.0 + init_velocity_prob: 0.0 + ranges: + lin_vel_x: !!python/tuple + - 0.0 + - 1.0 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.5 + - 0.5 + heading: null + viz: + z_offset: 1.15 + scale: 0.5 + foothold: + resampling_time_range: !!python/tuple + - 1000000000.0 + - 1000000000.0 + debug_vis: false + entity_name: robot + terrain_sensor_name: terrain_scan + contact_sensor_name: feet_ground_contact + velocity_command_name: twist + foot_site_names: !!python/tuple + - left_foot + - right_foot + gait_period: 0.9 + gait_action_name: gait_freq + nominal_height_m: 0.9 + lateral_inter_foot_m: 0.22 + foot_footprint_m: !!python/tuple + - 0.25 + - 0.1 + search_window_m: !!python/tuple + - 0.6 + - 0.6 + elevation_size_m: !!python/tuple + - 1.8 + - 1.2 + elevation_resolution_m: 0.05 + alpha_pos: 1.0 + alpha_dcm: 0.5 + alpha_steepness: 0.6 + alpha_flatness: 4.0 + alpha_height: 6.0 + alpha_climb_bonus: 1.5 + lateral_pos_weight: 2.5 + max_step_height_m: 0.25 + climb_velocity_threshold: 0.1 + standing_threshold: 0.1 + min_step_height_m: 0.05 + max_step_velocity_m_s: 0.5 + apex_clearance_m: 0.05 + clearance_scale: 0.5 + max_clearance_m: 0.2 + pre_apex_lower_window: 0.05 + pre_apex_upper_window: 0.05 + post_apex_lower_window: 0.1 + post_apex_upper_window: 0.15 + terrain_decision_threshold: 0.1 +curriculum: + terrain_levels: + func: !!python/name:src.tasks.velocity.mdp.curriculums.terrain_levels_vel '' + params: + command_name: twist + command_vel: + func: !!python/name:src.tasks.velocity.mdp.curriculums.commands_vel '' + params: + command_name: twist + velocity_stages: + - step: 0 + lin_vel_x: !!python/tuple + - 0.0 + - 0.5 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.2 + - 0.2 + - step: 120000 + lin_vel_x: !!python/tuple + - 0.0 + - 1.0 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.5 + - 0.5 +metrics: + mean_action_acc: + func: !!python/name:mjlab.envs.mdp.metrics.mean_action_acc '' + params: {} + per_substep: false + reduce: mean +recorders: {} +is_finite_horizon: false +auto_reset: true +scale_rewards_by_dt: true diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/env_cfgs.py b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/env_cfgs.py new file mode 100644 index 0000000000000000000000000000000000000000..29089b5f5af0e3df29b5cbf63f61fd363ef389ab --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/params/env_cfgs.py @@ -0,0 +1,2716 @@ +"""VinRobotics VR-M3 12DOF (lower-body only) velocity environment configurations. + +Self-contained: this module builds the full `ManagerBasedRlEnvCfg` inline +rather than deriving from `src.tasks.velocity.velocity_env_cfg`, so changes +to the shared factory do not silently affect VR-M3 12DOF training. +""" + +import math +from copy import deepcopy +from dataclasses import dataclass, replace +import numpy as np + +import instinct_mj.envs.mdp as instinct_mdp + +# import instinct_mj.tasks.locomotion.mdp as instinct_locomotion_mdp +try: + import instinct_mj.tasks.parkour.mdp as instinct_parkour_mdp +except ImportError: + instinct_parkour_mdp = None # type: ignore[assignment] +from instinct_mj.sensors.noisy_camera import NoisyGroupedRayCasterCameraCfg +from instinct_mj.utils.noise import ( + CropAndResizeCfg, + DepthArtifactNoiseCfg, + DepthContourNoiseCfg, + DepthNormalizationCfg, + DepthSkyArtifactNoiseCfg, + GaussianBlurNoiseCfg, + RangeBasedGaussianNoiseCfg, + StereoTooCloseNoiseCfg, +) +from mjlab.envs import ManagerBasedRlEnvCfg +from mjlab.envs import mdp as envs_mdp +from mjlab.envs.mdp import dr +from mjlab.envs.mdp.actions import JointPositionActionCfg +from mjlab.managers.action_manager import ActionTermCfg +from mjlab.managers.command_manager import CommandTermCfg +from mjlab.managers.curriculum_manager import CurriculumTermCfg +from mjlab.managers.event_manager import EventTermCfg +from mjlab.managers.metrics_manager import MetricsTermCfg +from mjlab.managers.observation_manager import ObservationGroupCfg, ObservationTermCfg +from mjlab.managers.reward_manager import RewardTermCfg +from mjlab.managers.scene_entity_config import SceneEntityCfg +from mjlab.managers.termination_manager import TerminationTermCfg +from mjlab.scene import SceneCfg +from mjlab.sensor import ( + ContactMatch, + ContactSensorCfg, + GridPatternCfg, + ObjRef, + PinholeCameraPatternCfg, + RayCastSensorCfg, +) + +from mjlab.sim import MujocoCfg, SimulationCfg +from mjlab.tasks.velocity.mdp import UniformVelocityCommandCfg +from mjlab.terrains import TerrainEntityCfg, SubTerrainCfg +from mjlab.terrains.config import ROUGH_TERRAINS_CFG +from mjlab.utils.noise import UniformNoiseCfg as Unoise +from mjlab.viewer import ViewerConfig + +import src.tasks.velocity.mdp as mdp +from src.assets.robots import ( + VR_M3_12DOF_ACTION_SCALE, + get_vr_m3_12dof_implicit_actuator_robot_cfg, + vr_m3_12dof_joint_pos_action_scale, + vr_m3_12dof_joint_vel_action_scale, +) +from src.tasks.velocity.terrains.config import PERCEPTIVE_TERRAINS_CFG +from src.envs import MultiCriticManagerBasedRlEnvCfg + +## +# VR-M3 12DOF specific constants +## + +# 12DOF keeps the upper body kinematically but with no actuated joints, so +# `waist_yaw_link` (the torso-equivalent body) is still referenceable. +TORSO_BODY = "waist_yaw_link" + +FOOT_SITES = ("left_foot", "right_foot") +FOOT_LINK_NAMES = ("left_ankle_roll_link", "right_ankle_roll_link") + +# Same foot geometry as the fullbody XML: 10 collision geoms per ankle_roll_link. +FOOT_GEOMS = tuple( + f"{side}_ankle_roll_link_collision_{i}" + for side in ("left", "right") + for i in range(1, 11) +) + +# 12DOF only actuates legs; waist and upper body have no actuators, so the +# pose reward only lists the leg-joint regexes. +POSE_STD_STANDING: dict[str, float] = {".*": 0.05} +POSE_STD_WALKING: dict[str, float] = { + r".*hip_pitch.*": 0.5, + r".*hip_roll.*": 0.15, + r".*hip_yaw.*": 0.15, + r".*knee.*": 0.5, + r".*ankle_pitch.*": 0.15, + r".*ankle_roll.*": 0.1, +} +POSE_STD_RUNNING: dict[str, float] = { + r".*hip_pitch.*": 0.5, + r".*hip_roll.*": 0.25, + r".*hip_yaw.*": 0.25, + r".*knee.*": 0.5, + r".*ankle_pitch.*": 0.25, + r".*ankle_roll.*": 0.1, +} + +GAIT_CYCLE_PERIOD = 0.9 + + +@dataclass +class VelocityEnvCfg(ManagerBasedRlEnvCfg): + def __post_init__(self): + pass + + +def vr_m3_12dof_rough_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF rough terrain velocity configuration.""" + + ## + # Sensors + ## + + feet_ground_cfg = ContactSensorCfg( + name="feet_ground_contact", + primary=ContactMatch( + mode="subtree", + pattern=r"^(left_ankle_roll_link|right_ankle_roll_link)$", + entity="robot", + ), + secondary=ContactMatch(mode="body", pattern="terrain"), + fields=("found", "force"), + reduce="netforce", + num_slots=1, + track_air_time=True, + history_length=4, + ) + self_collision_cfg = ContactSensorCfg( + name="self_collision", + primary=ContactMatch(mode="subtree", pattern="pelvis", entity="robot"), + secondary=ContactMatch(mode="subtree", pattern="pelvis", entity="robot"), + fields=("found", "force"), + reduce="none", + num_slots=1, + history_length=4, + ) + + ## + # Observations + ## + + actor_terms = { + "base_ang_vel": ObservationTermCfg( + func=mdp.builtin_sensor, + scale=0.25, + params={"sensor_name": "robot/imu_ang_vel"}, + noise=Unoise(n_min=-0.25, n_max=0.25), + history_length=5, + flatten_history_dim=True, + ), + "projected_gravity": ObservationTermCfg( + func=mdp.projected_gravity, + noise=Unoise(n_min=-0.05, n_max=0.05), + history_length=5, + flatten_history_dim=True, + ), + "velocity_commands": ObservationTermCfg( + func=mdp.generated_commands, + params={"command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ), + "joint_pos_rel": ObservationTermCfg( + func=mdp.joint_pos_rel, + noise=Unoise(n_min=-0.05, n_max=0.05), + history_length=5, + flatten_history_dim=True, + ), + "joint_vel_rel": ObservationTermCfg( + func=mdp.joint_vel_rel, + scale=0.05, + noise=Unoise(n_min=-1.5, n_max=1.5), + history_length=5, + flatten_history_dim=True, + ), + "last_action": ObservationTermCfg( + func=mdp.last_action, history_length=5, flatten_history_dim=True + ), + "gait_phase": ObservationTermCfg( + func=mdp.phase, + params={"period": GAIT_CYCLE_PERIOD, "command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ), + } + + critic_terms = { + **actor_terms, + "base_lin_vel": ObservationTermCfg( + func=mdp.builtin_sensor, + params={"sensor_name": "robot/imu_lin_vel"}, + history_length=5, + flatten_history_dim=True, + ), + "true_base_velocity": ObservationTermCfg( + func=envs_mdp.base_lin_vel, + history_length=5, + flatten_history_dim=True, + ), + "foot_height": ObservationTermCfg( + func=mdp.foot_height, + params={"asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES)}, + history_length=5, + flatten_history_dim=True, + ), + "foot_air_time": ObservationTermCfg( + func=mdp.foot_air_time, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "foot_contact": ObservationTermCfg( + func=mdp.foot_contact, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "foot_contact_forces": ObservationTermCfg( + func=mdp.foot_contact_forces, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "knee_reference": ObservationTermCfg( + func=mdp.get_desired_knee_angle, + params={ + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "command_name": "twist", + }, + history_length=5, + flatten_history_dim=True, + ), + } + + observations = { + "actor": ObservationGroupCfg( + terms=actor_terms, + concatenate_terms=True, + enable_corruption=True, + # history_length=5, + nan_policy="sanitize", + nan_check_per_term=True, + ), + "critic": ObservationGroupCfg( + terms=critic_terms, + concatenate_terms=True, + enable_corruption=False, + # history_length=5, + nan_policy="sanitize", + nan_check_per_term=True, + ), + } + + ## + # Metrics + ## + + metrics = { + "mean_action_acc": MetricsTermCfg(func=mdp.mean_action_acc), + } + + ## + # Actions + ## + + actions: dict[str, ActionTermCfg] = { + "joint_pos": JointPositionActionCfg( + entity_name="robot", + actuator_names=(".*",), + scale=VR_M3_12DOF_ACTION_SCALE, + use_default_offset=True, + ) + } + + ## + # Commands + ## + + commands: dict[str, CommandTermCfg] = { + "twist": UniformVelocityCommandCfg( + entity_name="robot", + resampling_time_range=(3.0, 8.0), + rel_standing_envs=0.05, + heading_command=False, + heading_control_stiffness=0.5, + debug_vis=True, + ranges=UniformVelocityCommandCfg.Ranges( + lin_vel_x=(-1.0, 2.0), + lin_vel_y=(-1.0, 1.0), + ang_vel_z=(-1.0, 1.0), + heading=None, + ), + ), + } + twist_cmd = commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.viz.z_offset = 1.15 + + ## + # Events + ## + + events = { + "reset_base": EventTermCfg( + func=mdp.reset_root_state_uniform, + mode="reset", + params={ + "pose_range": { + "x": (-0.5, 0.5), + "y": (-0.5, 0.5), + "z": (0.0, 0.0), + "yaw": (-3.14, 3.14), + }, + # "discrete_yaws": [0.0, math.pi / 2, math.pi, -math.pi / 2], # [0.0, math.pi / 2, math.pi, -math.pi / 2], + }, + ), + "reset_robot_joints": EventTermCfg( + func=mdp.reset_joints_by_offset, + mode="reset", + params={ + "position_range": (-0.1, 0.1), + "velocity_range": (-0.5, 0.5), + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + }, + ), + "push_robot": EventTermCfg( + func=mdp.push_by_setting_velocity, + mode="interval", + interval_range_s=(5.0, 6.0), + params={ + "velocity_range": { + "x": (-0.5, 0.5), + "y": (-0.5, 0.5), + "z": (-0.4, 0.4), + "roll": (-0.52, 0.52), + "pitch": (-0.52, 0.52), + "yaw": (-0.78, 0.78), + }, + }, + ), + "foot_friction": EventTermCfg( + mode="startup", + func=dr.geom_friction, + params={ + "asset_cfg": SceneEntityCfg("robot", geom_names=FOOT_GEOMS), + "operation": "abs", + "ranges": (0.3, 1.6), + "shared_random": True, + }, + ), + "encoder_bias": EventTermCfg( + mode="startup", + func=dr.encoder_bias, + params={ + "asset_cfg": SceneEntityCfg("robot"), + "bias_range": (-0.015, 0.015), + }, + ), + "base_com": EventTermCfg( + mode="startup", + func=dr.body_com_offset, + params={ + "asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,)), + "operation": "add", + "ranges": { + 0: (-0.05, 0.05), + 1: (-0.05, 0.05), + 2: (-0.05, 0.05), + }, + }, + ), + "body_com": EventTermCfg( + mode="startup", + func=dr.body_ipos, + params={ + "asset_cfg": SceneEntityCfg( + "robot", body_names=("^(?!waist_yaw_link$).*",) + ), + "operation": "add", + "ranges": { + 0: (-0.03, 0.03), + 1: (-0.03, 0.03), + 2: (-0.03, 0.03), + }, + }, + ), + "base_mass": EventTermCfg( + mode="startup", + func=dr.body_mass, + params={ + "asset_cfg": SceneEntityCfg("robot", body_names=("waist_yaw_link",)), + "operation": "add", + "ranges": (-4.0, 4.0), + }, + ), + "body_mass": EventTermCfg( + mode="startup", + func=dr.body_mass, + params={ + "asset_cfg": SceneEntityCfg( + "robot", body_names=("^(?!waist_yaw_link$).*",) + ), + "operation": "scale", + "ranges": (0.9, 1.1), + }, + ), + "randomize_actuator_gains": EventTermCfg( + func=dr.pd_gains, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "kp_range": (0.7, 1.1), + "kd_range": (0.7, 1.1), + }, + ), + "randomize_joint_limit": EventTermCfg( + mode="startup", + func=dr.joint_limits, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.94, 1.06), + }, + ), + "randomize_joint_stiffness": EventTermCfg( + mode="startup", + func=dr.joint_stiffness, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.7, 1.3), + }, + ), + "randomize_joint_frictionloss": EventTermCfg( + mode="startup", + func=dr.joint_friction, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.1, 1.3), + }, + ), + "randomize_joint_armature": EventTermCfg( + mode="startup", + func=dr.joint_armature, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.2, 5.0), + }, + ), + "randomize_joint_damping": EventTermCfg( + mode="startup", + func=dr.joint_damping, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.7, 1.3), + }, + ), + } + + ## + # Rewards + ## + + rewards = { + "track_linear_velocity": RewardTermCfg( + func=mdp.track_linear_velocity, + weight=2.0, + params={"command_name": "twist", "std": math.sqrt(0.25)}, + ), + "track_angular_velocity": RewardTermCfg( + func=mdp.track_angular_velocity, + weight=2.0, + params={"command_name": "twist", "std": math.sqrt(0.5)}, + ), + "body_orientation_l2": RewardTermCfg( + func=mdp.body_orientation_l2, + weight=-5.0, + params={"asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,))}, + ), + "pose": RewardTermCfg( + func=mdp.variable_posture, + weight=1.0, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), + "command_name": "twist", + "std_standing": POSE_STD_STANDING, + "std_walking": POSE_STD_WALKING, + "std_running": POSE_STD_RUNNING, + "walking_threshold": 0.1, + "running_threshold": 0.7, + }, + ), + "flat_orientation": RewardTermCfg(func=mdp.flat_orientation_l2, weight=-7.0), + "pelvis_orientation_l2": RewardTermCfg( + func=mdp.link_orientation, + weight=-3.0, + params={"asset_cfg": SceneEntityCfg("robot", body_names="pelvis")}, + ), + "joint_deviation_hip": RewardTermCfg( + func=mdp.joint_deviation_square, + weight=-0.1, + params={ + "asset_cfg": SceneEntityCfg( + "robot", + joint_names=(".*_hip_yaw_joint", ".*_hip_roll_joint"), + ) + }, + ), + "ang_vel_xy_l2": RewardTermCfg( + func=mdp.ang_vel_xy_l2, + weight=-0.05, + ), + "dof_torques_l2": RewardTermCfg( + func=mdp.joint_torques_l2, + weight=-1.0e-8, + params={ + "asset_cfg": SceneEntityCfg( + "robot", + joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + ) + }, + ), + "dof_vel_l2": RewardTermCfg( + func=mdp.joint_vel_l2, + weight=-1.0e-8, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + "feet_flat_ori": RewardTermCfg( + func=mdp.feet_orientation_contact, + weight=-0.01, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + }, + ), + "body_ang_vel": RewardTermCfg( + func=mdp.body_angular_velocity_penalty, + weight=-0.05, + params={"asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,))}, + ), + "angular_momentum": RewardTermCfg( + func=mdp.angular_momentum_penalty, + weight=-0.025, + params={"sensor_name": "robot/root_angmom"}, + ), + "is_terminated": RewardTermCfg(func=mdp.is_terminated, weight=-200.0), + "joint_acc_l2": RewardTermCfg(func=mdp.joint_acc_l2, weight=-2.5e-7), + "joint_pos_limits": RewardTermCfg(func=mdp.joint_pos_limits, weight=-5.0), + "action_rate_l2": RewardTermCfg(func=mdp.action_rate_l2, weight=-0.5), + "foot_gait": RewardTermCfg( + func=mdp.feet_gait, + weight=1.0, + params={ + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "threshold": 0.6, + "command_threshold": 0.1, + "command_name": "twist", + "sensor_name": "feet_ground_contact", + }, + ), + "feet_double_support": RewardTermCfg( + func=mdp.feet_double_support, + weight=2.0, + params={ + "sensor_name": "feet_ground_contact", + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "threshold": 0.6, + "command_name": "twist", + "cmd_threshold": 0.1, + "ds_match_weight": 1.0, + }, + ), + "foot_clearance": RewardTermCfg( + func=mdp.feet_clearance, + weight=-1.0, + params={ + "target_height": 0.10, + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES), + }, + ), + "foot_slip": RewardTermCfg( + func=mdp.feet_slip, + weight=-0.25, + params={ + "sensor_name": "feet_ground_contact", + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES), + }, + ), + "feet_close_xy": RewardTermCfg( + func=mdp.feet_close_xy_gauss, + weight=1.0, + params={ + "threshold": 0.2, + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "std": math.sqrt(0.05), + }, + ), + "soft_landing": RewardTermCfg( + func=mdp.soft_landing, + weight=-1e-3, + params={ + "sensor_name": "feet_ground_contact", + "command_name": "twist", + "command_threshold": 0.1, + }, + ), + "dont_wait": RewardTermCfg( + func=mdp.dont_wait, + weight=-0.5, + params={ + "command_name": "twist", + "cmd_threshold": 0.1, + }, + ), + "stand_still": RewardTermCfg( + func=mdp.stand_still, + weight=-1.0, + params={ + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), + }, + ), + "self_collisions": RewardTermCfg( + func=mdp.self_collision_cost, + weight=-1.0, + params={"sensor_name": self_collision_cfg.name, "force_threshold": 10.0}, + ), + "feet_air_time": RewardTermCfg( + func=mdp.feet_air_time, + weight=1.0, + params={ + "sensor_name": "feet_ground_contact", + "threshold": (1.0 - 0.6) * GAIT_CYCLE_PERIOD, # 0.48 s + "command_name": "twist", + "command_threshold": 0.1, + }, + ), + "feet_air_time_biped": RewardTermCfg( + func=mdp.feet_air_time_positive_biped, + weight=1.5, + params={ + "command_name": "twist", + "sensor_name": "feet_ground_contact", + "threshold": 0.52, + }, + ), + } + + ## + # Terminations + ## + + terminations = { + "time_out": TerminationTermCfg(func=mdp.time_out, time_out=True), + "fell_over": TerminationTermCfg( + func=mdp.bad_orientation, + params={"limit_angle": math.radians(70.0)}, + ), + "nan_term": TerminationTermCfg( + func=mdp.nan_detection, + time_out=False, + ), + } + + ## + # Curriculum + ## + + curriculum = { + "terrain_levels": CurriculumTermCfg( + func=mdp.terrain_levels_vel, + params={"command_name": "twist"}, + ), + "command_vel": CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (-0.5, 1.0), + "lin_vel_y": (-0.5, 0.5), + "ang_vel_z": (-0.5, 0.5), + }, + { + "step": 5000 * 24, + "lin_vel_x": (-0.7, 1.5), + "lin_vel_y": (-0.7, 0.7), + "ang_vel_z": (-0.7, 0.7), + }, + { + "step": 7000 * 24, + "lin_vel_x": (-1.0, 2.0), + "lin_vel_y": (-1.0, 1.0), + "ang_vel_z": (-1.0, 1.0), + }, + # { + # "step": 9000 * 24, + # "lin_vel_x": (-1.0, 3.0), + # "lin_vel_y": (-1.0, 1.0), + # "ang_vel_z": (-1.0, 1.0), + # }, + ], + }, + ), + } + + ## + # Scene + terrain + ## + + terrain_generator = replace(ROUGH_TERRAINS_CFG) + terrain_generator.curriculum = True + terrain = TerrainEntityCfg( + terrain_type="generator", + terrain_generator=terrain_generator, + max_init_terrain_level=5, + ) + + scene = SceneCfg( + terrain=terrain, + entities={"robot": get_vr_m3_12dof_implicit_actuator_robot_cfg()}, + sensors=(feet_ground_cfg, self_collision_cfg), + num_envs=1, + extent=2.0, + ) + + ## + # Assemble + ## + + cfg = VelocityEnvCfg( + scene=scene, + observations=observations, + actions=actions, + commands=commands, + events=events, + rewards=rewards, + terminations=terminations, + curriculum=curriculum, + metrics=metrics, + viewer=ViewerConfig( + origin_type=ViewerConfig.OriginType.ASSET_BODY, + entity_name="robot", + body_name=TORSO_BODY, + distance=3.0, + elevation=-5.0, + azimuth=90.0, + ), + sim=SimulationCfg( + # VR-M3 has ~1.4x the foot collision geoms of G1 (10/side vs 7/side); + # rough terrain randomization can push the contact count up, so + # nconmax is raised from G1's 48 to 512. + nconmax=512, + njmax=1500, + contact_sensor_maxmatch=500, + mujoco=MujocoCfg( + timestep=0.005, + iterations=10, + ls_iterations=20, + ccd_iterations=500, + ), + ), + decimation=4, + episode_length_s=20.0, + ) + + # Play mode overrides. + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["actor"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + return cfg + + +def vr_m3_12dof_flat_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF flat terrain velocity configuration.""" + cfg = vr_m3_12dof_rough_env_cfg(play=play) + cfg.rewards.pop("flat_orientation", None) + cfg.rewards.pop("pelvis_orientation_l2", None) + cfg.rewards.pop("joint_deviation_hip", None) + cfg.rewards.pop("ang_vel_xy_l2", None) + cfg.rewards.pop("dof_torques_l2", None) + cfg.rewards.pop("dof_vel_l2", None) + cfg.rewards.pop("feet_flat_ori", None) + # VR-M3 has ~1.4x the foot collision geoms of G1, so njmax needs headroom. + cfg.sim.njmax = 600 + cfg.sim.mujoco.ccd_iterations = 50 + cfg.sim.contact_sensor_maxmatch = 64 + cfg.sim.nconmax = None + + # Switch to flat terrain. + assert cfg.scene.terrain is not None + cfg.scene.terrain.terrain_type = "plane" + cfg.scene.terrain.terrain_generator = None + + # Remove raycast sensor and height scan (no terrain to scan). + cfg.scene.sensors = tuple( + s for s in (cfg.scene.sensors or ()) if s.name != "terrain_scan" + ) + # del cfg.observations["actor"].terms["height_scan"] + # del cfg.observations["critic"].terms["height_scan"] + cfg.observations["actor"].terms.pop("height_scan", None) + cfg.observations["critic"].terms.pop("height_scan", None) + + cfg.curriculum.pop("terrain_levels", None) + + if play: + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (-0.5, 2.0) + twist_cmd.ranges.lin_vel_y = (-0.5, 0.5) + twist_cmd.ranges.ang_vel_z = (-0.5, 0.5) + + return cfg + + +def vr_m3_12dof_perceptive_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF perceptive locomotion configuration with height-map.""" + cfg = vr_m3_12dof_rough_env_cfg(play=play) + + site_names = ("left_foot", "right_foot") + + # Auto-size contact buffers for complex terrain geometry. + cfg.sim.njmax = 700 + cfg.sim.mujoco.ccd_iterations = 500 + cfg.sim.contact_sensor_maxmatch = 500 + cfg.sim.nconmax = 128 + + # Swap terrain generator to perceptive preset (deepcopy to avoid mutation). + assert cfg.scene.terrain is not None + cfg.scene.terrain.terrain_generator = deepcopy(PERCEPTIVE_TERRAINS_CFG) + + if not play: + cfg.scene.terrain.terrain_generator.curriculum = True + + pelvis_height_measure = RayCastSensorCfg( + name="pelvis_height_measure", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=2.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + left_height_scanner = RayCastSensorCfg( + name="left_height_scanner", + frame=ObjRef(type="site", name="left_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=1.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + right_height_scanner = RayCastSensorCfg( + name="right_height_scanner", + frame=ObjRef(type="site", name="right_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=1.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + + # --- Gradient sensors (3x3 grid for foot edge detection) --- + left_foot_gradient = RayCastSensorCfg( + name="left_foot_gradient", + frame=ObjRef(type="site", name="left_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.2, 0.1), + resolution=0.1, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=1.0, + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + right_foot_gradient = RayCastSensorCfg( + name="right_foot_gradient", + frame=ObjRef(type="site", name="right_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.2, 0.1), + resolution=0.1, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=1.0, + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + pelvis_height_measure, + left_height_scanner, + right_height_scanner, + left_foot_gradient, + right_foot_gradient, + ) + + # --- Terrain-aware reward terms --- + cfg.rewards["terrain_foot_clearance"] = RewardTermCfg( + func=mdp.terrain_foot_clearance_cost, + weight=-0.5, + params={ + "target_clearance": 0.06, + "left_terrain_sensor": "left_height_scanner", + "right_terrain_sensor": "right_height_scanner", + "command_name": "twist", + "command_threshold": 0.05, + "asset_cfg": SceneEntityCfg("robot", site_names=site_names), + }, + ) + + cfg.rewards["terrain_stumble"] = RewardTermCfg( + func=mdp.terrain_stumble_cost, + weight=-1.0, + params={ + "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "velocity_threshold": 0.15, + }, + ) + + # cfg.rewards["step_accuracy"] = RewardTermCfg( + # func=custom_mdp.step_accuracy, + # weight=1.0, + # params={ + # "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "patch_name": "target", + # "std": 0.15, + # }, + # ) + + cfg.rewards["terrain_base_height"] = RewardTermCfg( + func=mdp.terrain_base_height_l2_cost, + weight=-1.0, + params={ + "target_height": 0.9, + "base_terrain_sensor": "pelvis_height_measure", + "asset_cfg": SceneEntityCfg("robot"), + }, + ) + + cfg.rewards["foot_edge"] = RewardTermCfg( + func=mdp.foot_edge_cost, + weight=-0.5, + params={ + "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + "left_gradient_sensor": "left_foot_gradient", + "right_gradient_sensor": "right_foot_gradient", + "gradient_threshold": 0.3, + "asset_cfg": SceneEntityCfg("robot", body_names=[r".*ankle_roll.*"]), + }, + ) + + # cfg.rewards["feet_at_plane"] = RewardTermCfg( + # func=parkour_mdp.feet_at_plane, + # weight=-0.1, + # params={ + # "contact_sensor_name": "feet_ground_contact", + # "left_height_scanner_name": "left_height_scanner", # matches your sensor + # "right_height_scanner_name": "right_height_scanner", # matches your sensor + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "height_offset": 0.06, + # }, + # ) + + # --- Terrain-aware termination --- + cfg.terminations["base_height"] = TerminationTermCfg( + func=mdp.root_height_below_minimum_terrain, + params={ + "minimum_height": 0.3, + "terrain_sensor_name": "pelvis_height_measure", + }, + ) + + if play: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + return cfg + + +def vr_m3_12dof_height_map_env_cfg(play: bool = False) -> VelocityEnvCfg: + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(0.6, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + cfg.scene.sensors = cfg.scene.sensors + (terrain_scan,) + + # --- Asymmetric actor-critic observations --- + # Actor: add terrain_scan with noise (proprioception terms inherited from base). + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + # func=custom_mdp.height_scan_custom, + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + noise=Unoise(n_min=-0.1, n_max=0.1), + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic: add terrain_scan (no noise, privileged) and true base velocity. + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + # func=custom_mdp.height_scan_custom, + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + history_length=5, + ) + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 2.5 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -5e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 1.0 + cfg.rewards["feet_double_support"].weight = 2.0 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -0.5 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 1.5 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards["foot_edge"].weight = -0.5 + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["actor"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_depth_map_env_cfg( + play: bool = False, +) -> VelocityEnvCfg: + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(1.8, 1.2), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + depth_camera = NoisyGroupedRayCasterCameraCfg( + name="camera", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + # RealSense depth camera D435 + # Intrinsics from camera_info: fx = fy = 386.56719970703125 at 640x480 + pattern=PinholeCameraPatternCfg( + height=int(480 / 8), + width=int(640 / 8), + fovy=2 + * math.degrees(math.atan(480 / 2 / 386.56719970703125)), # ~63.67 deg + ), + focal_length=1.0, + horizontal_aperture=640.0 / 386.56719970703125, # fovx ~79.24 deg + vertical_aperture=480.0 / 386.56719970703125, # fovy ~63.67 deg + ray_alignment="base", + include_geom_groups=(0, 1, 2), + exclude_parent_body=False, + offset=NoisyGroupedRayCasterCameraCfg.OffsetCfg( + pos=(0.00, 0.018, -0.1), + rot=( + math.cos(math.radians(60) / 2), # w + 0.0, # x + math.sin(math.radians(60) / 2), # y (pitch 60 deg about Y) + 0.0, # z + ), + convention="world", + ), + data_types=["distance_to_image_plane"], + depth_clipping_behavior="max", # clip to the maximum value + mesh_filter_max_hops=24, + noise_pipeline={ + "crop_and_resize": CropAndResizeCfg( + # (top, bottom, left, right), height/2 and centering width/2 + crop_region=(0, 0, 10, 10), + resize_shape=(30, 30), + ), + "gaussian_blur": GaussianBlurNoiseCfg(kernel_size=3, sigma=1), + "depth_normalization": DepthNormalizationCfg( + depth_range=(0.0, 2.5), + normalize=True, + output_range=(0.0, 1.0), + ), + }, + data_histories={"distance_to_image_plane_noised": 17}, + update_period=1 / 30, + min_distance=0.1, + max_distance=2.5, + debug_vis=play, + ) + undesired_contact_cfg = ContactSensorCfg( + name="undesired_contact_forces", + primary=ContactMatch( + mode="body", + pattern=".*", + entity="robot", + exclude=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + fields=("found", "force"), + reduce="netforce", + track_air_time=False, + history_length=3, + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + terrain_scan, + depth_camera, + undesired_contact_cfg, + ) + + cfg.events["randomize_ray_offsets"] = EventTermCfg( + func=instinct_mdp.randomize_ray_offsets, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("camera"), + "offset_pose_ranges": { + "x": (-0.01, 0.01), + "y": (-0.01, 0.01), + "z": (-0.03, 0.01), + "roll": (-math.radians(2), math.radians(2)), + "pitch": (-math.radians(10), math.radians(10)), + "yaw": (-math.radians(2), math.radians(2)), + }, + "distribution": "uniform", + }, + ) + + cfg.observations["actor"].concatenate_terms = False + cfg.observations["critic"].concatenate_terms = False + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + ) + + cfg.observations["actor"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + cfg.observations["critic"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + # Add "policy" alias for actor obs (Instinct runner expects "policy"). + actor_obs_cfg = cfg.observations.pop("actor") + cfg.observations["policy"] = actor_obs_cfg + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 2.0 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards["foot_edge"].weight = -0.5 + + cfg.rewards = { + **cfg.rewards, + "feet_slide": RewardTermCfg( + func=instinct_parkour_mdp.feet_slide, + weight=-0.4, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "threshold": 1.0, + }, + ), + # "joint_deviation_hip": RewardTermCfg( + # func=instinct_mdp.joint_deviation_square, + # weight=-0.3, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_yaw_joint", ".*_hip_roll_joint"), + # ) + # }, + # ), + # "ang_vel_xy_l2": RewardTermCfg( + # func=instinct_parkour_mdp.ang_vel_xy_l2, + # weight=-0.05, + # ), + # "dof_torques_l2": RewardTermCfg( + # func=instinct_parkour_mdp.joint_torques_l2, + # weight=-1.0e-7, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ) + # }, + # ), + # "dof_vel_l2": RewardTermCfg( + # func=envs_mdp.joint_vel_l2, + # weight=-5.0e-7, + # params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + # ), + # "feet_flat_ori": RewardTermCfg( + # func=instinct_parkour_mdp.feet_orientation_contact, + # weight=-0.01, + # params={ + # "sensor_name": "feet_ground_contact", + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # }, + # ), + # "feet_close_xy": RewardTermCfg( + # func=instinct_parkour_mdp.feet_close_xy_gauss, + # weight=1.0, + # params={ + # "threshold": 0.2, + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "std": math.sqrt(0.05), + # }, + # ), + # "energy": RewardTermCfg( + # func=parkour_mdp.rewards.motors_power_square, + # weight=-1.0e-8, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ), + # "normalize_by_stiffness": True, + # }, + # ), + "dof_pos_limits": RewardTermCfg( + func=envs_mdp.joint_pos_limits, + weight=-1.0, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + # "flat_orientation": RewardTermCfg(func=mdp.flat_orientation_l2, weight=-7.0), + # "pelvis_orientation_l2": RewardTermCfg( + # func=instinct_parkour_mdp.link_orientation, + # weight=-3.0, + # params={"asset_cfg": SceneEntityCfg("robot", body_names="pelvis")}, + # ), + } + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["policy"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_foothold_env_cfg(play: bool = False) -> VelocityEnvCfg: + """FastStair Stage 1 — planner-guided pre-training (paper §III-B.3). + + Extends ``vr_m3_12dof_height_map_env_cfg`` with: + + - A 1.8 × 1.2 m elevation map at 5 cm resolution (paper §III-C). + - The DCM-based foothold planner exposed as a ``FootholdCommand``. + - The exponential foothold-tracking reward with weight 0.6 (Table I §III-B.2). + - A privileged ``foothold_target`` observation on the critic. + - Velocity range restricted to the paper's pre-train regime + ``[-0.3, 1.0]`` m/s in x. + - Stage 1 reward weights from Table I. + """ + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(1.8, 1.2), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0,), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + depth_camera = NoisyGroupedRayCasterCameraCfg( + name="camera", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + # RealSense depth camera D435 + # Intrinsics from camera_info: fx = fy = 386.56719970703125 at 640x480 + pattern=PinholeCameraPatternCfg( + height=int(480 / 8), + width=int(640 / 8), + fovy=2 + * math.degrees(math.atan(480 / 2 / 386.56719970703125)), # ~63.67 deg + ), + focal_length=1.0, + horizontal_aperture=640.0 / 386.56719970703125, # fovx ~79.24 deg + vertical_aperture=480.0 / 386.56719970703125, # fovy ~63.67 deg + ray_alignment="base", + include_geom_groups=(0, 1, 2), + exclude_parent_body=False, + # TODO: double check with Offset from URDF + offset=NoisyGroupedRayCasterCameraCfg.OffsetCfg( + pos=(0.00, 0.018, -0.1), + rot=( + math.cos(math.radians(60) / 2), # w + 0.0, # x + math.sin(math.radians(60) / 2), # y (pitch 30 deg about Y) + 0.0, # z + ), + convention="world", + ), + data_types=["distance_to_image_plane"], + depth_clipping_behavior="max", # clip to the maximum value + mesh_filter_max_hops=24, + noise_pipeline={ + "crop_and_resize": CropAndResizeCfg( + # (top, bottom, left, right), height/2 and centering width/2 + crop_region=(0, 0, 10, 10), + resize_shape=(30, 30), + ), + "gaussian_blur": GaussianBlurNoiseCfg(kernel_size=3, sigma=1), + "depth_normalization": DepthNormalizationCfg( + depth_range=(0.0, 2.5), + normalize=True, + output_range=(0.0, 1.0), + ), + }, + data_histories={"distance_to_image_plane_noised": 17}, + update_period=1 / 30, + min_distance=0.1, + max_distance=2.5, + debug_vis=play, + ) + undesired_contact_cfg = ContactSensorCfg( + name="undesired_contact_forces", + primary=ContactMatch( + mode="body", + pattern=".*", + entity="robot", + exclude=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + fields=("found", "force"), + reduce="netforce", + track_air_time=False, + history_length=3, + ) + + cfg.scene.sensors = tuple( + s + for s in (cfg.scene.sensors or ()) + if s.name not in ("left_foot_gradient", "right_foot_gradient") + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + terrain_scan, + depth_camera, + undesired_contact_cfg, + ) + + cfg.events["randomize_ray_offsets"] = EventTermCfg( + func=instinct_mdp.randomize_ray_offsets, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("camera"), + "offset_pose_ranges": { + "x": (-0.01, 0.01), + "y": (-0.01, 0.01), + "z": (-0.03, 0.01), + "roll": (-math.radians(2), math.radians(2)), + "pitch": (-math.radians(10), math.radians(10)), + "yaw": (-math.radians(2), math.radians(2)), + }, + "distribution": "uniform", + }, + ) + + # Foothold command — the planner output. + cfg.commands["foothold"] = mdp.FootholdCommandCfg( + entity_name="robot", + terrain_sensor_name="terrain_scan", + contact_sensor_name="feet_ground_contact", + velocity_command_name="twist", + foot_site_names=FOOT_SITES, + gait_period=GAIT_CYCLE_PERIOD, + nominal_height_m=0.9, + lateral_inter_foot_m=0.22, + foot_footprint_m=(0.25, 0.10), + search_window_m=(0.6, 0.6), + elevation_size_m=(1.8, 1.2), + elevation_resolution_m=0.05, + alpha_pos=1.0, + alpha_dcm=0.5, + # Safety-aware terrain scoring (max-pool steepness + footprint + # flatness + soft height feasibility + climb bonus). See + # ``DCMFootholdPlanner`` docstring for the rationale. + alpha_steepness=0.6, + alpha_flatness=4.0, + alpha_height=6.0, + alpha_climb_bonus=1.5, + lateral_pos_weight=2.5, + max_step_height_m=0.25, + climb_velocity_threshold=0.1, + standing_threshold=0.1, + # Adaptive Bézier clearance: 5 cm base on flat ground, +0.5 m/m of + # step height, capped at 20 cm. + apex_clearance_m=0.05, + clearance_scale=0.5, + max_clearance_m=0.20, + pre_apex_lower_window=0.05, + pre_apex_upper_window=0.05, + post_apex_lower_window=0.1, + post_apex_upper_window=0.15, + terrain_decision_threshold=0.1, + debug_vis=play, + ) + + cfg.observations["actor"].concatenate_terms = False + cfg.observations["critic"].concatenate_terms = False + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + ) + + # Privileged critic observation: planner output (body frame). + cfg.observations["critic"].terms["foothold_target"] = ObservationTermCfg( + func=mdp.foothold_target, + params={"command_name": "foothold"}, + ) + + cfg.observations["actor"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + cfg.observations["critic"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + # add "policy" alias for actor obs for instinct compatibility + actor_obs_cfg = cfg.observations.pop("actor") + cfg.observations["policy"] = actor_obs_cfg + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # Pre-train velocity range (paper §III-B.3). + # twist_cmd = cfg.commands["twist"] + # assert isinstance(twist_cmd, UniformVelocityCommandCfg) + # twist_cmd.ranges = UniformVelocityCommandCfg.Ranges( + # lin_vel_x=(-0.3, 1.0), + # lin_vel_y=(-0.3, 0.3), + # ang_vel_z=(-1.0, 1.0), + # heading=None, + # ) + # twist_cmd.resampling_time_range = (8.0, 12.0) + # cfg.curriculum.pop("command_vel", None) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 2.0 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + # cfg.rewards["foot_edge"].weight = -0.5 + cfg.rewards.pop("foot_edge", None) + + cfg.rewards = { + **cfg.rewards, + "feet_slide": RewardTermCfg( + func=instinct_parkour_mdp.feet_slide, + weight=-0.4, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "threshold": 1.0, + }, + ), + # "energy": RewardTermCfg( + # func=parkour_mdp.rewards.motors_power_square, + # weight=-1.0e-8, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ), + # "normalize_by_stiffness": True, + # }, + # ), + "dof_pos_limits": RewardTermCfg( + func=envs_mdp.joint_pos_limits, + weight=-1.0, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + } + + cfg.rewards["foothold_tracking"] = RewardTermCfg( + func=mdp.foothold_tracking, + weight=2.1, + params={ + "command_name": "foothold", + "sigma_stages": [(10.0, 5.0), (20.0, 10.0), (30.0, 15.0)], + "stage_step_counts": [0, 4_000 * 24, 8_000 * 24], + "asset_cfg": SceneEntityCfg( + "robot", + site_names=FOOT_SITES, + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "sensor_name": "feet_ground_contact", + "velocity_command_name": "twist", + "velocity_command_threshold": 0.1, + # "log_csv_path": "foothold_tracking_rewards.csv" if play else None, + }, + ) + # cfg.rewards["track_linear_velocity"].weight = 1.0 + # if "action_rate_l2" in cfg.rewards: + # cfg.rewards["action_rate_l2"].weight = -2.5e-3 + # if "joint_acc_l2" in cfg.rewards: + # cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + # if "dof_torques_l2" in cfg.rewards: + # cfg.rewards["dof_torques_l2"].weight = -4.0e-7 + # if "dof_vel_l2" in cfg.rewards: + # cfg.rewards["dof_vel_l2"].weight = -2.5e-7 + # if "foot_edge" in cfg.rewards: + # cfg.rewards["foot_edge"].weight = -1.5 + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["policy"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_ga_phl_env_cfg(play: bool = False) -> VelocityEnvCfg: + """GA-PHL perceptive locomotion config for VR-M3 12DOF. + + Implements arXiv:2512.07464 (Gait-Adaptive Perceptive Humanoid Locomotion + with Real-Time Under-Base Terrain Reconstruction): + + - Downward-facing under-base depth camera (§III-E): replaces the 60° forward + camera with a 90° downward camera, covering the critical foot-support region. + - Omnidirectional velocity commands with a 3-stage curriculum (§IV-B). + - Reward weights matched to paper Table I as closely as possible using the + existing reward functions in this codebase. + + Based on ``vr_m3_12dof_foothold_env_cfg`` (inherits foothold planner, terrain + scan, depth image obs, and domain randomisation). Not implemented here because + they require framework-level extensions: + - U-Net height-map reconstruction (separate offline model). + - Successive Teacher-Student runner (runner-level, not env-level). + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_map_as_grid, + params={ + "sensor_name": "terrain_scan", + "miss_value": 2.0, + "use_grid": True, + "num_cols": int((1.8 + 1e-6) / 0.05) + 1, + "num_rows": int((1.2 + 1e-6) / 0.05) + 1, + }, + clip=(0.0, 2.0), + history_length=1, + flatten_history_dim=False, + ) + + cfg.observations["critic"].terms.pop("depth_image") + + cfg.commands["foothold"] = mdp.FootholdCommandCfg( + entity_name="robot", + terrain_sensor_name="terrain_scan", + contact_sensor_name="feet_ground_contact", + velocity_command_name="twist", + foot_site_names=FOOT_SITES, + gait_period="policy", + gait_action_name="gait_freq", + nominal_height_m=0.9, + lateral_inter_foot_m=0.18, + foot_footprint_m=(0.20, 0.10), + search_window_m=(0.6, 0.6), + elevation_size_m=(1.8, 1.2), + elevation_resolution_m=0.05, + alpha_pos=1.0, + alpha_dcm=0.5, + # Safety-aware terrain scoring (max-pool steepness + footprint + # flatness + soft height feasibility + climb bonus). See + # ``DCMFootholdPlanner`` docstring for the rationale. + alpha_steepness=0.6, + alpha_flatness=4.0, + alpha_height=6.0, + alpha_climb_bonus=1.5, + lateral_pos_weight=2.5, + max_step_height_m=0.25, + climb_velocity_threshold=0.1, + standing_threshold=0.1, + # Adaptive Bézier clearance: 5 cm base on flat ground, +0.5 m/m of + # step height, capped at 20 cm. + apex_clearance_m=0.05, + clearance_scale=0.5, + max_clearance_m=0.20, + pre_apex_lower_window=0.05, + pre_apex_upper_window=0.05, + post_apex_lower_window=0.1, + post_apex_upper_window=0.15, + terrain_decision_threshold=0.1, + debug_vis=play, + ) + + cfg.rewards["foothold_tracking"] = RewardTermCfg( + func=mdp.foothold_tracking, + weight=2.0, + params={ + "command_name": "foothold", + "sigma_stages": [(10.0, 5.0), (20.0, 10.0), (30.0, 15.0)], + "stage_step_counts": [0, 4_000 * 24, 8_000 * 24], + "asset_cfg": SceneEntityCfg( + "robot", + site_names=FOOT_SITES, + body_names=FOOT_LINK_NAMES, + ), + "sensor_name": "feet_ground_contact", + "velocity_command_name": "twist", + "velocity_command_threshold": 0.1, + "penalty_scale": 1.0, + # "log_csv_path": "foothold_tracking_rewards.csv" if play else None, + }, + ) + + # Route foot_gait and feet_double_support to the learnable phase φ_t so + # the gait reward is consistent with the policy's own internal clock. + cfg.observations["critic"].terms["knee_reference"].params[ + "action_name" + ] = "gait_freq" + cfg.rewards["foot_gait"].params["action_name"] = "gait_freq" + cfg.rewards["feet_double_support"].params["action_name"] = "gait_freq" + cfg.rewards["feet_air_time"].params["action_name"] = "gait_freq" + + cfg.actions["gait_freq"] = mdp.GaitFrequencyActionCfg( + entity_name="robot", + min_frequency=1.0, + max_frequency=1.5, + smooth_alpha=0.2, + default_frequency=1.2, + ) + + # ── 6. Adaptive gait-phase observation (replaces fixed-period phase obs) ── + # Returns [f_t, sin(2π·φ_t), cos(2π·φ_t)] — 3 scalars instead of 2. + # Both policy and critic groups inherit the same proprioceptive terms. + for group_name in ("policy", "critic"): + cfg.observations[group_name].terms.pop("gait_phase", None) + cfg.observations[group_name].terms["adaptive_gait_phase"] = ObservationTermCfg( + func=mdp.adaptive_gait_phase, + params={"action_name": "gait_freq", "command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ) + + # ── 7. Gait action limit penalty ───────────────────────────────────────── + # Small penalty for pushing f_t outside the valid band (paper §III-C). + cfg.rewards["gait_action_limit"] = RewardTermCfg( + func=mdp.gait_action_limit, + weight=-0.25, + params={"action_name": "gait_freq"}, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 4_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for training --- + # cfg.rewards["step_accuracy"].weight = 1.0 + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # NOT work with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-7 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -2.0 + cfg.rewards["self_collisions"].weight = -2.0 + # cfg.rewards["feet_air_time"].weight = 1.0 + # cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["feet_air_time_biped"].weight = 3.0 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards.pop( + "terrain_foot_clearance", None + ) # Not compatible with heightmap-based foothold planning + cfg.rewards.pop("foot_gait", None) # phase-locked, conflicts with foothold planner + cfg.rewards.pop("feet_double_support", None) # same problem + cfg.rewards.pop( + "feet_air_time", None + ) # Remove air time reward which can conflict with foothold planning + + # Experiment with new foothold penalties + cfg.rewards.pop("foot_edge", None) + cfg.rewards["terrain_stumble"].weight = -1.0 + + return cfg + + +def _create_multi_critic_cfg_from_single_critic( + cfg: VelocityEnvCfg, +) -> MultiCriticManagerBasedRlEnvCfg: + """Helper to copy a single-critic config to multi-critic format.""" + new_cfg = MultiCriticManagerBasedRlEnvCfg( + decimation=cfg.decimation, scene=cfg.scene + ) + new_cfg.observations = deepcopy(cfg.observations) + new_cfg.actions = deepcopy(cfg.actions) + new_cfg.events = deepcopy(cfg.events) + new_cfg.sim = deepcopy(cfg.sim) + new_cfg.viewer = deepcopy(cfg.viewer) + new_cfg.episode_length_s = cfg.episode_length_s + new_cfg.rewards = deepcopy(cfg.rewards) + new_cfg.terminations = deepcopy(cfg.terminations) + new_cfg.commands = deepcopy(cfg.commands) + new_cfg.curriculum = deepcopy(cfg.curriculum) + new_cfg.metrics = deepcopy(cfg.metrics) + new_cfg.is_finite_horizon = cfg.is_finite_horizon + new_cfg.scale_rewards_by_dt = cfg.scale_rewards_by_dt + + return new_cfg + + +def _create_critic_terrain_type_mapping( + cfg: MultiCriticManagerBasedRlEnvCfg, + terrain_type_list: list[str] = ["stair", "gap", "rough"], +): + # Use [stair, gap, rough] or [stair_up, stair_down, gap, rough] as the terrain + # types depending on the sub_terrains defined in the terrain generator config. + # In MJLab curriculum mode, each column is deterministically assigned to one + # sub-terrain by `_generate_curriculum_terrains`: + # sub_index = min(where(col / num_cols + 0.001 < cumsum(proportions))) + # `terrain.terrain_types` stores that column index per env, so to bucket envs + # by terrain category we map column_index -> sub_terrain class -> category. + + if terrain_type_list == ["stair", "gap", "rough"]: + terrain_type_mapping: dict[int, list[int]] = { + 0: [], # stair (both up and down) + 1: [], # gap + 2: [], # rough + } + elif terrain_type_list == ["stair_up", "stair_down", "gap", "rough"]: + terrain_type_mapping: dict[int, list[int]] = { + 0: [], # stair_up + 1: [], # stair_down + 2: [], # gap + 3: [], # rough + } + else: + raise ValueError( + "Unsupported terrain_type_list: {}. Only [stair, gap, rough] or " + "[stair_up, stair_down, gap, rough] are supported.".format( + terrain_type_list + ) + ) + + terrain_generator_cfg = cfg.scene.terrain.terrain_generator + if not terrain_generator_cfg.curriculum: + cfg.scene.terrain.terrain_generator.curriculum = True + + sub_terrains: dict[str, SubTerrainCfg] = terrain_generator_cfg.sub_terrains + sub_terrain_cfgs = list(sub_terrains.values()) + proportions = np.array([s.proportion for s in sub_terrain_cfgs], dtype=np.float64) + proportions /= proportions.sum() + cum_proportions = np.cumsum(proportions) + + num_cols = terrain_generator_cfg.num_cols + for col_idx in range(num_cols): + sub_index = int( + np.min(np.where(col_idx / num_cols + 0.001 < cum_proportions)[0]) + ) + class_name = sub_terrain_cfgs[sub_index].__class__.__name__ + if terrain_type_list == ["stair", "gap", "rough"]: + if "Stair" in class_name or "stair" in class_name: + terrain_type_mapping[0].append(col_idx) + elif "Gap" in class_name or "gap" in class_name: + terrain_type_mapping[1].append(col_idx) + else: + terrain_type_mapping[2].append(col_idx) + elif terrain_type_list == ["stair_up", "stair_down", "gap", "rough"]: + if "Stair" in class_name or "stair" in class_name: + if "BoxOpenStairsTerrainCfg" in class_name: + if sub_terrain_cfgs[sub_index].inverted == False: + terrain_type_mapping[0].append(col_idx) # stair_up + else: + terrain_type_mapping[1].append(col_idx) # stair_down + elif "BoxPyramidStairsTerrainCfg" in class_name: + terrain_type_mapping[0].append(col_idx) # stair_up + elif "BoxInvertedPyramidStairsTerrainCfg" in class_name: + terrain_type_mapping[1].append(col_idx) # stair_down + else: + raise ValueError( + "Unsupported stair type in class_name: {}. Only " + "BoxOpenStairsTerrainCfg, BoxPyramidStairsTerrainCfg, and " + "BoxInvertedPyramidStairsTerrainCfg are supported.".format( + class_name + ) + ) + elif class_name == "BoxSteppingStonesTerrainCfg": + terrain_type_mapping[2].append(col_idx) + else: + terrain_type_mapping[3].append(col_idx) + + # Drop empty buckets and re-index keys to be contiguous 0..N-1, so + # critic_labels emitted by the env line up exactly with critic head indices + # (otherwise the model has to clamp OOB labels, silently mis-routing envs). + non_empty = [v for v in terrain_type_mapping.values() if len(v) > 0] + cfg.critic_terrain_type_mapping = {i: v for i, v in enumerate(non_empty)} + if len(cfg.critic_terrain_type_mapping) == 0: + raise ValueError("No valid terrain types found in sub_terrains.") + if len(cfg.critic_terrain_type_mapping) < 2: + raise ValueError( + "At least 2 terrain types are required for multi-critic training." + ) + cfg.num_critics = len(cfg.critic_terrain_type_mapping) + + +def vr_m3_12dof_foothold_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_foothold_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + return cfg + + +def vr_m3_12dof_foothold_sts_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_foothold_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + cfg.observations["teacher_actor"] = deepcopy(cfg.observations["critic"]) + return cfg + + +def vr_m3_12dof_ga_phl_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_ga_phl_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + return cfg + + +def vr_m3_12dof_ga_phl_sts_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_ga_phl_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + cfg.observations["teacher_actor"] = deepcopy(cfg.observations["critic"]) + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 1 — Asymmetric actor-critic sensors + Band-specific DR +# --------------------------------------------------------------------------- + +# Actor sensor: foreground scan (heightmap_site is 0.5 m ahead of pelvis in the +# pelvis body frame, so the grid covers 0–1 m forward and ±0.3 m lateral). +# GridPatternCfg(size=(0.6, 1.0), resolution=0.05) → 13 cols × 21 rows = 273 rays +_HM_NUM_Y = 21 # actor grid rows (fwd/back, y) +_HM_NUM_X = 13 # actor grid cols (left/right, x) + +# Critic sensor: full surrounding scan centered on the pelvis body. +# GridPatternCfg(size=(1.0, 1.0), resolution=0.05) → 21 cols × 21 rows = 441 rays +_HM_CRITIC_NUM_Y = 21 # critic grid rows +_HM_CRITIC_NUM_X = 21 # critic grid cols + + +def vr_m3_12dof_height_map_dwt_dr_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """Asymmetric actor-critic height-map env with DWT band-specific DR. + + Two separate raycasters replace the shared ``terrain_scan``: + + * **Actor** (``terrain_scan_actor``): foreground patch mounted at + ``heightmap_site`` (0.5 m ahead of pelvis), 0.6 × 1.0 m @ 0.05 m + resolution, ``include_geom_groups=(0, 1, 2)`` so the actor can detect + body geometry (self-collision awareness during foothold selection). + The height observation uses DWT band-specific domain randomisation to + simulate the real-sensor high-frequency dropout at stair edges. + + * **Critic** (``terrain_scan_critic``): full surrounding patch mounted at + the pelvis body origin, 1.0 × 1.0 m @ 0.05 m resolution, + ``include_geom_groups=(0,)`` (terrain only — body geometry does not + pollute privileged height values). The critic additionally receives a + log-scaled DWT energy ratio as a terrain-type signal. + """ + from src.tasks.velocity.mdp.terrain_classifier import terrain_energy_ratio + + cfg = vr_m3_12dof_height_map_env_cfg(play=play) + + # Remove the single shared terrain_scan added by the base height-map cfg. + cfg.scene.sensors = tuple(s for s in cfg.scene.sensors if s.name != "terrain_scan") + + # Actor sensor — foreground, groups 0-2 (terrain + body). + terrain_scan_actor = RayCastSensorCfg( + name="terrain_scan_actor", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(0.6, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + # Critic sensor — full surrounding, group 0 only (terrain, no body). + terrain_scan_critic = RayCastSensorCfg( + name="terrain_scan_critic", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(1.0, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0,), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + cfg.scene.sensors = cfg.scene.sensors + (terrain_scan_actor, terrain_scan_critic) + + # Actor obs: DWT band-specific DR from the foreground sensor. + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_scan_dwt_aug, + params={ + "sensor_name": "terrain_scan_actor", + "num_y": _HM_NUM_Y, + "num_x": _HM_NUM_X, + "miss_value": 2.0, + "sigma_hh": 0.15, + "sigma_lh_hl": 0.05, + "sigma_ll": 0.02, + "attenuation_low": 0.3, + "attenuation_high": 1.0, + }, + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic obs: clean surrounding heightmap (privileged, no noise). + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan_critic", "miss_value": 2.0}, + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic obs: DWT energy ratio from the surrounding scan. + cfg.observations["critic"].terms["terrain_energy_ratio"] = ObservationTermCfg( + func=terrain_energy_ratio, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + history_length=5, + ) + + if play: + cfg.observations["actor"].enable_corruption = False + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 2 — DWT Encoder + Band DR +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_full_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT encoder with band-specific DR (Phase 2). + + Extends ``vr_m3_12dof_height_map_dwt_dr_env_cfg`` for use with + ``InstinctOnPolicyRunner`` + ``EncoderActorCritic`` + ``DWTParallelLayer``: + + - Actor ``height_scan``: ``height_scan_dwt_aug_as_grid`` — returns a 2D + ``[B, num_y, num_x]`` grid with band-specific DR applied, so + ``DWTParallelLayer`` can reshape it to ``[B, 1, H, W]`` for + ``DWTHeadModel``. Band DR (σ_hh=0.15, σ_lh_hl=0.05, σ_ll=0.02) + simulates real-sensor high-frequency dropout. + - ``concatenate_terms=False`` on actor (mixed 2-D/1-D terms). + - ``"policy"`` obs-group alias added for the instinct runner. + - Critic unchanged from DWT-DR (clean flat surrounding scan + energy ratio). + """ + from copy import deepcopy as _dc + + cfg = vr_m3_12dof_height_map_dwt_dr_env_cfg(play=play) + + # Band-DR augmented 2D grid for the DWT encoder. + # Returns [B, num_y, num_x]; concatenate_terms=False avoids mixed-rank + # torch.stack — the instinct encoder system processes each component separately. + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_scan_dwt_aug_as_grid, + params={ + "sensor_name": "terrain_scan_actor", + "num_y": _HM_NUM_Y, + "num_x": _HM_NUM_X, + "miss_value": 2.0, + "sigma_hh": 0.15, + "sigma_lh_hl": 0.05, + "sigma_ll": 0.02, + "attenuation_low": 0.3, + "attenuation_high": 1.0, + }, + clip=(0.0, 2.0), + ) + cfg.observations["actor"].concatenate_terms = False + + # "policy" alias for instinct runner (policy_observation_group="policy"). + cfg.observations["policy"] = _dc(cfg.observations["actor"]) + + if play: + cfg.observations["actor"].enable_corruption = False + cfg.observations["policy"].enable_corruption = False + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 3 — Lightweight Obs & Reward Shaping +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_dr_v2_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT-DR v2: Phase 3 observations and reward terms added to the DWT-DR env. + + Builds on ``vr_m3_12dof_height_map_dwt_dr_env_cfg`` with zero architecture + changes. New critic observations (subband energy map, DWT entropy, cross-band + coherence) give the value function richer terrain-type signals at essentially + zero overhead. Both actor and critic gain a richer velocity representation. + Two DWT-based reward terms encourage action smoothness and gait symmetry. + + New critic obs: + * ``subband_energy_map`` — 4-channel squared energy of DWT subbands + * ``dwt_terrain_entropy`` — Shannon entropy of DWT coefficients [B, 1] + * ``dwt_subband_coherence`` — cross-band (LH/HH, HL/HH) coherence [B, 2] + + New actor+critic obs: + * ``base_lin_vel`` replaced by ``base_velocity_dwt_filtered`` [B, 4] + (vel_x, vel_y, vel_z, speed_xy) + + New rewards (both registered with weight=-1.0 — functions return positive): + * ``dwt_action_smoothness`` — penalise high-freq detail energy in actions + * ``dwt_gait_symmetry`` — penalise L/R joint oscillation asymmetry + """ + from src.tasks.velocity.mdp.terrain_classifier import ( + dwt_terrain_entropy, + dwt_subband_coherence, + ) + + cfg = vr_m3_12dof_height_map_dwt_dr_env_cfg(play=play) + + # -- Critic obs: subband energy map (4 × H' × W' flattened) -- + cfg.observations["critic"].terms["subband_energy_map"] = ObservationTermCfg( + func=mdp.subband_energy_map, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic obs: DWT coefficient entropy -- + cfg.observations["critic"].terms["dwt_terrain_entropy"] = ObservationTermCfg( + func=dwt_terrain_entropy, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic obs: cross-band coherence [B, 2] -- + cfg.observations["critic"].terms["dwt_subband_coherence"] = ObservationTermCfg( + func=dwt_subband_coherence, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic: augment base_lin_vel with speed_xy for richer velocity signal [B, 4] -- + # Actor has no linear velocity term (not available from real-robot sensors); + # only the critic gets this privileged signal during training. + cfg.observations["critic"].terms["base_lin_vel"] = ObservationTermCfg( + func=mdp.base_velocity_dwt_filtered, + params={"asset_cfg": SceneEntityCfg("robot")}, + ) + + # -- DWT action smoothness penalty (positive metric, negative weight in cfg) -- + cfg.rewards["dwt_action_smoothness"] = RewardTermCfg( + func=mdp.dwt_action_smoothness, + params={"action_name": "joint_pos", "lambda_hf": 0.01}, + weight=-1.0, + ) + + # -- DWT gait symmetry penalty (positive metric, negative weight in cfg) -- + cfg.rewards["dwt_gait_symmetry"] = RewardTermCfg( + func=mdp.dwt_gait_symmetry, + params={ + "left_cfg": SceneEntityCfg("robot", joint_names=r"left_.*"), + "right_cfg": SceneEntityCfg("robot", joint_names=r"right_.*"), + "lambda_sym": 0.01, + }, + weight=-1.0, + ) + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 4 — 1D Temporal DWT for Proprioceptive Signals +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_proprioceptive_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 4: temporal DWT obs for proprioceptive signals on top of DWT-DR-v2. + + Builds on ``vr_m3_12dof_height_map_dwt_dr_v2_env_cfg`` with zero architecture + and no history_length changes. Adds four new obs terms and one new reward: + + New **actor** obs (deployable — no privileged sensors): + * ``imu_dwt_filtered`` [B, 12] — DWT slow-trend + noise-energy of IMU history + * ``joint_history_dwt`` [B, 48] — DWT slow-trend + fast-transient energy of joint history + + New **critic** obs (privileged / training-only): + * ``grf_dwt_features`` [B, 12] — contact onset-sharpness from foot-force history + + New reward (register with weight=-1.0 to penalise oscillatory GRF): + * ``dwt_contact_quality`` — level-1 DWT HF energy in normal GRF + + All DWT terms use level=1 with the existing history_length=5, which satisfies + the Db4 minimum signal length (T>=4). Increase history_length and level to 2 + (requires T>=5 at level 1 and T>=9 for the level-2 recursion) for finer + frequency resolution. + """ + cfg = vr_m3_12dof_height_map_dwt_dr_v2_env_cfg(play=play) + + # -- Actor obs: DWT-compressed IMU (angular velocity + projected gravity) -- + # base_ang_vel and projected_gravity are already in actor_terms (h=5) and + # will be processed BEFORE this term in the obs group dict, populating their + # history buffers before imu_dwt_filtered reads them. + cfg.observations["actor"].terms["imu_dwt_filtered"] = ObservationTermCfg( + func=mdp.imu_dwt_filtered, + params={"obs_group": "actor", "level": 1}, + ) + + # -- Actor obs: DWT-compressed joint history (position + velocity) -- + cfg.observations["actor"].terms["joint_history_dwt"] = ObservationTermCfg( + func=mdp.joint_history_dwt, + params={"obs_group": "actor", "level": 1}, + ) + + # -- Critic obs: GRF onset-sharpness (critic-only; not deployable) -- + # foot_contact_forces is already in critic_terms (h=5); grf_dwt_features + # is appended AFTER it so the buffer is already updated when this runs. + cfg.observations["critic"].terms["grf_dwt_features"] = ObservationTermCfg( + func=mdp.grf_dwt_features, + params={"obs_group": "critic", "level": 1}, + ) + + # -- Reward: penalise oscillatory GRF (smooth, controlled foot placement) -- + cfg.rewards["dwt_contact_quality"] = RewardTermCfg( + func=mdp.dwt_contact_quality_reward, + params={"sensor_name": "feet_ground_contact", "lambda_quality": 0.005}, + weight=-1.0, + ) + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 5 — Depth Image DWT Encoder +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_depth_map_dwt_enc_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 5: depth map task using DepthDWTHeadModel encoder. + + Observation pipeline is identical to ``vr_m3_12dof_depth_map_env_cfg``. + The DWT encoding happens entirely in the network (``DWTParallelLayer`` + + ``DepthDWTHeadModel`` configured in ``vr_m3_12dof_depth_map_dwt_enc_rl_cfg``). + + Adds ``depth_obstacle_channel`` [B, 225] to the policy obs group as a + pre-computed DWT-based obstacle proximity feature (edge energy × inv-depth). + """ + cfg = vr_m3_12dof_depth_map_env_cfg(play=play) + + cfg.observations["policy"].terms["depth_obstacle_channel"] = ObservationTermCfg( + func=mdp.depth_obstacle_channel, + params={ + "sensor_cfg": SceneEntityCfg("camera"), + "image_h": 30, + "image_w": 30, + "data_type": "distance_to_image_plane_noised", + }, + noise=None, + ) + + return cfg + + +def vr_m3_12dof_foothold_depth_map_dwt_enc_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 5 variant on the foothold base: DepthDWTHeadModel encoder + foothold planner. + + Inherits from ``vr_m3_12dof_foothold_env_cfg`` which already provides the depth + camera, "policy" obs alias, DCM foothold command, and foothold rewards. + + Adds ``depth_obstacle_channel`` [B, 225] to the policy obs group. + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["policy"].terms["depth_obstacle_channel"] = ObservationTermCfg( + func=mdp.depth_obstacle_channel, + params={ + "sensor_cfg": SceneEntityCfg("camera"), + "image_h": 30, + "image_w": 30, + "data_type": "distance_to_image_plane_noised", + }, + noise=None, + ) + + return cfg + +def vr_m3_12dof_foothold_fdf_env_cfg( + play: bool = False, + mask_fraction: float = 0.7, +) -> MultiCriticManagerBasedRlEnvCfg: + """Foothold task with Frequency-Domain Filtering (FDF) on the depth image. + + Replaces the raw delayed depth-image term from ``vr_m3_12dof_foothold_env_cfg`` + with an FFT-based low-pass filtered version (``mdp.depth_image_fft_lowpass_cls``): + a 2D FFT is applied per frame and the outer ``mask_fraction`` of the frequency + spectrum (by radial distance from the DC bin) is zeroed before reconstructing via + inverse FFT. A higher ``mask_fraction`` removes more high-frequency terrain/ + obstacle detail, simulating a lower-bandwidth depth sensor. + + To sweep masking strength (e.g. 0.1 / 0.3 / 0.5 / 0.7), edit this default. + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["actor"] = cfg.observations.pop("policy") + + for group in ("actor", "critic"): + base_term = cfg.observations[group].terms["depth_image"] + cfg.observations[group].terms["depth_image"] = replace( + base_term, + func=mdp.depth_image_fft_lowpass_cls(), + params={**base_term.params, "mask_fraction": mask_fraction}, + ) + + return cfg diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/policy.onnx b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/policy.onnx new file mode 100644 index 0000000000000000000000000000000000000000..c796aa57d007957c49075a8355571e43274628f3 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-10-16_vr_m3_12dof_dwt_foothold/policy.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:103755287ac204179e5014085e6f6201c58f903de2937234e97b31468d091fa8 +size 18840693 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560488.worker-4.1996424.0 b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560488.worker-4.1996424.0 new file mode 100644 index 0000000000000000000000000000000000000000..97a0aa8f9e3d64a0dc072feb2a102a52fbf8d6f2 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/events.out.tfevents.1784560488.worker-4.1996424.0 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8cbc83524f8c814a6d200064aaab207ea2e866a5aa841ea875e4641636b37b7 +size 65314565 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff new file mode 100644 index 0000000000000000000000000000000000000000..cc011430e174e01cbc344e924684199effb2d60f --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/git/mjlab_perceptive_dwt.diff @@ -0,0 +1,30 @@ +--- git commit --- +59c3c413a30c0a375f2365e7f02a02e5023b9634 + + +--- git status --- +On branch dev/fdf +Your branch is up to date with 'origin/dev/fdf'. + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: src/tasks/velocity/config/vr_m3_12dof/__init__.py + +no changes added to commit (use "git add" and/or "git commit -a") + + +--- git diff --- +diff --git a/src/tasks/velocity/config/vr_m3_12dof/__init__.py b/src/tasks/velocity/config/vr_m3_12dof/__init__.py +index a6e8d27..fb837e8 100644 +--- a/src/tasks/velocity/config/vr_m3_12dof/__init__.py ++++ b/src/tasks/velocity/config/vr_m3_12dof/__init__.py +@@ -203,7 +203,7 @@ except (AttributeError, ImportError): + # Frequency Domain Filtering + register_mjlab_task( + task_id="VR-M3-12DOF-Foothold-FDF", +- env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(), ++ env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(mask_fraction=0.7), + play_env_cfg=vr_m3_12dof_foothold_fdf_env_cfg(play=True), + rl_cfg=vr_m3_12dof_foothold_fdf_vr_rsl_rl_runner_cfg(), + runner_cls=VelocityOnPolicyRunner, \ No newline at end of file diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff new file mode 100644 index 0000000000000000000000000000000000000000..7d752229105146469e937c736f4169b4e7cde8e5 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/git/vr_rsl_rl.diff @@ -0,0 +1,12 @@ +--- git commit --- +13b0b308e7cd73f7d4188a8a3cde9a98db717e0f + + +--- git status --- +On branch main +Your branch is up to date with 'origin/main'. + +nothing to commit, working tree clean + + +--- git diff --- diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_0.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_0.pt new file mode 100644 index 0000000000000000000000000000000000000000..81a0611e6fddd1e44dff1c1e09138212fa794084 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_0.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:59f8fa47d84a949190276e6d6838929078ae305d12a964eb72980455d7a0ed23 +size 125693797 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_1000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_1000.pt new file mode 100644 index 0000000000000000000000000000000000000000..bf7ce1f8de5e20c3da419a2abab13c823305c0aa --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_1000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8220cb9f95bd9e931cbdefa1635ccd72199f3c8aee0e9f086175ba14a07f6b2 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_10000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_10000.pt new file mode 100644 index 0000000000000000000000000000000000000000..c2189d9ffbe1189c3fe0c623abb99b35a6c8990f --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_10000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:085bf6118a249068f708989ea027d65f90c0e50c645f0789b5f68a74bd92ede2 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_11000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_11000.pt new file mode 100644 index 0000000000000000000000000000000000000000..7a978792efaa7010934c14e19f3984f3e1f352db --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_11000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47b1774229bfc8de3a8c643a8917b86c86ee8b1ed505608487aeef1a920dc176 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_12000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_12000.pt new file mode 100644 index 0000000000000000000000000000000000000000..b19f7da4048d486bfde2b1dccdfef4234b71924e --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_12000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c22944ac1176ee990dc1e37a8dd40e6c1ae4b5ffd6deabcebf02abc2fb7da5e9 +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_13000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_13000.pt new file mode 100644 index 0000000000000000000000000000000000000000..059ea08d982a53ab267e145f6a60af1d9c58e40c --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_13000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:795cd9835e533a7bae05d985441eacc9b58452e1c8e946752972a9bcd19fc84d +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_14000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_14000.pt new file mode 100644 index 0000000000000000000000000000000000000000..2e55078d23004f5441b6235ed2f41bf4ef064e7b --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_14000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8153d00d87359d31a2d2b8eb320d3d5f5e19c0310b8711e2db63c37c2dc9e1af +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_15000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_15000.pt new file mode 100644 index 0000000000000000000000000000000000000000..8d3756bfc0944fdece333af354379dbbb89a637d --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_15000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f66ee1a0a9a7210f9467e585a623e6b0df4625fa6b617c0a6fb7c543cf67141d +size 125694769 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_2000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_2000.pt new file mode 100644 index 0000000000000000000000000000000000000000..666b2f0b72e2353f594436df4c079e31a8c0ef88 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_2000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67fc618e0f0a9a44a8bfde973b22e5ab4bfbcb1642ac3ab9039521471c66acea +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_3000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_3000.pt new file mode 100644 index 0000000000000000000000000000000000000000..231294ff3cedf66eacb78ba2521db233e8221e85 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_3000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ff5fb6e6ba3f37e3bcd12b91ea5a4f1ea399bbe9834f2b9aa5d12cff75ce1e3 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_4000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_4000.pt new file mode 100644 index 0000000000000000000000000000000000000000..da029f5f5bfa38c79e1956a740489c19f011f9dc --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_4000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b235df4f5a6942c69015d817cf62ad36474ec090f8788a0fc92bee1de07a404 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_5000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_5000.pt new file mode 100644 index 0000000000000000000000000000000000000000..2e2814a4fb2512e5669c7742c5c633c4c6baca33 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_5000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbcb9cdfc28221640609fa4fecd2af301f0f54a05e3961d56a7f3027e67e2c33 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_6000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_6000.pt new file mode 100644 index 0000000000000000000000000000000000000000..af59278bee9a0ca85f7e4425fb1be191f41ee853 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_6000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c045e3e2d37600ae0aa85df5969466988b6341ea02347c8ee016c0d68f948ba +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_7000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_7000.pt new file mode 100644 index 0000000000000000000000000000000000000000..a8d6b525bc8198933c09559645290a0a95c1f2e1 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_7000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fae1fa86c6db83171af621d80529ff125e7b8c9b966e2aac717a4de8bb2347ce +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_8000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_8000.pt new file mode 100644 index 0000000000000000000000000000000000000000..5414315959941fb78031aa7269d199b974a43db2 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_8000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0d16f1a77d5c4defc7cff9a46c498983b491ca7fa5ff466553ba4767b04e98e +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_9000.pt b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_9000.pt new file mode 100644 index 0000000000000000000000000000000000000000..31c6aa5b8e2ac076d33fc06c044ed68ee1d63655 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/model_9000.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54c03a33759f88a37698d5256139dd2a6053c13a6bc566cb36a3b4a2e653d6c7 +size 125694590 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/agent.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/agent.yaml new file mode 100644 index 0000000000000000000000000000000000000000..aa9b9f4a68d6235397146bc0edd8227bbcb7d230 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/agent.yaml @@ -0,0 +1,139 @@ +seed: 42 +num_steps_per_env: 24 +max_iterations: 100001 +obs_groups: + actor: + - base_ang_vel + - projected_gravity + - velocity_commands + - joint_pos_rel + - joint_vel_rel + - last_action + - gait_phase + - depth_image + critic: + - base_ang_vel + - projected_gravity + - velocity_commands + - joint_pos_rel + - joint_vel_rel + - last_action + - gait_phase + - base_lin_vel + - true_base_velocity + - foot_height + - foot_air_time + - foot_contact + - foot_contact_forces + - knee_reference + - height_scan + - foothold_target + - depth_image +save_interval: 1000 +experiment_name: vr_m3_12dof_dwt_foothold +run_name: vr_m3_12dof_dwt_foothold +logger: wandb +wandb_project: vr_m3_12dof +wandb_tags: !!python/tuple [] +resume: false +load_run: .* +load_checkpoint: model_.*.pt +clip_actions: null +upload_model: true +class_name: OnPolicyRunner +actor: + hidden_dims: !!python/tuple + - 1024 + - 512 + - 256 + - 128 + activation: elu + obs_normalization: true + cnn_cfg: + output_channels: !!python/tuple + - 32 + - 32 + kernel_size: !!python/tuple + - 3 + - 3 + stride: !!python/tuple + - 1 + - 1 + dilation: !!python/tuple + - 1 + - 1 + padding: 1 + padding_mode: replicate + norm: none + activation: relu + max_pool: false + max_pool_kernel_size: 3 + max_pool_stride: 2 + max_pool_padding: 0 + global_pool: none + head_output_dim: 64 + head_hidden_dims: + - 128 + - 64 + head_activation: relu + head_last_activation: relu + distribution_cfg: + init_std: 1.0 + std_type: scalar +critic: + hidden_dims: !!python/tuple + - 1024 + - 512 + - 256 + - 128 + activation: elu + obs_normalization: true + cnn_cfg: + output_channels: !!python/tuple + - 32 + - 32 + kernel_size: !!python/tuple + - 3 + - 3 + stride: !!python/tuple + - 1 + - 1 + dilation: !!python/tuple + - 1 + - 1 + padding: 1 + padding_mode: replicate + norm: none + activation: relu + max_pool: false + max_pool_kernel_size: 3 + max_pool_stride: 2 + max_pool_padding: 0 + global_pool: none + head_output_dim: 64 + head_hidden_dims: + - 128 + - 64 + head_activation: relu + head_last_activation: relu + distribution_cfg: + init_std: 1.0 + std_type: scalar +algorithm: + num_learning_epochs: 5 + num_mini_batches: 4 + learning_rate: 0.001 + schedule: adaptive + gamma: 0.99 + lam: 0.95 + entropy_coef: 0.005 + desired_kl: 0.01 + max_grad_norm: 1.0 + value_loss_coef: 1.0 + use_clipped_value_loss: true + clip_param: 0.2 + normalize_advantage_per_mini_batch: false + optimizer: adam + rnd_cfg: null + symmetry_cfg: null +multi_gpu: null diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/deploy.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/deploy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8721661609ecc1b4bb31e459ff96d72dc0a25f45 --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/deploy.yaml @@ -0,0 +1,93 @@ +joint_name: [left_hip_pitch_joint, left_hip_roll_joint, left_hip_yaw_joint, left_knee_pitch_joint, + left_ankle_pitch_joint, left_ankle_roll_joint, right_hip_pitch_joint, right_hip_roll_joint, + right_hip_yaw_joint, right_knee_pitch_joint, right_ankle_pitch_joint, right_ankle_roll_joint] +joint_ids_map: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] +step_dt: 0.02 +stiffness: [150.0, 150.0, 120.0, 200.0, 200.0, 200.0, 150.0, 150.0, 120.0, 200.0, + 200.0, 200.0] +damping: [25.0, 25.0, 4.0, 10.0, 8.0, 8.0, 25.0, 25.0, 4.0, 10.0, 8.0, 8.0] +default_joint_pos: [-0.1, 0.0, 0.0, 0.2, -0.1, 0.0, -0.1, 0.0, 0.0, 0.2, -0.1, 0.0] +commands: + twist: + ranges: + lin_vel_x: [0.0, 1.0] + lin_vel_y: [0.0, 0.0] + ang_vel_z: [-0.5, 0.5] + heading: null +actions: + JointPositionAction: + clip: null + scale: [0.6, 0.6, 0.271, 0.45, 0.15, 0.15, 0.6, 0.6, 0.271, 0.45, 0.15, 0.15] + offset: [-0.1, 0.0, 0.0, 0.2, -0.1, 0.0, -0.1, 0.0, 0.0, 0.2, -0.1, 0.0] + joint_names: [.*] + joint_ids: null +observations: + base_ang_vel: + params: {sensor_name: robot/imu_ang_vel} + clip: null + scale: [0.25, 0.25, 0.25] + history_length: 5 + projected_gravity: + params: {} + clip: null + scale: [1.0, 1.0, 1.0] + history_length: 5 + velocity_commands: + params: {command_name: twist} + clip: null + scale: [1.0, 1.0, 1.0] + history_length: 5 + joint_pos_rel: + params: {} + clip: null + scale: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + history_length: 5 + joint_vel_rel: + params: {} + clip: null + scale: [0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05] + history_length: 5 + last_action: + params: {} + clip: null + scale: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + history_length: 5 + gait_phase: + params: {period: 0.9, command_name: twist} + clip: null + scale: [1.0, 1.0] + history_length: 5 + depth_image: + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice [null, null, null] + body_names: null + body_ids: !!python/object/apply:builtins.slice [null, null, null] + geom_names: null + geom_ids: !!python/object/apply:builtins.slice [null, null, null] + site_names: null + site_ids: !!python/object/apply:builtins.slice [null, null, null] + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice [null, null, null] + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice [null, null, null] + camera_names: null + camera_ids: !!python/object/apply:builtins.slice [null, null, null] + light_names: null + light_ids: !!python/object/apply:builtins.slice [null, null, null] + material_names: null + material_ids: !!python/object/apply:builtins.slice [null, null, null] + pair_names: null + pair_ids: !!python/object/apply:builtins.slice [null, null, null] + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: [0, 1] + debug_vis: false + mask_fraction: 0.7 + clip: null + scale: [1.0, 1.0, 1.0, 1.0] + history_length: 1 diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/env.yaml b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/env.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5f0e04148957ece0a1f407a1721226c346bfda3a --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/env.yaml @@ -0,0 +1,3768 @@ +decimation: 4 +scene: + num_envs: 1024 + env_spacing: 2.0 + terrain: + init_state: + pos: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + rot: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.0 + lin_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + ang_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + joint_pos: + .*: 0.0 + joint_vel: + .*: 0.0 + spec_fn: !!python/name:mjlab.entity.entity.%3Clambda%3E '' + articulation: null + sort_actuators: false + lights: !!python/tuple + - name: sun + body: world + mode: fixed + target: null + type: directional + castshadow: true + pos: !!python/tuple + - 0.0 + - 0.0 + - 1.5 + dir: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + cutoff: 45.0 + exponent: 10.0 + cameras: !!python/tuple [] + textures: !!python/tuple + - name: groundplane + type: 2d + builtin: checker + rgb1: !!python/tuple + - 0.2 + - 0.3 + - 0.4 + rgb2: !!python/tuple + - 0.1 + - 0.2 + - 0.3 + width: 300 + height: 300 + mark: edge + markrgb: !!python/tuple + - 0.8 + - 0.8 + - 0.8 + materials: !!python/tuple + - name: groundplane + rgba: !!python/tuple + - 1.0 + - 1.0 + - 1.0 + - 1.0 + texuniform: true + texrepeat: !!python/tuple + - 4.0 + - 4.0 + reflectance: 0.2 + texture: groundplane + geom_names_expr: !!python/tuple + - terrain$ + collisions: !!python/tuple [] + terrain_type: generator + terrain_generator: + seed: null + curriculum: true + size: !!python/tuple + - 8.0 + - 8.0 + border_width: 1.0 + border_height: 1.0 + num_rows: 10 + num_cols: 14 + color_scheme: height + sub_terrains: + flat: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + pyramid_stairs: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.3 + platform_width: 3.0 + holes: false + pyramid_stairs_med: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.45 + platform_width: 3.0 + holes: false + pyramid_stairs_wide: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.6 + platform_width: 3.0 + holes: false + pyramid_stairs_inv: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.3 + platform_width: 3.0 + holes: false + pyramid_stairs_inv_med: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.45 + platform_width: 3.0 + holes: false + pyramid_stairs_inv_wide: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 20 + patch_radius: 0.15 + max_height_diff: 0.02 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + border_width: 1.0 + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width: 0.6 + platform_width: 3.0 + holes: false + open_stairs_pyramid: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width_range: !!python/tuple + - 0.3 + - 0.6 + platform_width: 3.0 + border_width: 1.0 + step_thickness: 0.05 + inverted: false + open_stairs_bowl: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + step_height_range: !!python/tuple + - 0.05 + - 0.2 + step_width_range: !!python/tuple + - 0.3 + - 0.6 + platform_width: 3.0 + border_width: 1.0 + step_thickness: 0.05 + inverted: true + hf_pyramid_slope: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + slope_range: !!python/tuple + - 0.0 + - 0.4 + platform_width: 2.0 + inverted: false + border_width: 0.25 + horizontal_scale: 0.2 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + hf_pyramid_slope_inv: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + slope_range: !!python/tuple + - 0.0 + - 0.4 + platform_width: 2.0 + inverted: true + border_width: 0.25 + horizontal_scale: 0.2 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + stepping_stones: + proportion: 0.1 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: + target: + num_patches: 30 + patch_radius: 0.2 + max_height_diff: 0.03 + x_range: !!python/tuple + - -1000000.0 + - 1000000.0 + y_range: !!python/tuple + - -1000000.0 + - 1000000.0 + z_range: !!python/tuple + - -1000000.0 + - 1000000.0 + grid_resolution: null + stone_size_range: !!python/tuple + - 0.4 + - 0.8 + stone_distance_range: !!python/tuple + - 0.2 + - 0.5 + stone_height: 0.2 + stone_height_variation: 0.05 + stone_size_variation: 0.1 + floor_depth: 2.0 + displacement_range: 0.1 + platform_width: 1.0 + border_width: 0.0 + uniform_noise: + proportion: 0.15 + size: !!python/tuple + - 8.0 + - 8.0 + flat_patch_sampling: null + noise_range: !!python/tuple + - 0.02 + - 0.1 + noise_step: 0.02 + downsampled_scale: null + horizontal_scale: 0.1 + vertical_scale: 0.005 + base_thickness_ratio: 1.0 + border_width: 0.25 + difficulty_range: !!python/tuple + - 0.0 + - 1.0 + add_lights: true + env_spacing: 2.0 + max_init_terrain_level: 5 + num_envs: 1024 + entities: + robot: + init_state: + pos: !!python/tuple + - 0 + - 0 + - 0.9 + rot: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.0 + lin_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + ang_vel: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + joint_pos: + .*_hip_pitch_joint: -0.1 + .*_hip_roll_joint: 0.0 + .*_hip_yaw_joint: 0.0 + .*_knee_pitch_joint: 0.2 + .*_ankle_pitch_joint: -0.1 + .*_ankle_roll_joint: 0.0 + joint_vel: + .*: 0.0 + spec_fn: !!python/name:src.assets.robots.vr_m3.vr_m3_12dof_constants.get_spec '' + articulation: + actuators: !!python/tuple + - target_names_expr: !!python/tuple + - .*_hip_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 150.0 + damping: 25.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_hip_roll_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 150.0 + damping: 25.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_hip_yaw_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.02864 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 120.0 + damping: 4.0 + effort_limit: 130.0 + - target_names_expr: !!python/tuple + - .*_knee_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.1404 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 10.0 + effort_limit: 360.0 + - target_names_expr: !!python/tuple + - .*_ankle_pitch_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.03006 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 8.0 + effort_limit: 120.0 + - target_names_expr: !!python/tuple + - .*_ankle_roll_joint + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + armature: 0.03006 + frictionloss: 0.1 + viscous_damping: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + stiffness: 200.0 + damping: 8.0 + effort_limit: 120.0 + soft_joint_pos_limit_factor: 0.9 + sort_actuators: false + lights: !!python/tuple [] + cameras: !!python/tuple [] + textures: !!python/tuple [] + materials: !!python/tuple [] + collisions: !!python/tuple + - geom_names_expr: !!python/tuple + - .*_collision_\d+ + contype: 1 + conaffinity: 1 + condim: + ^(left|right)_ankle_roll_link_collision_\d+$: 3 + .*_collision_\d+: 1 + priority: + ^(left|right)_ankle_roll_link_collision_\d+$: 1 + friction: + ^(left|right)_ankle_roll_link_collision_\d+$: !!python/tuple + - 0.6 + solref: null + solimp: null + margin: null + gap: null + solmix: null + disable_other_geoms: true + sensors: !!python/tuple + - name: feet_ground_contact + primary: + mode: subtree + pattern: ^(left_ankle_roll_link|right_ankle_roll_link)$ + entity: robot + exclude: !!python/tuple [] + secondary: + mode: body + pattern: terrain + entity: null + exclude: !!python/tuple [] + fields: !!python/tuple + - found + - force + reduce: netforce + num_slots: 1 + secondary_policy: first + track_air_time: true + global_frame: false + history_length: 4 + debug: false + - name: self_collision + primary: + mode: subtree + pattern: pelvis + entity: robot + exclude: !!python/tuple [] + secondary: + mode: subtree + pattern: pelvis + entity: robot + exclude: !!python/tuple [] + fields: !!python/tuple + - found + - force + reduce: none + num_slots: 1 + secondary_policy: first + track_air_time: false + global_frame: false + history_length: 4 + debug: false + - name: pelvis_height_measure + frame: + type: body + name: pelvis + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 2.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: left_height_scanner + frame: + type: site + name: left_foot + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 1.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: right_height_scanner + frame: + type: site + name: right_foot + entity: robot + pattern: + size: !!python/tuple + - 0.0 + - 0.0 + resolution: 0.1 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 1.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: terrain_scan + frame: + type: body + name: pelvis + entity: robot + pattern: + size: !!python/tuple + - 1.8 + - 1.2 + resolution: 0.05 + direction: !!python/tuple + - 0.0 + - 0.0 + - -1.0 + ray_alignment: yaw + max_distance: 2.0 + exclude_parent_body: true + include_geom_groups: !!python/tuple + - 0 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: true + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + - name: camera + frame: + type: body + name: pelvis + entity: robot + pattern: + width: 80 + height: 60 + fovy: 63.668103675039276 + _camera_name: null + ray_alignment: base + max_distance: 2.5 + exclude_parent_body: false + include_geom_groups: !!python/tuple + - 0 + - 1 + - 2 + debug_vis: false + viz: + hit_color: !!python/tuple + - 0.0 + - 1.0 + - 0.0 + - 0.8 + miss_color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 0.4 + hit_sphere_color: !!python/tuple + - 0.0 + - 1.0 + - 1.0 + - 1.0 + hit_sphere_radius: 0.5 + show_rays: false + show_normals: false + normal_color: !!python/tuple + - 1.0 + - 1.0 + - 0.0 + - 1.0 + normal_length: 5.0 + class_type: !!python/name:instinct_mj.sensors.noisy_camera.noisy_grouped_raycaster_camera.NoisyGroupedRayCasterCamera '' + min_distance: 0.1 + mesh_prim_paths: [] + aux_mesh_and_link_names: {} + mesh_filter_max_hops: 24 + mesh_filter_epsilon: 0.0001 + offset: + pos: !!python/tuple + - 0.0 + - 0.018 + - -0.1 + rot: !!python/tuple + - 0.8660254037844387 + - 0.0 + - 0.49999999999999994 + - 0.0 + convention: world + data_types: + - distance_to_image_plane + update_period: 0.03333333333333333 + depth_clipping_behavior: max + focal_length: 1.0 + horizontal_aperture: 1.6555983034386739 + vertical_aperture: 1.2416987275790055 + horizontal_aperture_offset: 0.0 + vertical_aperture_offset: 0.0 + visualizer_cfg: + prim_path: /Visuals/RayCaster + markers: + hit: !!python/object/apply:types.SimpleNamespace + state: + radius: 0.02 + color: !!python/tuple + - 1.0 + - 0.0 + - 0.0 + - 1.0 + frame: !!python/object/apply:types.SimpleNamespace + state: + scale: !!python/tuple + - 0.1 + - 0.1 + - 0.1 + noise_pipeline: + crop_and_resize: + func: !!python/name:instinct_mj.utils.noise.noise_model.crop_and_resize '' + device: cuda:0 + crop_region: !!python/tuple + - 0 + - 0 + - 10 + - 10 + resize_shape: !!python/tuple + - 30 + - 30 + gaussian_blur: + func: !!python/name:instinct_mj.utils.noise.noise_model.gaussian_blur_noise '' + device: cuda:0 + kernel_size: 3 + sigma: 1 + depth_normalization: + func: !!python/name:instinct_mj.utils.noise.noise_model.depth_normalization '' + device: cuda:0 + depth_range: !!python/tuple + - 0.0 + - 2.5 + normalize: true + output_range: !!python/tuple + - 0.0 + - 1.0 + data_histories: + distance_to_image_plane_noised: 17 + - name: undesired_contact_forces + primary: + mode: body + pattern: .* + entity: robot + exclude: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + secondary: null + fields: !!python/tuple + - found + - force + reduce: netforce + num_slots: 1 + secondary_policy: first + track_air_time: false + global_frame: false + history_length: 3 + debug: false + extent: 2.0 + spec_fn: null +observations: + critic: + terms: + base_ang_vel: + func: &id001 !!python/name:mjlab.envs.mdp.observations.builtin_sensor '' + params: + sensor_name: robot/imu_ang_vel + noise: + operation: add + _tensor_cache: {} + n_min: -0.25 + n_max: 0.25 + clip: null + scale: 0.25 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + projected_gravity: + func: &id002 !!python/name:mjlab.envs.mdp.observations.projected_gravity '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + velocity_commands: + func: &id003 !!python/name:mjlab.envs.mdp.observations.generated_commands '' + params: + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_pos_rel: + func: &id004 !!python/name:mjlab.envs.mdp.observations.joint_pos_rel '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_vel_rel: + func: &id005 !!python/name:mjlab.envs.mdp.observations.joint_vel_rel '' + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -1.5 + n_max: 1.5 + clip: null + scale: 0.05 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + last_action: + func: &id006 !!python/name:mjlab.envs.mdp.observations.last_action '' + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + gait_phase: + func: &id007 !!python/name:src.tasks.velocity.mdp.observations.phase '' + params: + period: 0.9 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + base_lin_vel: + func: *id001 + params: + sensor_name: robot/imu_lin_vel + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + true_base_velocity: + func: !!python/name:mjlab.envs.mdp.observations.base_lin_vel '' + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_height: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_height '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_air_time: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_air_time '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_contact: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_contact '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + foot_contact_forces: + func: !!python/name:src.tasks.velocity.mdp.observations.foot_contact_forces '' + params: + sensor_name: feet_ground_contact + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + knee_reference: + func: !!python/name:src.tasks.velocity.mdp.rewards.get_desired_knee_angle '' + params: + period: 0.9 + offset: + - 0.0 + - 0.5 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + height_scan: + func: !!python/name:mjlab.envs.mdp.observations.height_scan '' + params: + sensor_name: terrain_scan + miss_value: 2.0 + noise: null + clip: !!python/tuple + - 0.0 + - 2.0 + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + foothold_target: + func: !!python/name:src.tasks.velocity.mdp.observations.foothold_target '' + params: + command_name: foothold + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + depth_image: + func: !!python/name:src.tasks.velocity.mdp.observations.DepthImageFFTLowpass '' + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: !!python/tuple + - 0 + - 1 + debug_vis: false + mask_fraction: 0.7 + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + concatenate_terms: false + concatenate_dim: -1 + enable_corruption: false + history_length: null + flatten_history_dim: true + nan_policy: sanitize + nan_check_per_term: true + actor: + terms: + base_ang_vel: + func: *id001 + params: + sensor_name: robot/imu_ang_vel + noise: + operation: add + _tensor_cache: {} + n_min: -0.25 + n_max: 0.25 + clip: null + scale: 0.25 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + projected_gravity: + func: *id002 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + velocity_commands: + func: *id003 + params: + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_pos_rel: + func: *id004 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -0.05 + n_max: 0.05 + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + joint_vel_rel: + func: *id005 + params: {} + noise: + operation: add + _tensor_cache: {} + n_min: -1.5 + n_max: 1.5 + clip: null + scale: 0.05 + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + last_action: + func: *id006 + params: {} + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + gait_phase: + func: *id007 + params: + period: 0.9 + command_name: twist + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 5 + flatten_history_dim: true + depth_image: + func: !!python/name:src.tasks.velocity.mdp.observations.DepthImageFFTLowpass '' + params: + data_type: distance_to_image_plane_noised_history + sensor_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + history_skip_frames: 5 + num_output_frames: 4 + delayed_frame_ranges: !!python/tuple + - 0 + - 1 + debug_vis: false + mask_fraction: 0.7 + noise: null + clip: null + scale: null + delay_min_lag: 0 + delay_max_lag: 0 + delay_per_env: true + delay_hold_prob: 0.0 + delay_update_period: 0 + delay_per_env_phase: true + history_length: 0 + flatten_history_dim: true + concatenate_terms: false + concatenate_dim: -1 + enable_corruption: true + history_length: null + flatten_history_dim: true + nan_policy: sanitize + nan_check_per_term: true +actions: + joint_pos: + entity_name: robot + clip: null + transmission_type: !!python/object/apply:mjlab.actuator.actuator.TransmissionType + - joint + actuator_names: !!python/tuple + - .* + scale: + .*_hip_pitch_joint: 0.6 + .*_hip_roll_joint: 0.6 + .*_hip_yaw_joint: 0.2708333333333333 + .*_knee_pitch_joint: 0.45 + .*_ankle_pitch_joint: 0.15 + .*_ankle_roll_joint: 0.15 + offset: 0.0 + preserve_order: false + use_default_offset: true +events: + reset_base: + func: !!python/name:mjlab.envs.mdp.events.reset_root_state_uniform '' + params: + pose_range: + x: !!python/tuple + - -0.5 + - 0.5 + y: !!python/tuple + - -0.5 + - 0.5 + z: !!python/tuple + - 0.0 + - 0.0 + yaw: !!python/tuple + - -3.14 + - 3.14 + mode: reset + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + reset_robot_joints: + func: !!python/name:mjlab.envs.mdp.events.reset_joints_by_offset '' + params: + position_range: !!python/tuple + - -0.1 + - 0.1 + velocity_range: !!python/tuple + - -0.5 + - 0.5 + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + mode: reset + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + push_robot: + func: !!python/name:mjlab.envs.mdp.events.push_by_setting_velocity '' + params: + velocity_range: + x: !!python/tuple + - -0.5 + - 0.5 + y: !!python/tuple + - -0.5 + - 0.5 + z: !!python/tuple + - -0.4 + - 0.4 + roll: !!python/tuple + - -0.52 + - 0.52 + pitch: !!python/tuple + - -0.52 + - 0.52 + yaw: !!python/tuple + - -0.78 + - 0.78 + mode: interval + interval_range_s: !!python/tuple + - 5.0 + - 6.0 + is_global_time: false + min_step_count_between_reset: 0 + foot_friction: + func: !!python/name:mjlab.envs.mdp.dr.geom.geom_friction '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: !!python/tuple + - left_ankle_roll_link_collision_1 + - left_ankle_roll_link_collision_2 + - left_ankle_roll_link_collision_3 + - left_ankle_roll_link_collision_4 + - left_ankle_roll_link_collision_5 + - left_ankle_roll_link_collision_6 + - left_ankle_roll_link_collision_7 + - left_ankle_roll_link_collision_8 + - left_ankle_roll_link_collision_9 + - left_ankle_roll_link_collision_10 + - right_ankle_roll_link_collision_1 + - right_ankle_roll_link_collision_2 + - right_ankle_roll_link_collision_3 + - right_ankle_roll_link_collision_4 + - right_ankle_roll_link_collision_5 + - right_ankle_roll_link_collision_6 + - right_ankle_roll_link_collision_7 + - right_ankle_roll_link_collision_8 + - right_ankle_roll_link_collision_9 + - right_ankle_roll_link_collision_10 + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: abs + ranges: !!python/tuple + - 0.3 + - 1.6 + shared_random: true + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + encoder_bias: + func: !!python/name:mjlab.envs.mdp.dr.joint.encoder_bias '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + bias_range: !!python/tuple + - -0.015 + - 0.015 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + base_com: + func: &id008 !!python/name:mjlab.envs.mdp.dr.body.body_com_offset '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: + 0: !!python/tuple + - -0.05 + - 0.05 + 1: !!python/tuple + - -0.05 + - 0.05 + 2: !!python/tuple + - -0.05 + - 0.05 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + body_com: + func: *id008 + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - ^(?!waist_yaw_link$).* + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: + 0: !!python/tuple + - -0.03 + - 0.03 + 1: !!python/tuple + - -0.03 + - 0.03 + 2: !!python/tuple + - -0.03 + - 0.03 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + base_mass: + func: &id009 !!python/name:mjlab.envs.mdp.dr.body.body_mass '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: add + ranges: !!python/tuple + - -4.0 + - 4.0 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + body_mass: + func: *id009 + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - ^(?!waist_yaw_link$).* + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.9 + - 1.1 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_actuator_gains: + func: !!python/name:mjlab.envs.mdp.dr.actuator.pd_gains '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + kp_range: !!python/tuple + - 0.7 + - 1.1 + kd_range: !!python/tuple + - 0.7 + - 1.1 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_limit: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_limits '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.94 + - 1.06 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_stiffness: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_stiffness '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.7 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_frictionloss: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_friction '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.1 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_armature: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_armature '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.2 + - 5.0 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_joint_damping: + func: !!python/name:mjlab.envs.mdp.dr.joint.joint_damping '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + operation: scale + ranges: !!python/tuple + - 0.7 + - 1.3 + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 + randomize_ray_offsets: + func: !!python/name:instinct_mj.envs.mdp.events.randomization.randomize_ray_offsets '' + params: + asset_cfg: + name: camera + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + offset_pose_ranges: + x: !!python/tuple + - -0.01 + - 0.01 + y: !!python/tuple + - -0.01 + - 0.01 + z: !!python/tuple + - -0.03 + - 0.01 + roll: !!python/tuple + - -0.03490658503988659 + - 0.03490658503988659 + pitch: !!python/tuple + - -0.17453292519943295 + - 0.17453292519943295 + yaw: !!python/tuple + - -0.03490658503988659 + - 0.03490658503988659 + distribution: uniform + mode: startup + interval_range_s: null + is_global_time: false + min_step_count_between_reset: 0 +seed: 42 +sim: + nconmax: 128 + njmax: 700 + ls_parallel: true + contact_sensor_maxmatch: 500 + mujoco: + timestep: 0.005 + integrator: implicitfast + impratio: 1.0 + cone: pyramidal + jacobian: auto + solver: newton + iterations: 10 + tolerance: 1.0e-08 + ls_iterations: 20 + ls_tolerance: 0.01 + ccd_iterations: 500 + gravity: !!python/tuple + - 0.0 + - 0.0 + - -9.81 + disableflags: !!python/tuple [] + enableflags: !!python/tuple [] + nan_guard: + enabled: false + buffer_size: 100 + output_dir: /tmp/mjlab/nan_dumps + max_envs_to_dump: 5 +viewer: + lookat: !!python/tuple + - 0.0 + - 0.0 + - 0.0 + distance: 3.0 + fovy: null + elevation: -5.0 + azimuth: 90.0 + origin_type: !!python/object/apply:mjlab.viewer.viewer_config.OriginType + - 4 + entity_name: robot + body_name: waist_yaw_link + env_idx: 0 + max_extra_envs: 2 + enable_reflections: true + enable_shadows: true + height: 240 + width: 320 +episode_length_s: 20.0 +rewards: + track_linear_velocity: + func: !!python/name:src.tasks.velocity.mdp.rewards.track_linear_velocity '' + params: + command_name: twist + std: 0.5 + weight: 3.5 + track_angular_velocity: + func: !!python/name:src.tasks.velocity.mdp.rewards.track_angular_velocity '' + params: + command_name: twist + std: 0.7071067811865476 + weight: 3.0 + flat_orientation: + func: !!python/name:mjlab.envs.mdp.rewards.flat_orientation_l2 '' + params: {} + weight: -7.0 + pelvis_orientation_l2: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.link_orientation '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: pelvis + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -3.0 + joint_deviation_hip: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.joint_deviation_square '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .*_hip_yaw_joint + - .*_hip_roll_joint + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.3 + ang_vel_xy_l2: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.ang_vel_xy_l2 '' + params: {} + weight: -0.1 + dof_torques_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_torques_l2 '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .*_hip_.* + - .*_knee_.* + - .*_ankle_.* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0e-08 + dof_vel_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_vel_l2 '' + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -5.0e-07 + feet_flat_ori: + func: !!python/name:src.tasks.velocity.mdp.instinct_reward.feet_orientation_contact '' + params: + sensor_name: feet_ground_contact + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.01 + body_ang_vel: + func: !!python/name:src.tasks.velocity.mdp.rewards.body_angular_velocity_penalty '' + params: + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - waist_yaw_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.05 + angular_momentum: + func: !!python/name:src.tasks.velocity.mdp.rewards.angular_momentum_penalty '' + params: + sensor_name: robot/root_angmom + weight: -0.001 + is_terminated: + func: !!python/name:mjlab.envs.mdp.rewards.is_terminated '' + params: {} + weight: -200.0 + joint_acc_l2: + func: !!python/name:mjlab.envs.mdp.rewards.joint_acc_l2 '' + params: {} + weight: -5.0e-07 + joint_pos_limits: + func: &id010 !!python/name:mjlab.envs.mdp.rewards.joint_pos_limits '' + params: {} + weight: -1.0 + action_rate_l2: + func: !!python/name:mjlab.envs.mdp.rewards.action_rate_l2 '' + params: {} + weight: -0.8 + foot_gait: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_gait '' + params: + period: 0.9 + offset: + - 0.0 + - 0.5 + threshold: 0.6 + command_threshold: 0.1 + command_name: twist + sensor_name: feet_ground_contact + weight: 2.0 + feet_double_support: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_double_support '' + params: + sensor_name: feet_ground_contact + period: 0.9 + offset: + - 0.0 + - 0.5 + threshold: 0.6 + command_name: twist + cmd_threshold: 0.1 + ds_match_weight: 1.0 + weight: 1.5 + foot_slip: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_slip '' + params: + sensor_name: feet_ground_contact + command_name: twist + command_threshold: 0.1 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.4 + feet_close_xy: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_close_xy_gauss '' + params: + threshold: 0.2 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + std: 0.22360679774997896 + weight: 1.0 + soft_landing: + func: !!python/name:src.tasks.velocity.mdp.rewards.soft_landing '' + params: + sensor_name: feet_ground_contact + command_name: twist + command_threshold: 0.1 + weight: -0.001 + dont_wait: + func: !!python/name:src.tasks.velocity.mdp.rewards.dont_wait '' + params: + command_name: twist + cmd_threshold: 0.1 + weight: -1.0 + stand_still: + func: !!python/name:src.tasks.velocity.mdp.rewards.stand_still '' + params: + command_name: twist + command_threshold: 0.1 + asset_cfg: + name: robot + joint_names: .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0 + self_collisions: + func: !!python/name:src.tasks.velocity.mdp.rewards.self_collision_cost '' + params: + sensor_name: self_collision + force_threshold: 10.0 + weight: -2.0 + feet_air_time: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_air_time '' + params: + sensor_name: feet_ground_contact + threshold: 0.36000000000000004 + command_name: twist + command_threshold: 0.1 + weight: 1.0 + feet_air_time_biped: + func: !!python/name:src.tasks.velocity.mdp.rewards.feet_air_time_positive_biped '' + params: + command_name: twist + sensor_name: feet_ground_contact + threshold: 0.52 + weight: 2.0 + terrain_foot_clearance: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_foot_clearance_cost '' + params: + target_clearance: 0.06 + left_terrain_sensor: left_height_scanner + right_terrain_sensor: right_height_scanner + command_name: twist + command_threshold: 0.05 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -0.5 + terrain_stumble: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_stumble_cost '' + params: + sensor_cfg: + name: feet_ground_contact + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + velocity_threshold: 0.15 + weight: -0.5 + terrain_base_height: + func: !!python/name:src.tasks.velocity.mdp.rewards.terrain_base_height_l2_cost '' + params: + target_height: 0.9 + base_terrain_sensor: pelvis_height_measure + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.5 + feet_slide: + func: !!python/name:instinct_mj.tasks.parkour.mdp.rewards.feet_slide '' + params: + sensor_name: feet_ground_contact + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + threshold: 1.0 + weight: -0.4 + dof_pos_limits: + func: *id010 + params: + asset_cfg: + name: robot + joint_names: !!python/tuple + - .* + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: null + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: null + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + weight: -1.0 + foothold_tracking: + func: !!python/name:src.tasks.velocity.mdp.rewards.foothold_tracking '' + params: + command_name: foothold + sigma_stages: + - !!python/tuple + - 10.0 + - 5.0 + - !!python/tuple + - 20.0 + - 10.0 + - !!python/tuple + - 30.0 + - 15.0 + stage_step_counts: + - 0 + - 96000 + - 192000 + asset_cfg: + name: robot + joint_names: null + joint_ids: !!python/object/apply:builtins.slice + - null + - null + - null + body_names: !!python/tuple + - left_ankle_roll_link + - right_ankle_roll_link + body_ids: !!python/object/apply:builtins.slice + - null + - null + - null + geom_names: null + geom_ids: !!python/object/apply:builtins.slice + - null + - null + - null + site_names: !!python/tuple + - left_foot + - right_foot + site_ids: !!python/object/apply:builtins.slice + - null + - null + - null + actuator_names: null + actuator_ids: !!python/object/apply:builtins.slice + - null + - null + - null + tendon_names: null + tendon_ids: !!python/object/apply:builtins.slice + - null + - null + - null + camera_names: null + camera_ids: !!python/object/apply:builtins.slice + - null + - null + - null + light_names: null + light_ids: !!python/object/apply:builtins.slice + - null + - null + - null + material_names: null + material_ids: !!python/object/apply:builtins.slice + - null + - null + - null + pair_names: null + pair_ids: !!python/object/apply:builtins.slice + - null + - null + - null + preserve_order: false + sensor_name: feet_ground_contact + velocity_command_name: twist + velocity_command_threshold: 0.1 + weight: 2.1 +terminations: + time_out: + func: !!python/name:mjlab.envs.mdp.terminations.time_out '' + params: {} + time_out: true + fell_over: + func: !!python/name:mjlab.envs.mdp.terminations.bad_orientation '' + params: + limit_angle: 1.2217304763960306 + time_out: false + nan_term: + func: !!python/name:mjlab.envs.mdp.terminations.nan_detection '' + params: {} + time_out: false + base_height: + func: !!python/name:src.tasks.velocity.mdp.rewards.root_height_below_minimum_terrain '' + params: + minimum_height: 0.3 + terrain_sensor_name: pelvis_height_measure + time_out: false +commands: + twist: + resampling_time_range: !!python/tuple + - 3.0 + - 8.0 + debug_vis: true + entity_name: robot + heading_command: false + heading_control_stiffness: 0.5 + rel_standing_envs: 0.05 + rel_heading_envs: 1.0 + rel_world_envs: 0.0 + rel_forward_envs: 0.0 + init_velocity_prob: 0.0 + ranges: + lin_vel_x: !!python/tuple + - 0.0 + - 1.0 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.5 + - 0.5 + heading: null + viz: + z_offset: 1.15 + scale: 0.5 + foothold: + resampling_time_range: !!python/tuple + - 1000000000.0 + - 1000000000.0 + debug_vis: false + entity_name: robot + terrain_sensor_name: terrain_scan + contact_sensor_name: feet_ground_contact + velocity_command_name: twist + foot_site_names: !!python/tuple + - left_foot + - right_foot + gait_period: 0.9 + gait_action_name: gait_freq + nominal_height_m: 0.9 + lateral_inter_foot_m: 0.22 + foot_footprint_m: !!python/tuple + - 0.25 + - 0.1 + search_window_m: !!python/tuple + - 0.6 + - 0.6 + elevation_size_m: !!python/tuple + - 1.8 + - 1.2 + elevation_resolution_m: 0.05 + alpha_pos: 1.0 + alpha_dcm: 0.5 + alpha_steepness: 0.6 + alpha_flatness: 4.0 + alpha_height: 6.0 + alpha_climb_bonus: 1.5 + lateral_pos_weight: 2.5 + max_step_height_m: 0.25 + climb_velocity_threshold: 0.1 + standing_threshold: 0.1 + min_step_height_m: 0.05 + max_step_velocity_m_s: 0.5 + apex_clearance_m: 0.05 + clearance_scale: 0.5 + max_clearance_m: 0.2 + pre_apex_lower_window: 0.05 + pre_apex_upper_window: 0.05 + post_apex_lower_window: 0.1 + post_apex_upper_window: 0.15 + terrain_decision_threshold: 0.1 +curriculum: + terrain_levels: + func: !!python/name:src.tasks.velocity.mdp.curriculums.terrain_levels_vel '' + params: + command_name: twist + command_vel: + func: !!python/name:src.tasks.velocity.mdp.curriculums.commands_vel '' + params: + command_name: twist + velocity_stages: + - step: 0 + lin_vel_x: !!python/tuple + - 0.0 + - 0.5 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.2 + - 0.2 + - step: 120000 + lin_vel_x: !!python/tuple + - 0.0 + - 1.0 + lin_vel_y: !!python/tuple + - 0.0 + - 0.0 + ang_vel_z: !!python/tuple + - -0.5 + - 0.5 +metrics: + mean_action_acc: + func: !!python/name:mjlab.envs.mdp.metrics.mean_action_acc '' + params: {} + per_substep: false + reduce: mean +recorders: {} +is_finite_horizon: false +auto_reset: true +scale_rewards_by_dt: true diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/env_cfgs.py b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/env_cfgs.py new file mode 100644 index 0000000000000000000000000000000000000000..29089b5f5af0e3df29b5cbf63f61fd363ef389ab --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/params/env_cfgs.py @@ -0,0 +1,2716 @@ +"""VinRobotics VR-M3 12DOF (lower-body only) velocity environment configurations. + +Self-contained: this module builds the full `ManagerBasedRlEnvCfg` inline +rather than deriving from `src.tasks.velocity.velocity_env_cfg`, so changes +to the shared factory do not silently affect VR-M3 12DOF training. +""" + +import math +from copy import deepcopy +from dataclasses import dataclass, replace +import numpy as np + +import instinct_mj.envs.mdp as instinct_mdp + +# import instinct_mj.tasks.locomotion.mdp as instinct_locomotion_mdp +try: + import instinct_mj.tasks.parkour.mdp as instinct_parkour_mdp +except ImportError: + instinct_parkour_mdp = None # type: ignore[assignment] +from instinct_mj.sensors.noisy_camera import NoisyGroupedRayCasterCameraCfg +from instinct_mj.utils.noise import ( + CropAndResizeCfg, + DepthArtifactNoiseCfg, + DepthContourNoiseCfg, + DepthNormalizationCfg, + DepthSkyArtifactNoiseCfg, + GaussianBlurNoiseCfg, + RangeBasedGaussianNoiseCfg, + StereoTooCloseNoiseCfg, +) +from mjlab.envs import ManagerBasedRlEnvCfg +from mjlab.envs import mdp as envs_mdp +from mjlab.envs.mdp import dr +from mjlab.envs.mdp.actions import JointPositionActionCfg +from mjlab.managers.action_manager import ActionTermCfg +from mjlab.managers.command_manager import CommandTermCfg +from mjlab.managers.curriculum_manager import CurriculumTermCfg +from mjlab.managers.event_manager import EventTermCfg +from mjlab.managers.metrics_manager import MetricsTermCfg +from mjlab.managers.observation_manager import ObservationGroupCfg, ObservationTermCfg +from mjlab.managers.reward_manager import RewardTermCfg +from mjlab.managers.scene_entity_config import SceneEntityCfg +from mjlab.managers.termination_manager import TerminationTermCfg +from mjlab.scene import SceneCfg +from mjlab.sensor import ( + ContactMatch, + ContactSensorCfg, + GridPatternCfg, + ObjRef, + PinholeCameraPatternCfg, + RayCastSensorCfg, +) + +from mjlab.sim import MujocoCfg, SimulationCfg +from mjlab.tasks.velocity.mdp import UniformVelocityCommandCfg +from mjlab.terrains import TerrainEntityCfg, SubTerrainCfg +from mjlab.terrains.config import ROUGH_TERRAINS_CFG +from mjlab.utils.noise import UniformNoiseCfg as Unoise +from mjlab.viewer import ViewerConfig + +import src.tasks.velocity.mdp as mdp +from src.assets.robots import ( + VR_M3_12DOF_ACTION_SCALE, + get_vr_m3_12dof_implicit_actuator_robot_cfg, + vr_m3_12dof_joint_pos_action_scale, + vr_m3_12dof_joint_vel_action_scale, +) +from src.tasks.velocity.terrains.config import PERCEPTIVE_TERRAINS_CFG +from src.envs import MultiCriticManagerBasedRlEnvCfg + +## +# VR-M3 12DOF specific constants +## + +# 12DOF keeps the upper body kinematically but with no actuated joints, so +# `waist_yaw_link` (the torso-equivalent body) is still referenceable. +TORSO_BODY = "waist_yaw_link" + +FOOT_SITES = ("left_foot", "right_foot") +FOOT_LINK_NAMES = ("left_ankle_roll_link", "right_ankle_roll_link") + +# Same foot geometry as the fullbody XML: 10 collision geoms per ankle_roll_link. +FOOT_GEOMS = tuple( + f"{side}_ankle_roll_link_collision_{i}" + for side in ("left", "right") + for i in range(1, 11) +) + +# 12DOF only actuates legs; waist and upper body have no actuators, so the +# pose reward only lists the leg-joint regexes. +POSE_STD_STANDING: dict[str, float] = {".*": 0.05} +POSE_STD_WALKING: dict[str, float] = { + r".*hip_pitch.*": 0.5, + r".*hip_roll.*": 0.15, + r".*hip_yaw.*": 0.15, + r".*knee.*": 0.5, + r".*ankle_pitch.*": 0.15, + r".*ankle_roll.*": 0.1, +} +POSE_STD_RUNNING: dict[str, float] = { + r".*hip_pitch.*": 0.5, + r".*hip_roll.*": 0.25, + r".*hip_yaw.*": 0.25, + r".*knee.*": 0.5, + r".*ankle_pitch.*": 0.25, + r".*ankle_roll.*": 0.1, +} + +GAIT_CYCLE_PERIOD = 0.9 + + +@dataclass +class VelocityEnvCfg(ManagerBasedRlEnvCfg): + def __post_init__(self): + pass + + +def vr_m3_12dof_rough_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF rough terrain velocity configuration.""" + + ## + # Sensors + ## + + feet_ground_cfg = ContactSensorCfg( + name="feet_ground_contact", + primary=ContactMatch( + mode="subtree", + pattern=r"^(left_ankle_roll_link|right_ankle_roll_link)$", + entity="robot", + ), + secondary=ContactMatch(mode="body", pattern="terrain"), + fields=("found", "force"), + reduce="netforce", + num_slots=1, + track_air_time=True, + history_length=4, + ) + self_collision_cfg = ContactSensorCfg( + name="self_collision", + primary=ContactMatch(mode="subtree", pattern="pelvis", entity="robot"), + secondary=ContactMatch(mode="subtree", pattern="pelvis", entity="robot"), + fields=("found", "force"), + reduce="none", + num_slots=1, + history_length=4, + ) + + ## + # Observations + ## + + actor_terms = { + "base_ang_vel": ObservationTermCfg( + func=mdp.builtin_sensor, + scale=0.25, + params={"sensor_name": "robot/imu_ang_vel"}, + noise=Unoise(n_min=-0.25, n_max=0.25), + history_length=5, + flatten_history_dim=True, + ), + "projected_gravity": ObservationTermCfg( + func=mdp.projected_gravity, + noise=Unoise(n_min=-0.05, n_max=0.05), + history_length=5, + flatten_history_dim=True, + ), + "velocity_commands": ObservationTermCfg( + func=mdp.generated_commands, + params={"command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ), + "joint_pos_rel": ObservationTermCfg( + func=mdp.joint_pos_rel, + noise=Unoise(n_min=-0.05, n_max=0.05), + history_length=5, + flatten_history_dim=True, + ), + "joint_vel_rel": ObservationTermCfg( + func=mdp.joint_vel_rel, + scale=0.05, + noise=Unoise(n_min=-1.5, n_max=1.5), + history_length=5, + flatten_history_dim=True, + ), + "last_action": ObservationTermCfg( + func=mdp.last_action, history_length=5, flatten_history_dim=True + ), + "gait_phase": ObservationTermCfg( + func=mdp.phase, + params={"period": GAIT_CYCLE_PERIOD, "command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ), + } + + critic_terms = { + **actor_terms, + "base_lin_vel": ObservationTermCfg( + func=mdp.builtin_sensor, + params={"sensor_name": "robot/imu_lin_vel"}, + history_length=5, + flatten_history_dim=True, + ), + "true_base_velocity": ObservationTermCfg( + func=envs_mdp.base_lin_vel, + history_length=5, + flatten_history_dim=True, + ), + "foot_height": ObservationTermCfg( + func=mdp.foot_height, + params={"asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES)}, + history_length=5, + flatten_history_dim=True, + ), + "foot_air_time": ObservationTermCfg( + func=mdp.foot_air_time, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "foot_contact": ObservationTermCfg( + func=mdp.foot_contact, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "foot_contact_forces": ObservationTermCfg( + func=mdp.foot_contact_forces, + params={"sensor_name": "feet_ground_contact"}, + history_length=5, + flatten_history_dim=True, + ), + "knee_reference": ObservationTermCfg( + func=mdp.get_desired_knee_angle, + params={ + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "command_name": "twist", + }, + history_length=5, + flatten_history_dim=True, + ), + } + + observations = { + "actor": ObservationGroupCfg( + terms=actor_terms, + concatenate_terms=True, + enable_corruption=True, + # history_length=5, + nan_policy="sanitize", + nan_check_per_term=True, + ), + "critic": ObservationGroupCfg( + terms=critic_terms, + concatenate_terms=True, + enable_corruption=False, + # history_length=5, + nan_policy="sanitize", + nan_check_per_term=True, + ), + } + + ## + # Metrics + ## + + metrics = { + "mean_action_acc": MetricsTermCfg(func=mdp.mean_action_acc), + } + + ## + # Actions + ## + + actions: dict[str, ActionTermCfg] = { + "joint_pos": JointPositionActionCfg( + entity_name="robot", + actuator_names=(".*",), + scale=VR_M3_12DOF_ACTION_SCALE, + use_default_offset=True, + ) + } + + ## + # Commands + ## + + commands: dict[str, CommandTermCfg] = { + "twist": UniformVelocityCommandCfg( + entity_name="robot", + resampling_time_range=(3.0, 8.0), + rel_standing_envs=0.05, + heading_command=False, + heading_control_stiffness=0.5, + debug_vis=True, + ranges=UniformVelocityCommandCfg.Ranges( + lin_vel_x=(-1.0, 2.0), + lin_vel_y=(-1.0, 1.0), + ang_vel_z=(-1.0, 1.0), + heading=None, + ), + ), + } + twist_cmd = commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.viz.z_offset = 1.15 + + ## + # Events + ## + + events = { + "reset_base": EventTermCfg( + func=mdp.reset_root_state_uniform, + mode="reset", + params={ + "pose_range": { + "x": (-0.5, 0.5), + "y": (-0.5, 0.5), + "z": (0.0, 0.0), + "yaw": (-3.14, 3.14), + }, + # "discrete_yaws": [0.0, math.pi / 2, math.pi, -math.pi / 2], # [0.0, math.pi / 2, math.pi, -math.pi / 2], + }, + ), + "reset_robot_joints": EventTermCfg( + func=mdp.reset_joints_by_offset, + mode="reset", + params={ + "position_range": (-0.1, 0.1), + "velocity_range": (-0.5, 0.5), + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + }, + ), + "push_robot": EventTermCfg( + func=mdp.push_by_setting_velocity, + mode="interval", + interval_range_s=(5.0, 6.0), + params={ + "velocity_range": { + "x": (-0.5, 0.5), + "y": (-0.5, 0.5), + "z": (-0.4, 0.4), + "roll": (-0.52, 0.52), + "pitch": (-0.52, 0.52), + "yaw": (-0.78, 0.78), + }, + }, + ), + "foot_friction": EventTermCfg( + mode="startup", + func=dr.geom_friction, + params={ + "asset_cfg": SceneEntityCfg("robot", geom_names=FOOT_GEOMS), + "operation": "abs", + "ranges": (0.3, 1.6), + "shared_random": True, + }, + ), + "encoder_bias": EventTermCfg( + mode="startup", + func=dr.encoder_bias, + params={ + "asset_cfg": SceneEntityCfg("robot"), + "bias_range": (-0.015, 0.015), + }, + ), + "base_com": EventTermCfg( + mode="startup", + func=dr.body_com_offset, + params={ + "asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,)), + "operation": "add", + "ranges": { + 0: (-0.05, 0.05), + 1: (-0.05, 0.05), + 2: (-0.05, 0.05), + }, + }, + ), + "body_com": EventTermCfg( + mode="startup", + func=dr.body_ipos, + params={ + "asset_cfg": SceneEntityCfg( + "robot", body_names=("^(?!waist_yaw_link$).*",) + ), + "operation": "add", + "ranges": { + 0: (-0.03, 0.03), + 1: (-0.03, 0.03), + 2: (-0.03, 0.03), + }, + }, + ), + "base_mass": EventTermCfg( + mode="startup", + func=dr.body_mass, + params={ + "asset_cfg": SceneEntityCfg("robot", body_names=("waist_yaw_link",)), + "operation": "add", + "ranges": (-4.0, 4.0), + }, + ), + "body_mass": EventTermCfg( + mode="startup", + func=dr.body_mass, + params={ + "asset_cfg": SceneEntityCfg( + "robot", body_names=("^(?!waist_yaw_link$).*",) + ), + "operation": "scale", + "ranges": (0.9, 1.1), + }, + ), + "randomize_actuator_gains": EventTermCfg( + func=dr.pd_gains, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "kp_range": (0.7, 1.1), + "kd_range": (0.7, 1.1), + }, + ), + "randomize_joint_limit": EventTermCfg( + mode="startup", + func=dr.joint_limits, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.94, 1.06), + }, + ), + "randomize_joint_stiffness": EventTermCfg( + mode="startup", + func=dr.joint_stiffness, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.7, 1.3), + }, + ), + "randomize_joint_frictionloss": EventTermCfg( + mode="startup", + func=dr.joint_friction, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.1, 1.3), + }, + ), + "randomize_joint_armature": EventTermCfg( + mode="startup", + func=dr.joint_armature, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.2, 5.0), + }, + ), + "randomize_joint_damping": EventTermCfg( + mode="startup", + func=dr.joint_damping, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=(".*",)), + "operation": "scale", + "ranges": (0.7, 1.3), + }, + ), + } + + ## + # Rewards + ## + + rewards = { + "track_linear_velocity": RewardTermCfg( + func=mdp.track_linear_velocity, + weight=2.0, + params={"command_name": "twist", "std": math.sqrt(0.25)}, + ), + "track_angular_velocity": RewardTermCfg( + func=mdp.track_angular_velocity, + weight=2.0, + params={"command_name": "twist", "std": math.sqrt(0.5)}, + ), + "body_orientation_l2": RewardTermCfg( + func=mdp.body_orientation_l2, + weight=-5.0, + params={"asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,))}, + ), + "pose": RewardTermCfg( + func=mdp.variable_posture, + weight=1.0, + params={ + "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), + "command_name": "twist", + "std_standing": POSE_STD_STANDING, + "std_walking": POSE_STD_WALKING, + "std_running": POSE_STD_RUNNING, + "walking_threshold": 0.1, + "running_threshold": 0.7, + }, + ), + "flat_orientation": RewardTermCfg(func=mdp.flat_orientation_l2, weight=-7.0), + "pelvis_orientation_l2": RewardTermCfg( + func=mdp.link_orientation, + weight=-3.0, + params={"asset_cfg": SceneEntityCfg("robot", body_names="pelvis")}, + ), + "joint_deviation_hip": RewardTermCfg( + func=mdp.joint_deviation_square, + weight=-0.1, + params={ + "asset_cfg": SceneEntityCfg( + "robot", + joint_names=(".*_hip_yaw_joint", ".*_hip_roll_joint"), + ) + }, + ), + "ang_vel_xy_l2": RewardTermCfg( + func=mdp.ang_vel_xy_l2, + weight=-0.05, + ), + "dof_torques_l2": RewardTermCfg( + func=mdp.joint_torques_l2, + weight=-1.0e-8, + params={ + "asset_cfg": SceneEntityCfg( + "robot", + joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + ) + }, + ), + "dof_vel_l2": RewardTermCfg( + func=mdp.joint_vel_l2, + weight=-1.0e-8, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + "feet_flat_ori": RewardTermCfg( + func=mdp.feet_orientation_contact, + weight=-0.01, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + }, + ), + "body_ang_vel": RewardTermCfg( + func=mdp.body_angular_velocity_penalty, + weight=-0.05, + params={"asset_cfg": SceneEntityCfg("robot", body_names=(TORSO_BODY,))}, + ), + "angular_momentum": RewardTermCfg( + func=mdp.angular_momentum_penalty, + weight=-0.025, + params={"sensor_name": "robot/root_angmom"}, + ), + "is_terminated": RewardTermCfg(func=mdp.is_terminated, weight=-200.0), + "joint_acc_l2": RewardTermCfg(func=mdp.joint_acc_l2, weight=-2.5e-7), + "joint_pos_limits": RewardTermCfg(func=mdp.joint_pos_limits, weight=-5.0), + "action_rate_l2": RewardTermCfg(func=mdp.action_rate_l2, weight=-0.5), + "foot_gait": RewardTermCfg( + func=mdp.feet_gait, + weight=1.0, + params={ + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "threshold": 0.6, + "command_threshold": 0.1, + "command_name": "twist", + "sensor_name": "feet_ground_contact", + }, + ), + "feet_double_support": RewardTermCfg( + func=mdp.feet_double_support, + weight=2.0, + params={ + "sensor_name": "feet_ground_contact", + "period": GAIT_CYCLE_PERIOD, + "offset": [0.0, 0.5], + "threshold": 0.6, + "command_name": "twist", + "cmd_threshold": 0.1, + "ds_match_weight": 1.0, + }, + ), + "foot_clearance": RewardTermCfg( + func=mdp.feet_clearance, + weight=-1.0, + params={ + "target_height": 0.10, + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES), + }, + ), + "foot_slip": RewardTermCfg( + func=mdp.feet_slip, + weight=-0.25, + params={ + "sensor_name": "feet_ground_contact", + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", site_names=FOOT_SITES), + }, + ), + "feet_close_xy": RewardTermCfg( + func=mdp.feet_close_xy_gauss, + weight=1.0, + params={ + "threshold": 0.2, + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "std": math.sqrt(0.05), + }, + ), + "soft_landing": RewardTermCfg( + func=mdp.soft_landing, + weight=-1e-3, + params={ + "sensor_name": "feet_ground_contact", + "command_name": "twist", + "command_threshold": 0.1, + }, + ), + "dont_wait": RewardTermCfg( + func=mdp.dont_wait, + weight=-0.5, + params={ + "command_name": "twist", + "cmd_threshold": 0.1, + }, + ), + "stand_still": RewardTermCfg( + func=mdp.stand_still, + weight=-1.0, + params={ + "command_name": "twist", + "command_threshold": 0.1, + "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), + }, + ), + "self_collisions": RewardTermCfg( + func=mdp.self_collision_cost, + weight=-1.0, + params={"sensor_name": self_collision_cfg.name, "force_threshold": 10.0}, + ), + "feet_air_time": RewardTermCfg( + func=mdp.feet_air_time, + weight=1.0, + params={ + "sensor_name": "feet_ground_contact", + "threshold": (1.0 - 0.6) * GAIT_CYCLE_PERIOD, # 0.48 s + "command_name": "twist", + "command_threshold": 0.1, + }, + ), + "feet_air_time_biped": RewardTermCfg( + func=mdp.feet_air_time_positive_biped, + weight=1.5, + params={ + "command_name": "twist", + "sensor_name": "feet_ground_contact", + "threshold": 0.52, + }, + ), + } + + ## + # Terminations + ## + + terminations = { + "time_out": TerminationTermCfg(func=mdp.time_out, time_out=True), + "fell_over": TerminationTermCfg( + func=mdp.bad_orientation, + params={"limit_angle": math.radians(70.0)}, + ), + "nan_term": TerminationTermCfg( + func=mdp.nan_detection, + time_out=False, + ), + } + + ## + # Curriculum + ## + + curriculum = { + "terrain_levels": CurriculumTermCfg( + func=mdp.terrain_levels_vel, + params={"command_name": "twist"}, + ), + "command_vel": CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (-0.5, 1.0), + "lin_vel_y": (-0.5, 0.5), + "ang_vel_z": (-0.5, 0.5), + }, + { + "step": 5000 * 24, + "lin_vel_x": (-0.7, 1.5), + "lin_vel_y": (-0.7, 0.7), + "ang_vel_z": (-0.7, 0.7), + }, + { + "step": 7000 * 24, + "lin_vel_x": (-1.0, 2.0), + "lin_vel_y": (-1.0, 1.0), + "ang_vel_z": (-1.0, 1.0), + }, + # { + # "step": 9000 * 24, + # "lin_vel_x": (-1.0, 3.0), + # "lin_vel_y": (-1.0, 1.0), + # "ang_vel_z": (-1.0, 1.0), + # }, + ], + }, + ), + } + + ## + # Scene + terrain + ## + + terrain_generator = replace(ROUGH_TERRAINS_CFG) + terrain_generator.curriculum = True + terrain = TerrainEntityCfg( + terrain_type="generator", + terrain_generator=terrain_generator, + max_init_terrain_level=5, + ) + + scene = SceneCfg( + terrain=terrain, + entities={"robot": get_vr_m3_12dof_implicit_actuator_robot_cfg()}, + sensors=(feet_ground_cfg, self_collision_cfg), + num_envs=1, + extent=2.0, + ) + + ## + # Assemble + ## + + cfg = VelocityEnvCfg( + scene=scene, + observations=observations, + actions=actions, + commands=commands, + events=events, + rewards=rewards, + terminations=terminations, + curriculum=curriculum, + metrics=metrics, + viewer=ViewerConfig( + origin_type=ViewerConfig.OriginType.ASSET_BODY, + entity_name="robot", + body_name=TORSO_BODY, + distance=3.0, + elevation=-5.0, + azimuth=90.0, + ), + sim=SimulationCfg( + # VR-M3 has ~1.4x the foot collision geoms of G1 (10/side vs 7/side); + # rough terrain randomization can push the contact count up, so + # nconmax is raised from G1's 48 to 512. + nconmax=512, + njmax=1500, + contact_sensor_maxmatch=500, + mujoco=MujocoCfg( + timestep=0.005, + iterations=10, + ls_iterations=20, + ccd_iterations=500, + ), + ), + decimation=4, + episode_length_s=20.0, + ) + + # Play mode overrides. + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["actor"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + return cfg + + +def vr_m3_12dof_flat_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF flat terrain velocity configuration.""" + cfg = vr_m3_12dof_rough_env_cfg(play=play) + cfg.rewards.pop("flat_orientation", None) + cfg.rewards.pop("pelvis_orientation_l2", None) + cfg.rewards.pop("joint_deviation_hip", None) + cfg.rewards.pop("ang_vel_xy_l2", None) + cfg.rewards.pop("dof_torques_l2", None) + cfg.rewards.pop("dof_vel_l2", None) + cfg.rewards.pop("feet_flat_ori", None) + # VR-M3 has ~1.4x the foot collision geoms of G1, so njmax needs headroom. + cfg.sim.njmax = 600 + cfg.sim.mujoco.ccd_iterations = 50 + cfg.sim.contact_sensor_maxmatch = 64 + cfg.sim.nconmax = None + + # Switch to flat terrain. + assert cfg.scene.terrain is not None + cfg.scene.terrain.terrain_type = "plane" + cfg.scene.terrain.terrain_generator = None + + # Remove raycast sensor and height scan (no terrain to scan). + cfg.scene.sensors = tuple( + s for s in (cfg.scene.sensors or ()) if s.name != "terrain_scan" + ) + # del cfg.observations["actor"].terms["height_scan"] + # del cfg.observations["critic"].terms["height_scan"] + cfg.observations["actor"].terms.pop("height_scan", None) + cfg.observations["critic"].terms.pop("height_scan", None) + + cfg.curriculum.pop("terrain_levels", None) + + if play: + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (-0.5, 2.0) + twist_cmd.ranges.lin_vel_y = (-0.5, 0.5) + twist_cmd.ranges.ang_vel_z = (-0.5, 0.5) + + return cfg + + +def vr_m3_12dof_perceptive_env_cfg(play: bool = False) -> VelocityEnvCfg: + """Create VR-M3 12DOF perceptive locomotion configuration with height-map.""" + cfg = vr_m3_12dof_rough_env_cfg(play=play) + + site_names = ("left_foot", "right_foot") + + # Auto-size contact buffers for complex terrain geometry. + cfg.sim.njmax = 700 + cfg.sim.mujoco.ccd_iterations = 500 + cfg.sim.contact_sensor_maxmatch = 500 + cfg.sim.nconmax = 128 + + # Swap terrain generator to perceptive preset (deepcopy to avoid mutation). + assert cfg.scene.terrain is not None + cfg.scene.terrain.terrain_generator = deepcopy(PERCEPTIVE_TERRAINS_CFG) + + if not play: + cfg.scene.terrain.terrain_generator.curriculum = True + + pelvis_height_measure = RayCastSensorCfg( + name="pelvis_height_measure", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=2.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + left_height_scanner = RayCastSensorCfg( + name="left_height_scanner", + frame=ObjRef(type="site", name="left_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=1.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + right_height_scanner = RayCastSensorCfg( + name="right_height_scanner", + frame=ObjRef(type="site", name="right_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.0, 0.0), + resolution=0.1, + direction=(0.0, 0.0, -1.0), # Rays pointing downward + ), + ray_alignment="yaw", # Align with body yaw only (stable on slopes) + max_distance=1.0, # Max scan depth + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + + # --- Gradient sensors (3x3 grid for foot edge detection) --- + left_foot_gradient = RayCastSensorCfg( + name="left_foot_gradient", + frame=ObjRef(type="site", name="left_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.2, 0.1), + resolution=0.1, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=1.0, + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + right_foot_gradient = RayCastSensorCfg( + name="right_foot_gradient", + frame=ObjRef(type="site", name="right_foot", entity="robot"), + pattern=GridPatternCfg( + size=(0.2, 0.1), + resolution=0.1, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=1.0, + include_geom_groups=(0,), # Only hit terrain (group 0) + exclude_parent_body=True, + debug_vis=play, + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + pelvis_height_measure, + left_height_scanner, + right_height_scanner, + left_foot_gradient, + right_foot_gradient, + ) + + # --- Terrain-aware reward terms --- + cfg.rewards["terrain_foot_clearance"] = RewardTermCfg( + func=mdp.terrain_foot_clearance_cost, + weight=-0.5, + params={ + "target_clearance": 0.06, + "left_terrain_sensor": "left_height_scanner", + "right_terrain_sensor": "right_height_scanner", + "command_name": "twist", + "command_threshold": 0.05, + "asset_cfg": SceneEntityCfg("robot", site_names=site_names), + }, + ) + + cfg.rewards["terrain_stumble"] = RewardTermCfg( + func=mdp.terrain_stumble_cost, + weight=-1.0, + params={ + "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "velocity_threshold": 0.15, + }, + ) + + # cfg.rewards["step_accuracy"] = RewardTermCfg( + # func=custom_mdp.step_accuracy, + # weight=1.0, + # params={ + # "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "patch_name": "target", + # "std": 0.15, + # }, + # ) + + cfg.rewards["terrain_base_height"] = RewardTermCfg( + func=mdp.terrain_base_height_l2_cost, + weight=-1.0, + params={ + "target_height": 0.9, + "base_terrain_sensor": "pelvis_height_measure", + "asset_cfg": SceneEntityCfg("robot"), + }, + ) + + cfg.rewards["foot_edge"] = RewardTermCfg( + func=mdp.foot_edge_cost, + weight=-0.5, + params={ + "sensor_cfg": SceneEntityCfg("feet_ground_contact"), + "left_gradient_sensor": "left_foot_gradient", + "right_gradient_sensor": "right_foot_gradient", + "gradient_threshold": 0.3, + "asset_cfg": SceneEntityCfg("robot", body_names=[r".*ankle_roll.*"]), + }, + ) + + # cfg.rewards["feet_at_plane"] = RewardTermCfg( + # func=parkour_mdp.feet_at_plane, + # weight=-0.1, + # params={ + # "contact_sensor_name": "feet_ground_contact", + # "left_height_scanner_name": "left_height_scanner", # matches your sensor + # "right_height_scanner_name": "right_height_scanner", # matches your sensor + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "height_offset": 0.06, + # }, + # ) + + # --- Terrain-aware termination --- + cfg.terminations["base_height"] = TerminationTermCfg( + func=mdp.root_height_below_minimum_terrain, + params={ + "minimum_height": 0.3, + "terrain_sensor_name": "pelvis_height_measure", + }, + ) + + if play: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + return cfg + + +def vr_m3_12dof_height_map_env_cfg(play: bool = False) -> VelocityEnvCfg: + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(0.6, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + cfg.scene.sensors = cfg.scene.sensors + (terrain_scan,) + + # --- Asymmetric actor-critic observations --- + # Actor: add terrain_scan with noise (proprioception terms inherited from base). + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + # func=custom_mdp.height_scan_custom, + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + noise=Unoise(n_min=-0.1, n_max=0.1), + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic: add terrain_scan (no noise, privileged) and true base velocity. + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + # func=custom_mdp.height_scan_custom, + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + history_length=5, + ) + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 2.5 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -5e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 1.0 + cfg.rewards["feet_double_support"].weight = 2.0 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -0.5 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 1.5 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards["foot_edge"].weight = -0.5 + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["actor"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_depth_map_env_cfg( + play: bool = False, +) -> VelocityEnvCfg: + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(1.8, 1.2), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + depth_camera = NoisyGroupedRayCasterCameraCfg( + name="camera", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + # RealSense depth camera D435 + # Intrinsics from camera_info: fx = fy = 386.56719970703125 at 640x480 + pattern=PinholeCameraPatternCfg( + height=int(480 / 8), + width=int(640 / 8), + fovy=2 + * math.degrees(math.atan(480 / 2 / 386.56719970703125)), # ~63.67 deg + ), + focal_length=1.0, + horizontal_aperture=640.0 / 386.56719970703125, # fovx ~79.24 deg + vertical_aperture=480.0 / 386.56719970703125, # fovy ~63.67 deg + ray_alignment="base", + include_geom_groups=(0, 1, 2), + exclude_parent_body=False, + offset=NoisyGroupedRayCasterCameraCfg.OffsetCfg( + pos=(0.00, 0.018, -0.1), + rot=( + math.cos(math.radians(60) / 2), # w + 0.0, # x + math.sin(math.radians(60) / 2), # y (pitch 60 deg about Y) + 0.0, # z + ), + convention="world", + ), + data_types=["distance_to_image_plane"], + depth_clipping_behavior="max", # clip to the maximum value + mesh_filter_max_hops=24, + noise_pipeline={ + "crop_and_resize": CropAndResizeCfg( + # (top, bottom, left, right), height/2 and centering width/2 + crop_region=(0, 0, 10, 10), + resize_shape=(30, 30), + ), + "gaussian_blur": GaussianBlurNoiseCfg(kernel_size=3, sigma=1), + "depth_normalization": DepthNormalizationCfg( + depth_range=(0.0, 2.5), + normalize=True, + output_range=(0.0, 1.0), + ), + }, + data_histories={"distance_to_image_plane_noised": 17}, + update_period=1 / 30, + min_distance=0.1, + max_distance=2.5, + debug_vis=play, + ) + undesired_contact_cfg = ContactSensorCfg( + name="undesired_contact_forces", + primary=ContactMatch( + mode="body", + pattern=".*", + entity="robot", + exclude=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + fields=("found", "force"), + reduce="netforce", + track_air_time=False, + history_length=3, + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + terrain_scan, + depth_camera, + undesired_contact_cfg, + ) + + cfg.events["randomize_ray_offsets"] = EventTermCfg( + func=instinct_mdp.randomize_ray_offsets, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("camera"), + "offset_pose_ranges": { + "x": (-0.01, 0.01), + "y": (-0.01, 0.01), + "z": (-0.03, 0.01), + "roll": (-math.radians(2), math.radians(2)), + "pitch": (-math.radians(10), math.radians(10)), + "yaw": (-math.radians(2), math.radians(2)), + }, + "distribution": "uniform", + }, + ) + + cfg.observations["actor"].concatenate_terms = False + cfg.observations["critic"].concatenate_terms = False + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + ) + + cfg.observations["actor"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + cfg.observations["critic"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + # Add "policy" alias for actor obs (Instinct runner expects "policy"). + actor_obs_cfg = cfg.observations.pop("actor") + cfg.observations["policy"] = actor_obs_cfg + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 2.0 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards["foot_edge"].weight = -0.5 + + cfg.rewards = { + **cfg.rewards, + "feet_slide": RewardTermCfg( + func=instinct_parkour_mdp.feet_slide, + weight=-0.4, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "threshold": 1.0, + }, + ), + # "joint_deviation_hip": RewardTermCfg( + # func=instinct_mdp.joint_deviation_square, + # weight=-0.3, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_yaw_joint", ".*_hip_roll_joint"), + # ) + # }, + # ), + # "ang_vel_xy_l2": RewardTermCfg( + # func=instinct_parkour_mdp.ang_vel_xy_l2, + # weight=-0.05, + # ), + # "dof_torques_l2": RewardTermCfg( + # func=instinct_parkour_mdp.joint_torques_l2, + # weight=-1.0e-7, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ) + # }, + # ), + # "dof_vel_l2": RewardTermCfg( + # func=envs_mdp.joint_vel_l2, + # weight=-5.0e-7, + # params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + # ), + # "feet_flat_ori": RewardTermCfg( + # func=instinct_parkour_mdp.feet_orientation_contact, + # weight=-0.01, + # params={ + # "sensor_name": "feet_ground_contact", + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # }, + # ), + # "feet_close_xy": RewardTermCfg( + # func=instinct_parkour_mdp.feet_close_xy_gauss, + # weight=1.0, + # params={ + # "threshold": 0.2, + # "asset_cfg": SceneEntityCfg( + # "robot", + # body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + # ), + # "std": math.sqrt(0.05), + # }, + # ), + # "energy": RewardTermCfg( + # func=parkour_mdp.rewards.motors_power_square, + # weight=-1.0e-8, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ), + # "normalize_by_stiffness": True, + # }, + # ), + "dof_pos_limits": RewardTermCfg( + func=envs_mdp.joint_pos_limits, + weight=-1.0, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + # "flat_orientation": RewardTermCfg(func=mdp.flat_orientation_l2, weight=-7.0), + # "pelvis_orientation_l2": RewardTermCfg( + # func=instinct_parkour_mdp.link_orientation, + # weight=-3.0, + # params={"asset_cfg": SceneEntityCfg("robot", body_names="pelvis")}, + # ), + } + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["policy"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_foothold_env_cfg(play: bool = False) -> VelocityEnvCfg: + """FastStair Stage 1 — planner-guided pre-training (paper §III-B.3). + + Extends ``vr_m3_12dof_height_map_env_cfg`` with: + + - A 1.8 × 1.2 m elevation map at 5 cm resolution (paper §III-C). + - The DCM-based foothold planner exposed as a ``FootholdCommand``. + - The exponential foothold-tracking reward with weight 0.6 (Table I §III-B.2). + - A privileged ``foothold_target`` observation on the critic. + - Velocity range restricted to the paper's pre-train regime + ``[-0.3, 1.0]`` m/s in x. + - Stage 1 reward weights from Table I. + """ + cfg = vr_m3_12dof_perceptive_env_cfg(play=play) + + terrain_scan = RayCastSensorCfg( + name="terrain_scan", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(1.8, 1.2), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0,), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + depth_camera = NoisyGroupedRayCasterCameraCfg( + name="camera", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + # RealSense depth camera D435 + # Intrinsics from camera_info: fx = fy = 386.56719970703125 at 640x480 + pattern=PinholeCameraPatternCfg( + height=int(480 / 8), + width=int(640 / 8), + fovy=2 + * math.degrees(math.atan(480 / 2 / 386.56719970703125)), # ~63.67 deg + ), + focal_length=1.0, + horizontal_aperture=640.0 / 386.56719970703125, # fovx ~79.24 deg + vertical_aperture=480.0 / 386.56719970703125, # fovy ~63.67 deg + ray_alignment="base", + include_geom_groups=(0, 1, 2), + exclude_parent_body=False, + # TODO: double check with Offset from URDF + offset=NoisyGroupedRayCasterCameraCfg.OffsetCfg( + pos=(0.00, 0.018, -0.1), + rot=( + math.cos(math.radians(60) / 2), # w + 0.0, # x + math.sin(math.radians(60) / 2), # y (pitch 30 deg about Y) + 0.0, # z + ), + convention="world", + ), + data_types=["distance_to_image_plane"], + depth_clipping_behavior="max", # clip to the maximum value + mesh_filter_max_hops=24, + noise_pipeline={ + "crop_and_resize": CropAndResizeCfg( + # (top, bottom, left, right), height/2 and centering width/2 + crop_region=(0, 0, 10, 10), + resize_shape=(30, 30), + ), + "gaussian_blur": GaussianBlurNoiseCfg(kernel_size=3, sigma=1), + "depth_normalization": DepthNormalizationCfg( + depth_range=(0.0, 2.5), + normalize=True, + output_range=(0.0, 1.0), + ), + }, + data_histories={"distance_to_image_plane_noised": 17}, + update_period=1 / 30, + min_distance=0.1, + max_distance=2.5, + debug_vis=play, + ) + undesired_contact_cfg = ContactSensorCfg( + name="undesired_contact_forces", + primary=ContactMatch( + mode="body", + pattern=".*", + entity="robot", + exclude=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + fields=("found", "force"), + reduce="netforce", + track_air_time=False, + history_length=3, + ) + + cfg.scene.sensors = tuple( + s + for s in (cfg.scene.sensors or ()) + if s.name not in ("left_foot_gradient", "right_foot_gradient") + ) + + cfg.scene.sensors = cfg.scene.sensors + ( + terrain_scan, + depth_camera, + undesired_contact_cfg, + ) + + cfg.events["randomize_ray_offsets"] = EventTermCfg( + func=instinct_mdp.randomize_ray_offsets, + mode="startup", + params={ + "asset_cfg": SceneEntityCfg("camera"), + "offset_pose_ranges": { + "x": (-0.01, 0.01), + "y": (-0.01, 0.01), + "z": (-0.03, 0.01), + "roll": (-math.radians(2), math.radians(2)), + "pitch": (-math.radians(10), math.radians(10)), + "yaw": (-math.radians(2), math.radians(2)), + }, + "distribution": "uniform", + }, + ) + + # Foothold command — the planner output. + cfg.commands["foothold"] = mdp.FootholdCommandCfg( + entity_name="robot", + terrain_sensor_name="terrain_scan", + contact_sensor_name="feet_ground_contact", + velocity_command_name="twist", + foot_site_names=FOOT_SITES, + gait_period=GAIT_CYCLE_PERIOD, + nominal_height_m=0.9, + lateral_inter_foot_m=0.22, + foot_footprint_m=(0.25, 0.10), + search_window_m=(0.6, 0.6), + elevation_size_m=(1.8, 1.2), + elevation_resolution_m=0.05, + alpha_pos=1.0, + alpha_dcm=0.5, + # Safety-aware terrain scoring (max-pool steepness + footprint + # flatness + soft height feasibility + climb bonus). See + # ``DCMFootholdPlanner`` docstring for the rationale. + alpha_steepness=0.6, + alpha_flatness=4.0, + alpha_height=6.0, + alpha_climb_bonus=1.5, + lateral_pos_weight=2.5, + max_step_height_m=0.25, + climb_velocity_threshold=0.1, + standing_threshold=0.1, + # Adaptive Bézier clearance: 5 cm base on flat ground, +0.5 m/m of + # step height, capped at 20 cm. + apex_clearance_m=0.05, + clearance_scale=0.5, + max_clearance_m=0.20, + pre_apex_lower_window=0.05, + pre_apex_upper_window=0.05, + post_apex_lower_window=0.1, + post_apex_upper_window=0.15, + terrain_decision_threshold=0.1, + debug_vis=play, + ) + + cfg.observations["actor"].concatenate_terms = False + cfg.observations["critic"].concatenate_terms = False + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan", "miss_value": 2.0}, + clip=(0.0, 2.0), + ) + + # Privileged critic observation: planner output (body frame). + cfg.observations["critic"].terms["foothold_target"] = ObservationTermCfg( + func=mdp.foothold_target, + params={"command_name": "foothold"}, + ) + + cfg.observations["actor"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + cfg.observations["critic"].terms["depth_image"] = ObservationTermCfg( + func=instinct_mdp.delayed_visualizable_image, + params={ + "data_type": "distance_to_image_plane_noised_history", + "sensor_cfg": SceneEntityCfg("camera"), + "history_skip_frames": 5, + "num_output_frames": 4, + "delayed_frame_ranges": (0, 1), + "debug_vis": play, + }, + noise=None, + ) + + # add "policy" alias for actor obs for instinct compatibility + actor_obs_cfg = cfg.observations.pop("actor") + cfg.observations["policy"] = actor_obs_cfg + + # ------------------------------------------------------------------ + # Command ranges + # ------------------------------------------------------------------ + twist = cfg.commands["twist"] + assert isinstance(twist, UniformVelocityCommandCfg) + + twist.ranges = UniformVelocityCommandCfg.Ranges( + lin_vel_x=(0.0, 1.0), + lin_vel_y=(0.0, 0.0), + ang_vel_z=(-0.5, 0.5), + heading=None, + ) + + # Pre-train velocity range (paper §III-B.3). + # twist_cmd = cfg.commands["twist"] + # assert isinstance(twist_cmd, UniformVelocityCommandCfg) + # twist_cmd.ranges = UniformVelocityCommandCfg.Ranges( + # lin_vel_x=(-0.3, 1.0), + # lin_vel_y=(-0.3, 0.3), + # ang_vel_z=(-1.0, 1.0), + # heading=None, + # ) + # twist_cmd.resampling_time_range = (8.0, 12.0) + # cfg.curriculum.pop("command_vel", None) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 5_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for teacher training --- + cfg.rewards["terrain_stumble"].weight = -0.5 + # cfg.rewards["step_accuracy"].weight = 1.0 + + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # incompatible with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-8 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -1.0 + cfg.rewards["self_collisions"].weight = -2.0 + cfg.rewards["feet_air_time"].weight = 1.0 + cfg.rewards["feet_air_time_biped"].weight = 2.0 + cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["terrain_base_height"].weight = -1.5 + # cfg.rewards["foot_edge"].weight = -0.5 + cfg.rewards.pop("foot_edge", None) + + cfg.rewards = { + **cfg.rewards, + "feet_slide": RewardTermCfg( + func=instinct_parkour_mdp.feet_slide, + weight=-0.4, + params={ + "sensor_name": "feet_ground_contact", + "asset_cfg": SceneEntityCfg( + "robot", + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "threshold": 1.0, + }, + ), + # "energy": RewardTermCfg( + # func=parkour_mdp.rewards.motors_power_square, + # weight=-1.0e-8, + # params={ + # "asset_cfg": SceneEntityCfg( + # "robot", + # joint_names=(".*_hip_.*", ".*_knee_.*", ".*_ankle_.*"), + # ), + # "normalize_by_stiffness": True, + # }, + # ), + "dof_pos_limits": RewardTermCfg( + func=envs_mdp.joint_pos_limits, + weight=-1.0, + params={"asset_cfg": SceneEntityCfg("robot", joint_names=(".*",))}, + ), + } + + cfg.rewards["foothold_tracking"] = RewardTermCfg( + func=mdp.foothold_tracking, + weight=2.1, + params={ + "command_name": "foothold", + "sigma_stages": [(10.0, 5.0), (20.0, 10.0), (30.0, 15.0)], + "stage_step_counts": [0, 4_000 * 24, 8_000 * 24], + "asset_cfg": SceneEntityCfg( + "robot", + site_names=FOOT_SITES, + body_names=("left_ankle_roll_link", "right_ankle_roll_link"), + ), + "sensor_name": "feet_ground_contact", + "velocity_command_name": "twist", + "velocity_command_threshold": 0.1, + # "log_csv_path": "foothold_tracking_rewards.csv" if play else None, + }, + ) + # cfg.rewards["track_linear_velocity"].weight = 1.0 + # if "action_rate_l2" in cfg.rewards: + # cfg.rewards["action_rate_l2"].weight = -2.5e-3 + # if "joint_acc_l2" in cfg.rewards: + # cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + # if "dof_torques_l2" in cfg.rewards: + # cfg.rewards["dof_torques_l2"].weight = -4.0e-7 + # if "dof_vel_l2" in cfg.rewards: + # cfg.rewards["dof_vel_l2"].weight = -2.5e-7 + # if "foot_edge" in cfg.rewards: + # cfg.rewards["foot_edge"].weight = -1.5 + + if play: + cfg.episode_length_s = int(1e9) + cfg.observations["policy"].enable_corruption = False + cfg.events.pop("push_robot", None) + cfg.curriculum = {} + cfg.events["randomize_terrain"] = EventTermCfg( + func=envs_mdp.randomize_terrain, + mode="reset", + params={}, + ) + assert cfg.scene.terrain is not None + if cfg.scene.terrain.terrain_generator is not None: + cfg.scene.terrain.terrain_generator.curriculum = False + cfg.scene.terrain.terrain_generator.num_cols = 5 + cfg.scene.terrain.terrain_generator.num_rows = 5 + cfg.scene.terrain.terrain_generator.border_width = 10.0 + + twist_cmd = cfg.commands["twist"] + assert isinstance(twist_cmd, UniformVelocityCommandCfg) + twist_cmd.ranges.lin_vel_x = (0.4, 0.6) + twist_cmd.ranges.lin_vel_y = (0.0, 0.0) + twist_cmd.ranges.ang_vel_z = (0.0, 0.0) + + return cfg + + +def vr_m3_12dof_ga_phl_env_cfg(play: bool = False) -> VelocityEnvCfg: + """GA-PHL perceptive locomotion config for VR-M3 12DOF. + + Implements arXiv:2512.07464 (Gait-Adaptive Perceptive Humanoid Locomotion + with Real-Time Under-Base Terrain Reconstruction): + + - Downward-facing under-base depth camera (§III-E): replaces the 60° forward + camera with a 90° downward camera, covering the critical foot-support region. + - Omnidirectional velocity commands with a 3-stage curriculum (§IV-B). + - Reward weights matched to paper Table I as closely as possible using the + existing reward functions in this codebase. + + Based on ``vr_m3_12dof_foothold_env_cfg`` (inherits foothold planner, terrain + scan, depth image obs, and domain randomisation). Not implemented here because + they require framework-level extensions: + - U-Net height-map reconstruction (separate offline model). + - Successive Teacher-Student runner (runner-level, not env-level). + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_map_as_grid, + params={ + "sensor_name": "terrain_scan", + "miss_value": 2.0, + "use_grid": True, + "num_cols": int((1.8 + 1e-6) / 0.05) + 1, + "num_rows": int((1.2 + 1e-6) / 0.05) + 1, + }, + clip=(0.0, 2.0), + history_length=1, + flatten_history_dim=False, + ) + + cfg.observations["critic"].terms.pop("depth_image") + + cfg.commands["foothold"] = mdp.FootholdCommandCfg( + entity_name="robot", + terrain_sensor_name="terrain_scan", + contact_sensor_name="feet_ground_contact", + velocity_command_name="twist", + foot_site_names=FOOT_SITES, + gait_period="policy", + gait_action_name="gait_freq", + nominal_height_m=0.9, + lateral_inter_foot_m=0.18, + foot_footprint_m=(0.20, 0.10), + search_window_m=(0.6, 0.6), + elevation_size_m=(1.8, 1.2), + elevation_resolution_m=0.05, + alpha_pos=1.0, + alpha_dcm=0.5, + # Safety-aware terrain scoring (max-pool steepness + footprint + # flatness + soft height feasibility + climb bonus). See + # ``DCMFootholdPlanner`` docstring for the rationale. + alpha_steepness=0.6, + alpha_flatness=4.0, + alpha_height=6.0, + alpha_climb_bonus=1.5, + lateral_pos_weight=2.5, + max_step_height_m=0.25, + climb_velocity_threshold=0.1, + standing_threshold=0.1, + # Adaptive Bézier clearance: 5 cm base on flat ground, +0.5 m/m of + # step height, capped at 20 cm. + apex_clearance_m=0.05, + clearance_scale=0.5, + max_clearance_m=0.20, + pre_apex_lower_window=0.05, + pre_apex_upper_window=0.05, + post_apex_lower_window=0.1, + post_apex_upper_window=0.15, + terrain_decision_threshold=0.1, + debug_vis=play, + ) + + cfg.rewards["foothold_tracking"] = RewardTermCfg( + func=mdp.foothold_tracking, + weight=2.0, + params={ + "command_name": "foothold", + "sigma_stages": [(10.0, 5.0), (20.0, 10.0), (30.0, 15.0)], + "stage_step_counts": [0, 4_000 * 24, 8_000 * 24], + "asset_cfg": SceneEntityCfg( + "robot", + site_names=FOOT_SITES, + body_names=FOOT_LINK_NAMES, + ), + "sensor_name": "feet_ground_contact", + "velocity_command_name": "twist", + "velocity_command_threshold": 0.1, + "penalty_scale": 1.0, + # "log_csv_path": "foothold_tracking_rewards.csv" if play else None, + }, + ) + + # Route foot_gait and feet_double_support to the learnable phase φ_t so + # the gait reward is consistent with the policy's own internal clock. + cfg.observations["critic"].terms["knee_reference"].params[ + "action_name" + ] = "gait_freq" + cfg.rewards["foot_gait"].params["action_name"] = "gait_freq" + cfg.rewards["feet_double_support"].params["action_name"] = "gait_freq" + cfg.rewards["feet_air_time"].params["action_name"] = "gait_freq" + + cfg.actions["gait_freq"] = mdp.GaitFrequencyActionCfg( + entity_name="robot", + min_frequency=1.0, + max_frequency=1.5, + smooth_alpha=0.2, + default_frequency=1.2, + ) + + # ── 6. Adaptive gait-phase observation (replaces fixed-period phase obs) ── + # Returns [f_t, sin(2π·φ_t), cos(2π·φ_t)] — 3 scalars instead of 2. + # Both policy and critic groups inherit the same proprioceptive terms. + for group_name in ("policy", "critic"): + cfg.observations[group_name].terms.pop("gait_phase", None) + cfg.observations[group_name].terms["adaptive_gait_phase"] = ObservationTermCfg( + func=mdp.adaptive_gait_phase, + params={"action_name": "gait_freq", "command_name": "twist"}, + history_length=5, + flatten_history_dim=True, + ) + + # ── 7. Gait action limit penalty ───────────────────────────────────────── + # Small penalty for pushing f_t outside the valid band (paper §III-C). + cfg.rewards["gait_action_limit"] = RewardTermCfg( + func=mdp.gait_action_limit, + weight=-0.25, + params={"action_name": "gait_freq"}, + ) + + # ------------------------------------------------------------------ + # Curriculum + # ------------------------------------------------------------------ + cfg.curriculum["command_vel"] = CurriculumTermCfg( + func=mdp.commands_vel, + params={ + "command_name": "twist", + "velocity_stages": [ + { + "step": 0, + "lin_vel_x": (0.0, 0.5), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.2, 0.2), + }, + { + "step": 4_000 * 24, + "lin_vel_x": (0.0, 1.0), + "lin_vel_y": (0.0, 0.0), + "ang_vel_z": (-0.5, 0.5), + }, + ], + }, + ) + + # --- Terrain reward weight adjustments for training --- + # cfg.rewards["step_accuracy"].weight = 1.0 + cfg.rewards.pop("pose", None) + cfg.rewards.pop("body_orientation_l2", None) + cfg.rewards.pop("foot_clearance", None) # NOT work with terrain + + cfg.rewards["track_linear_velocity"].weight = 3.5 + cfg.rewards["track_angular_velocity"].weight = 3.0 + cfg.rewards["flat_orientation"].weight = -7.0 + cfg.rewards["pelvis_orientation_l2"].weight = -3.0 + cfg.rewards["joint_deviation_hip"].weight = -0.3 + cfg.rewards["ang_vel_xy_l2"].weight = -0.1 + cfg.rewards["dof_torques_l2"].weight = -1e-7 + cfg.rewards["dof_vel_l2"].weight = -5e-7 + cfg.rewards["feet_flat_ori"].weight = -0.01 + cfg.rewards["body_ang_vel"].weight = -0.05 + cfg.rewards["angular_momentum"].weight = -0.001 + cfg.rewards["joint_acc_l2"].weight = -5.0e-7 + cfg.rewards["joint_pos_limits"].weight = -1.0 + cfg.rewards["action_rate_l2"].weight = -0.8 + cfg.rewards["foot_gait"].weight = 2.0 + cfg.rewards["feet_double_support"].weight = 1.5 + cfg.rewards["foot_slip"].weight = -0.4 + cfg.rewards["feet_close_xy"].weight = 1.0 + cfg.rewards["soft_landing"].weight = -1e-3 + cfg.rewards["dont_wait"].weight = -1.0 + cfg.rewards["stand_still"].weight = -2.0 + cfg.rewards["self_collisions"].weight = -2.0 + # cfg.rewards["feet_air_time"].weight = 1.0 + # cfg.rewards["terrain_foot_clearance"].weight = -0.5 + cfg.rewards["feet_air_time_biped"].weight = 3.0 + cfg.rewards["terrain_base_height"].weight = -1.5 + cfg.rewards.pop( + "terrain_foot_clearance", None + ) # Not compatible with heightmap-based foothold planning + cfg.rewards.pop("foot_gait", None) # phase-locked, conflicts with foothold planner + cfg.rewards.pop("feet_double_support", None) # same problem + cfg.rewards.pop( + "feet_air_time", None + ) # Remove air time reward which can conflict with foothold planning + + # Experiment with new foothold penalties + cfg.rewards.pop("foot_edge", None) + cfg.rewards["terrain_stumble"].weight = -1.0 + + return cfg + + +def _create_multi_critic_cfg_from_single_critic( + cfg: VelocityEnvCfg, +) -> MultiCriticManagerBasedRlEnvCfg: + """Helper to copy a single-critic config to multi-critic format.""" + new_cfg = MultiCriticManagerBasedRlEnvCfg( + decimation=cfg.decimation, scene=cfg.scene + ) + new_cfg.observations = deepcopy(cfg.observations) + new_cfg.actions = deepcopy(cfg.actions) + new_cfg.events = deepcopy(cfg.events) + new_cfg.sim = deepcopy(cfg.sim) + new_cfg.viewer = deepcopy(cfg.viewer) + new_cfg.episode_length_s = cfg.episode_length_s + new_cfg.rewards = deepcopy(cfg.rewards) + new_cfg.terminations = deepcopy(cfg.terminations) + new_cfg.commands = deepcopy(cfg.commands) + new_cfg.curriculum = deepcopy(cfg.curriculum) + new_cfg.metrics = deepcopy(cfg.metrics) + new_cfg.is_finite_horizon = cfg.is_finite_horizon + new_cfg.scale_rewards_by_dt = cfg.scale_rewards_by_dt + + return new_cfg + + +def _create_critic_terrain_type_mapping( + cfg: MultiCriticManagerBasedRlEnvCfg, + terrain_type_list: list[str] = ["stair", "gap", "rough"], +): + # Use [stair, gap, rough] or [stair_up, stair_down, gap, rough] as the terrain + # types depending on the sub_terrains defined in the terrain generator config. + # In MJLab curriculum mode, each column is deterministically assigned to one + # sub-terrain by `_generate_curriculum_terrains`: + # sub_index = min(where(col / num_cols + 0.001 < cumsum(proportions))) + # `terrain.terrain_types` stores that column index per env, so to bucket envs + # by terrain category we map column_index -> sub_terrain class -> category. + + if terrain_type_list == ["stair", "gap", "rough"]: + terrain_type_mapping: dict[int, list[int]] = { + 0: [], # stair (both up and down) + 1: [], # gap + 2: [], # rough + } + elif terrain_type_list == ["stair_up", "stair_down", "gap", "rough"]: + terrain_type_mapping: dict[int, list[int]] = { + 0: [], # stair_up + 1: [], # stair_down + 2: [], # gap + 3: [], # rough + } + else: + raise ValueError( + "Unsupported terrain_type_list: {}. Only [stair, gap, rough] or " + "[stair_up, stair_down, gap, rough] are supported.".format( + terrain_type_list + ) + ) + + terrain_generator_cfg = cfg.scene.terrain.terrain_generator + if not terrain_generator_cfg.curriculum: + cfg.scene.terrain.terrain_generator.curriculum = True + + sub_terrains: dict[str, SubTerrainCfg] = terrain_generator_cfg.sub_terrains + sub_terrain_cfgs = list(sub_terrains.values()) + proportions = np.array([s.proportion for s in sub_terrain_cfgs], dtype=np.float64) + proportions /= proportions.sum() + cum_proportions = np.cumsum(proportions) + + num_cols = terrain_generator_cfg.num_cols + for col_idx in range(num_cols): + sub_index = int( + np.min(np.where(col_idx / num_cols + 0.001 < cum_proportions)[0]) + ) + class_name = sub_terrain_cfgs[sub_index].__class__.__name__ + if terrain_type_list == ["stair", "gap", "rough"]: + if "Stair" in class_name or "stair" in class_name: + terrain_type_mapping[0].append(col_idx) + elif "Gap" in class_name or "gap" in class_name: + terrain_type_mapping[1].append(col_idx) + else: + terrain_type_mapping[2].append(col_idx) + elif terrain_type_list == ["stair_up", "stair_down", "gap", "rough"]: + if "Stair" in class_name or "stair" in class_name: + if "BoxOpenStairsTerrainCfg" in class_name: + if sub_terrain_cfgs[sub_index].inverted == False: + terrain_type_mapping[0].append(col_idx) # stair_up + else: + terrain_type_mapping[1].append(col_idx) # stair_down + elif "BoxPyramidStairsTerrainCfg" in class_name: + terrain_type_mapping[0].append(col_idx) # stair_up + elif "BoxInvertedPyramidStairsTerrainCfg" in class_name: + terrain_type_mapping[1].append(col_idx) # stair_down + else: + raise ValueError( + "Unsupported stair type in class_name: {}. Only " + "BoxOpenStairsTerrainCfg, BoxPyramidStairsTerrainCfg, and " + "BoxInvertedPyramidStairsTerrainCfg are supported.".format( + class_name + ) + ) + elif class_name == "BoxSteppingStonesTerrainCfg": + terrain_type_mapping[2].append(col_idx) + else: + terrain_type_mapping[3].append(col_idx) + + # Drop empty buckets and re-index keys to be contiguous 0..N-1, so + # critic_labels emitted by the env line up exactly with critic head indices + # (otherwise the model has to clamp OOB labels, silently mis-routing envs). + non_empty = [v for v in terrain_type_mapping.values() if len(v) > 0] + cfg.critic_terrain_type_mapping = {i: v for i, v in enumerate(non_empty)} + if len(cfg.critic_terrain_type_mapping) == 0: + raise ValueError("No valid terrain types found in sub_terrains.") + if len(cfg.critic_terrain_type_mapping) < 2: + raise ValueError( + "At least 2 terrain types are required for multi-critic training." + ) + cfg.num_critics = len(cfg.critic_terrain_type_mapping) + + +def vr_m3_12dof_foothold_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_foothold_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + return cfg + + +def vr_m3_12dof_foothold_sts_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_foothold_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + cfg.observations["teacher_actor"] = deepcopy(cfg.observations["critic"]) + return cfg + + +def vr_m3_12dof_ga_phl_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_ga_phl_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + return cfg + + +def vr_m3_12dof_ga_phl_sts_multi_critic_env_cfg( + play: bool = False, +) -> MultiCriticManagerBasedRlEnvCfg: + cfg = _create_multi_critic_cfg_from_single_critic( + vr_m3_12dof_ga_phl_env_cfg(play=play) + ) + _create_critic_terrain_type_mapping( + cfg, terrain_type_list=["stair_up", "stair_down", "gap", "rough"] + ) + + cfg.observations["actor"] = cfg.observations.pop("policy") + cfg.observations["teacher_actor"] = deepcopy(cfg.observations["critic"]) + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 1 — Asymmetric actor-critic sensors + Band-specific DR +# --------------------------------------------------------------------------- + +# Actor sensor: foreground scan (heightmap_site is 0.5 m ahead of pelvis in the +# pelvis body frame, so the grid covers 0–1 m forward and ±0.3 m lateral). +# GridPatternCfg(size=(0.6, 1.0), resolution=0.05) → 13 cols × 21 rows = 273 rays +_HM_NUM_Y = 21 # actor grid rows (fwd/back, y) +_HM_NUM_X = 13 # actor grid cols (left/right, x) + +# Critic sensor: full surrounding scan centered on the pelvis body. +# GridPatternCfg(size=(1.0, 1.0), resolution=0.05) → 21 cols × 21 rows = 441 rays +_HM_CRITIC_NUM_Y = 21 # critic grid rows +_HM_CRITIC_NUM_X = 21 # critic grid cols + + +def vr_m3_12dof_height_map_dwt_dr_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """Asymmetric actor-critic height-map env with DWT band-specific DR. + + Two separate raycasters replace the shared ``terrain_scan``: + + * **Actor** (``terrain_scan_actor``): foreground patch mounted at + ``heightmap_site`` (0.5 m ahead of pelvis), 0.6 × 1.0 m @ 0.05 m + resolution, ``include_geom_groups=(0, 1, 2)`` so the actor can detect + body geometry (self-collision awareness during foothold selection). + The height observation uses DWT band-specific domain randomisation to + simulate the real-sensor high-frequency dropout at stair edges. + + * **Critic** (``terrain_scan_critic``): full surrounding patch mounted at + the pelvis body origin, 1.0 × 1.0 m @ 0.05 m resolution, + ``include_geom_groups=(0,)`` (terrain only — body geometry does not + pollute privileged height values). The critic additionally receives a + log-scaled DWT energy ratio as a terrain-type signal. + """ + from src.tasks.velocity.mdp.terrain_classifier import terrain_energy_ratio + + cfg = vr_m3_12dof_height_map_env_cfg(play=play) + + # Remove the single shared terrain_scan added by the base height-map cfg. + cfg.scene.sensors = tuple(s for s in cfg.scene.sensors if s.name != "terrain_scan") + + # Actor sensor — foreground, groups 0-2 (terrain + body). + terrain_scan_actor = RayCastSensorCfg( + name="terrain_scan_actor", + frame=ObjRef(type="site", name="heightmap_site", entity="robot"), + pattern=GridPatternCfg( + size=(0.6, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0, 1, 2), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + # Critic sensor — full surrounding, group 0 only (terrain, no body). + terrain_scan_critic = RayCastSensorCfg( + name="terrain_scan_critic", + frame=ObjRef(type="body", name="pelvis", entity="robot"), + pattern=GridPatternCfg( + size=(1.0, 1.0), + resolution=0.05, + direction=(0.0, 0.0, -1.0), + ), + ray_alignment="yaw", + max_distance=2.0, + include_geom_groups=(0,), + exclude_parent_body=True, + debug_vis=play, + viz=RayCastSensorCfg.VizCfg(show_normals=True), + ) + + cfg.scene.sensors = cfg.scene.sensors + (terrain_scan_actor, terrain_scan_critic) + + # Actor obs: DWT band-specific DR from the foreground sensor. + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_scan_dwt_aug, + params={ + "sensor_name": "terrain_scan_actor", + "num_y": _HM_NUM_Y, + "num_x": _HM_NUM_X, + "miss_value": 2.0, + "sigma_hh": 0.15, + "sigma_lh_hl": 0.05, + "sigma_ll": 0.02, + "attenuation_low": 0.3, + "attenuation_high": 1.0, + }, + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic obs: clean surrounding heightmap (privileged, no noise). + cfg.observations["critic"].terms["height_scan"] = ObservationTermCfg( + func=envs_mdp.height_scan, + params={"sensor_name": "terrain_scan_critic", "miss_value": 2.0}, + clip=(0.0, 2.0), + history_length=5, + ) + + # Critic obs: DWT energy ratio from the surrounding scan. + cfg.observations["critic"].terms["terrain_energy_ratio"] = ObservationTermCfg( + func=terrain_energy_ratio, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + history_length=5, + ) + + if play: + cfg.observations["actor"].enable_corruption = False + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 2 — DWT Encoder + Band DR +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_full_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT encoder with band-specific DR (Phase 2). + + Extends ``vr_m3_12dof_height_map_dwt_dr_env_cfg`` for use with + ``InstinctOnPolicyRunner`` + ``EncoderActorCritic`` + ``DWTParallelLayer``: + + - Actor ``height_scan``: ``height_scan_dwt_aug_as_grid`` — returns a 2D + ``[B, num_y, num_x]`` grid with band-specific DR applied, so + ``DWTParallelLayer`` can reshape it to ``[B, 1, H, W]`` for + ``DWTHeadModel``. Band DR (σ_hh=0.15, σ_lh_hl=0.05, σ_ll=0.02) + simulates real-sensor high-frequency dropout. + - ``concatenate_terms=False`` on actor (mixed 2-D/1-D terms). + - ``"policy"`` obs-group alias added for the instinct runner. + - Critic unchanged from DWT-DR (clean flat surrounding scan + energy ratio). + """ + from copy import deepcopy as _dc + + cfg = vr_m3_12dof_height_map_dwt_dr_env_cfg(play=play) + + # Band-DR augmented 2D grid for the DWT encoder. + # Returns [B, num_y, num_x]; concatenate_terms=False avoids mixed-rank + # torch.stack — the instinct encoder system processes each component separately. + cfg.observations["actor"].terms["height_scan"] = ObservationTermCfg( + func=mdp.height_scan_dwt_aug_as_grid, + params={ + "sensor_name": "terrain_scan_actor", + "num_y": _HM_NUM_Y, + "num_x": _HM_NUM_X, + "miss_value": 2.0, + "sigma_hh": 0.15, + "sigma_lh_hl": 0.05, + "sigma_ll": 0.02, + "attenuation_low": 0.3, + "attenuation_high": 1.0, + }, + clip=(0.0, 2.0), + ) + cfg.observations["actor"].concatenate_terms = False + + # "policy" alias for instinct runner (policy_observation_group="policy"). + cfg.observations["policy"] = _dc(cfg.observations["actor"]) + + if play: + cfg.observations["actor"].enable_corruption = False + cfg.observations["policy"].enable_corruption = False + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 3 — Lightweight Obs & Reward Shaping +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_dr_v2_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT-DR v2: Phase 3 observations and reward terms added to the DWT-DR env. + + Builds on ``vr_m3_12dof_height_map_dwt_dr_env_cfg`` with zero architecture + changes. New critic observations (subband energy map, DWT entropy, cross-band + coherence) give the value function richer terrain-type signals at essentially + zero overhead. Both actor and critic gain a richer velocity representation. + Two DWT-based reward terms encourage action smoothness and gait symmetry. + + New critic obs: + * ``subband_energy_map`` — 4-channel squared energy of DWT subbands + * ``dwt_terrain_entropy`` — Shannon entropy of DWT coefficients [B, 1] + * ``dwt_subband_coherence`` — cross-band (LH/HH, HL/HH) coherence [B, 2] + + New actor+critic obs: + * ``base_lin_vel`` replaced by ``base_velocity_dwt_filtered`` [B, 4] + (vel_x, vel_y, vel_z, speed_xy) + + New rewards (both registered with weight=-1.0 — functions return positive): + * ``dwt_action_smoothness`` — penalise high-freq detail energy in actions + * ``dwt_gait_symmetry`` — penalise L/R joint oscillation asymmetry + """ + from src.tasks.velocity.mdp.terrain_classifier import ( + dwt_terrain_entropy, + dwt_subband_coherence, + ) + + cfg = vr_m3_12dof_height_map_dwt_dr_env_cfg(play=play) + + # -- Critic obs: subband energy map (4 × H' × W' flattened) -- + cfg.observations["critic"].terms["subband_energy_map"] = ObservationTermCfg( + func=mdp.subband_energy_map, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic obs: DWT coefficient entropy -- + cfg.observations["critic"].terms["dwt_terrain_entropy"] = ObservationTermCfg( + func=dwt_terrain_entropy, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic obs: cross-band coherence [B, 2] -- + cfg.observations["critic"].terms["dwt_subband_coherence"] = ObservationTermCfg( + func=dwt_subband_coherence, + params={ + "sensor_name": "terrain_scan_critic", + "num_y": _HM_CRITIC_NUM_Y, + "num_x": _HM_CRITIC_NUM_X, + "miss_value": 2.0, + }, + ) + + # -- Critic: augment base_lin_vel with speed_xy for richer velocity signal [B, 4] -- + # Actor has no linear velocity term (not available from real-robot sensors); + # only the critic gets this privileged signal during training. + cfg.observations["critic"].terms["base_lin_vel"] = ObservationTermCfg( + func=mdp.base_velocity_dwt_filtered, + params={"asset_cfg": SceneEntityCfg("robot")}, + ) + + # -- DWT action smoothness penalty (positive metric, negative weight in cfg) -- + cfg.rewards["dwt_action_smoothness"] = RewardTermCfg( + func=mdp.dwt_action_smoothness, + params={"action_name": "joint_pos", "lambda_hf": 0.01}, + weight=-1.0, + ) + + # -- DWT gait symmetry penalty (positive metric, negative weight in cfg) -- + cfg.rewards["dwt_gait_symmetry"] = RewardTermCfg( + func=mdp.dwt_gait_symmetry, + params={ + "left_cfg": SceneEntityCfg("robot", joint_names=r"left_.*"), + "right_cfg": SceneEntityCfg("robot", joint_names=r"right_.*"), + "lambda_sym": 0.01, + }, + weight=-1.0, + ) + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 4 — 1D Temporal DWT for Proprioceptive Signals +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_height_map_dwt_proprioceptive_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 4: temporal DWT obs for proprioceptive signals on top of DWT-DR-v2. + + Builds on ``vr_m3_12dof_height_map_dwt_dr_v2_env_cfg`` with zero architecture + and no history_length changes. Adds four new obs terms and one new reward: + + New **actor** obs (deployable — no privileged sensors): + * ``imu_dwt_filtered`` [B, 12] — DWT slow-trend + noise-energy of IMU history + * ``joint_history_dwt`` [B, 48] — DWT slow-trend + fast-transient energy of joint history + + New **critic** obs (privileged / training-only): + * ``grf_dwt_features`` [B, 12] — contact onset-sharpness from foot-force history + + New reward (register with weight=-1.0 to penalise oscillatory GRF): + * ``dwt_contact_quality`` — level-1 DWT HF energy in normal GRF + + All DWT terms use level=1 with the existing history_length=5, which satisfies + the Db4 minimum signal length (T>=4). Increase history_length and level to 2 + (requires T>=5 at level 1 and T>=9 for the level-2 recursion) for finer + frequency resolution. + """ + cfg = vr_m3_12dof_height_map_dwt_dr_v2_env_cfg(play=play) + + # -- Actor obs: DWT-compressed IMU (angular velocity + projected gravity) -- + # base_ang_vel and projected_gravity are already in actor_terms (h=5) and + # will be processed BEFORE this term in the obs group dict, populating their + # history buffers before imu_dwt_filtered reads them. + cfg.observations["actor"].terms["imu_dwt_filtered"] = ObservationTermCfg( + func=mdp.imu_dwt_filtered, + params={"obs_group": "actor", "level": 1}, + ) + + # -- Actor obs: DWT-compressed joint history (position + velocity) -- + cfg.observations["actor"].terms["joint_history_dwt"] = ObservationTermCfg( + func=mdp.joint_history_dwt, + params={"obs_group": "actor", "level": 1}, + ) + + # -- Critic obs: GRF onset-sharpness (critic-only; not deployable) -- + # foot_contact_forces is already in critic_terms (h=5); grf_dwt_features + # is appended AFTER it so the buffer is already updated when this runs. + cfg.observations["critic"].terms["grf_dwt_features"] = ObservationTermCfg( + func=mdp.grf_dwt_features, + params={"obs_group": "critic", "level": 1}, + ) + + # -- Reward: penalise oscillatory GRF (smooth, controlled foot placement) -- + cfg.rewards["dwt_contact_quality"] = RewardTermCfg( + func=mdp.dwt_contact_quality_reward, + params={"sensor_name": "feet_ground_contact", "lambda_quality": 0.005}, + weight=-1.0, + ) + + return cfg + + +# --------------------------------------------------------------------------- +# DWT Phase 5 — Depth Image DWT Encoder +# --------------------------------------------------------------------------- + + +def vr_m3_12dof_depth_map_dwt_enc_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 5: depth map task using DepthDWTHeadModel encoder. + + Observation pipeline is identical to ``vr_m3_12dof_depth_map_env_cfg``. + The DWT encoding happens entirely in the network (``DWTParallelLayer`` + + ``DepthDWTHeadModel`` configured in ``vr_m3_12dof_depth_map_dwt_enc_rl_cfg``). + + Adds ``depth_obstacle_channel`` [B, 225] to the policy obs group as a + pre-computed DWT-based obstacle proximity feature (edge energy × inv-depth). + """ + cfg = vr_m3_12dof_depth_map_env_cfg(play=play) + + cfg.observations["policy"].terms["depth_obstacle_channel"] = ObservationTermCfg( + func=mdp.depth_obstacle_channel, + params={ + "sensor_cfg": SceneEntityCfg("camera"), + "image_h": 30, + "image_w": 30, + "data_type": "distance_to_image_plane_noised", + }, + noise=None, + ) + + return cfg + + +def vr_m3_12dof_foothold_depth_map_dwt_enc_env_cfg( + play: bool = False, +) -> "VelocityEnvCfg": + """DWT Phase 5 variant on the foothold base: DepthDWTHeadModel encoder + foothold planner. + + Inherits from ``vr_m3_12dof_foothold_env_cfg`` which already provides the depth + camera, "policy" obs alias, DCM foothold command, and foothold rewards. + + Adds ``depth_obstacle_channel`` [B, 225] to the policy obs group. + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["policy"].terms["depth_obstacle_channel"] = ObservationTermCfg( + func=mdp.depth_obstacle_channel, + params={ + "sensor_cfg": SceneEntityCfg("camera"), + "image_h": 30, + "image_w": 30, + "data_type": "distance_to_image_plane_noised", + }, + noise=None, + ) + + return cfg + +def vr_m3_12dof_foothold_fdf_env_cfg( + play: bool = False, + mask_fraction: float = 0.7, +) -> MultiCriticManagerBasedRlEnvCfg: + """Foothold task with Frequency-Domain Filtering (FDF) on the depth image. + + Replaces the raw delayed depth-image term from ``vr_m3_12dof_foothold_env_cfg`` + with an FFT-based low-pass filtered version (``mdp.depth_image_fft_lowpass_cls``): + a 2D FFT is applied per frame and the outer ``mask_fraction`` of the frequency + spectrum (by radial distance from the DC bin) is zeroed before reconstructing via + inverse FFT. A higher ``mask_fraction`` removes more high-frequency terrain/ + obstacle detail, simulating a lower-bandwidth depth sensor. + + To sweep masking strength (e.g. 0.1 / 0.3 / 0.5 / 0.7), edit this default. + """ + cfg = vr_m3_12dof_foothold_env_cfg(play=play) + + cfg.observations["actor"] = cfg.observations.pop("policy") + + for group in ("actor", "critic"): + base_term = cfg.observations[group].terms["depth_image"] + cfg.observations[group].terms["depth_image"] = replace( + base_term, + func=mdp.depth_image_fft_lowpass_cls(), + params={**base_term.params, "mask_fraction": mask_fraction}, + ) + + return cfg diff --git a/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/policy.onnx b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/policy.onnx new file mode 100644 index 0000000000000000000000000000000000000000..0cd0285f32804eb4e1f3d9a1433b60e212c8d68a --- /dev/null +++ b/vr_m3_12dof_dwt_foothold/2026-07-20_22-14-38_vr_m3_12dof_dwt_foothold/policy.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70195bbd9311f5932e1c885e93d025f087baf4d28c86b36a2ff8ce8e5eb0573e +size 18840693