├── .gitignore ├── LICENSE ├── README.md ├── humanoidverse ├── __init__.py ├── agents │ ├── __init__.py │ ├── base_algo │ │ └── base_algo.py │ ├── callbacks │ │ ├── __init__.py │ │ ├── analysis_plot_force.py │ │ ├── analysis_plot_force_estimator.py │ │ ├── analysis_plot_locomotion.py │ │ ├── analysis_plot_locomotion_estimate_vel.py │ │ ├── analysis_plot_motion_tracking.py │ │ ├── analysis_plot_motion_tracking_openloop.py │ │ ├── analysis_plot_template.html │ │ └── base_callback.py │ ├── dagger │ │ └── dagger.py │ ├── decouple │ │ └── ppo_decoupled.py │ ├── delta_a │ │ └── train_delta_a.py │ ├── delta_dynamics │ │ └── delta_dynamics_model.py │ ├── force_control │ │ ├── ppo_estimator.py │ │ └── ppo_force_estimator.py │ ├── modules │ │ ├── __init__.py │ │ ├── data_utils.py │ │ ├── encoder_modules.py │ │ ├── modules.py │ │ ├── ppo_modules.py │ │ └── world_models.py │ ├── mppi │ │ └── mppi.py │ ├── ppo │ │ └── ppo.py │ └── ppo_locomanip.py ├── config │ ├── algo │ │ └── ppo.yaml │ ├── base.yaml │ ├── base │ │ ├── fabric.yaml │ │ ├── hydra.yaml │ │ └── structure.yaml │ ├── base_eval.yaml │ ├── domain_rand │ │ ├── NO_domain_rand.yaml │ │ └── domain_rand_base.yaml │ ├── env │ │ ├── base_task.yaml │ │ ├── legged_base.yaml │ │ ├── locomotion.yaml │ │ ├── locomotion_genesis.yaml │ │ └── motion_tracking.yaml │ ├── exp │ │ ├── base_exp.yaml │ │ ├── legged_base.yaml │ │ ├── locomotion.yaml │ │ └── motion_tracking.yaml │ ├── obs │ │ ├── legged_obs.yaml │ │ ├── loco │ │ │ ├── leggedloco_obs_history_wolinvel.yaml │ │ │ ├── leggedloco_obs_singlestep_withlinvel.yaml │ │ │ ├── leggedloco_obs_singlestep_wolinvel.yaml │ │ │ └── leggedloco_obs_singlestep_wolinvel_a2c.yaml │ │ └── motion_tracking │ │ │ ├── deepmimic.yaml │ │ │ ├── deepmimic_a2c.yaml │ │ │ ├── deepmimic_a2c_nolinvel_LARGEnoise_history.yaml │ │ │ └── motion_tracking.yaml │ ├── opt │ │ ├── eval_analysis_plot_locomotion.yaml │ │ ├── eval_analysis_plot_motion_tracking.yaml │ │ ├── record.yaml │ │ └── wandb.yaml │ ├── rewards │ │ ├── loco │ │ │ ├── reward_g1_locomotion.yaml │ │ │ ├── reward_g1_unitree.yaml │ │ │ ├── reward_go2_locomotion.yaml │ │ │ ├── reward_go2_locomotion_sysid.yaml │ │ │ ├── reward_h1_2_locomotion.yaml │ │ │ ├── reward_h1_locomotion.yaml │ │ │ ├── reward_h1_locomotion_10dof.yaml │ │ │ ├── reward_h1_locomotion_19dof_2real.yaml │ │ │ └── reward_h1_locomotion_positiveonly.yaml │ │ └── motion_tracking │ │ │ ├── reward_motion_tracking_basic.yaml │ │ │ └── reward_motion_tracking_dm_2real.yaml │ ├── robot │ │ ├── g1 │ │ │ └── g1_29dof_anneal_23dof.yaml │ │ └── robot_base.yaml │ ├── simulator │ │ ├── genesis.yaml │ │ ├── isaacgym.yaml │ │ ├── isaacsim.yaml │ │ └── mujoco.yaml │ └── terrain │ │ ├── terrain_base.yaml │ │ ├── terrain_locomotion.yaml │ │ └── terrain_locomotion_plane.yaml ├── data │ ├── motions │ │ └── g1_29dof_anneal_23dof │ │ │ └── TairanTestbed │ │ │ └── singles │ │ │ └── 0-TairanTestbed_TairanTestbed_CR7_video_CR7_level1_filter_amass.pkl │ └── robots │ │ └── g1 │ │ ├── .asset_hash │ │ ├── g1_29dof_anneal_23dof.urdf │ │ ├── g1_29dof_anneal_23dof.usd │ │ ├── g1_29dof_anneal_23dof.xml │ │ ├── g1_29dof_anneal_23dof_fitmotionONLY.xml │ │ └── meshes │ │ ├── head_link.STL │ │ ├── left_ankle_pitch_link.STL │ │ ├── left_ankle_roll_link.STL │ │ ├── left_elbow_link.STL │ │ ├── left_elbow_link_merge.STL │ │ ├── left_hand_index_0_link.STL │ │ ├── left_hand_index_1_link.STL │ │ ├── left_hand_middle_0_link.STL │ │ ├── left_hand_middle_1_link.STL │ │ ├── left_hand_palm_link.STL │ │ ├── left_hand_thumb_0_link.STL │ │ ├── left_hand_thumb_1_link.STL │ │ ├── left_hand_thumb_2_link.STL │ │ ├── left_hip_pitch_link.STL │ │ ├── left_hip_roll_link.STL │ │ ├── left_hip_yaw_link.STL │ │ ├── left_knee_link.STL │ │ ├── left_rubber_hand.STL │ │ ├── left_shoulder_pitch_link.STL │ │ ├── left_shoulder_roll_link.STL │ │ ├── left_shoulder_yaw_link.STL │ │ ├── left_wrist_pitch_link.STL │ │ ├── left_wrist_roll_link.STL │ │ ├── left_wrist_roll_rubber_hand.STL │ │ ├── left_wrist_yaw_link.STL │ │ ├── logo_link.STL │ │ ├── pelvis.STL │ │ ├── pelvis_contour_link.STL │ │ ├── right_ankle_pitch_link.STL │ │ ├── right_ankle_roll_link.STL │ │ ├── right_elbow_link.STL │ │ ├── right_elbow_link_merge.STL │ │ ├── right_hand_index_0_link.STL │ │ ├── right_hand_index_1_link.STL │ │ ├── right_hand_middle_0_link.STL │ │ ├── right_hand_middle_1_link.STL │ │ ├── right_hand_palm_link.STL │ │ ├── right_hand_thumb_0_link.STL │ │ ├── right_hand_thumb_1_link.STL │ │ ├── right_hand_thumb_2_link.STL │ │ ├── right_hip_pitch_link.STL │ │ ├── right_hip_roll_link.STL │ │ ├── right_hip_yaw_link.STL │ │ ├── right_knee_link.STL │ │ ├── right_rubber_hand.STL │ │ ├── right_shoulder_pitch_link.STL │ │ ├── right_shoulder_roll_link.STL │ │ ├── right_shoulder_yaw_link.STL │ │ ├── right_wrist_pitch_link.STL │ │ ├── right_wrist_roll_link.STL │ │ ├── right_wrist_roll_rubber_hand.STL │ │ ├── right_wrist_yaw_link.STL │ │ ├── torso_constraint_L_link.STL │ │ ├── torso_constraint_L_rod_link.STL │ │ ├── torso_constraint_R_link.STL │ │ ├── torso_constraint_R_rod_link.STL │ │ ├── torso_link.STL │ │ ├── waist_constraint_L.STL │ │ ├── waist_constraint_R.STL │ │ ├── waist_roll_link.STL │ │ ├── waist_support_link.STL │ │ └── waist_yaw_link.STL ├── envs │ ├── __init__.py │ ├── base_task │ │ ├── __init__.py │ │ └── base_task.py │ ├── env_utils │ │ ├── __init__.py │ │ ├── command_generator.py │ │ ├── general.py │ │ ├── history_handler.py │ │ ├── terrain.py │ │ └── visualization.py │ ├── legged_base_task │ │ ├── __init__.py │ │ └── legged_robot_base.py │ ├── locomotion │ │ ├── __init__.py │ │ └── locomotion.py │ └── motion_tracking │ │ ├── __init__.py │ │ └── motion_tracking.py ├── eval_agent.py ├── simulator │ ├── base_simulator │ │ └── base_simulator.py │ ├── genesis │ │ ├── genesis.py │ │ ├── genesis_mjdebug.py │ │ ├── genesis_viewer.py │ │ └── tmp_gs_utils.py │ ├── isaacgym │ │ ├── isaacgym.py │ │ └── isaacgym_hoi.py │ └── isaacsim │ │ ├── event_cfg.py │ │ ├── events.py │ │ ├── isaaclab_cfg.py │ │ ├── isaaclab_viewpoint_camera_controller.py │ │ ├── isaacsim.py │ │ └── isaacsim_articulation_cfg.py ├── train_agent.py └── utils │ ├── __init__.py │ ├── average_meters.py │ ├── common.py │ ├── config_utils.py │ ├── helpers.py │ ├── inference_helpers.py │ ├── logging.py │ ├── math.py │ ├── motion_lib │ ├── __init__.py │ ├── motion_lib_base.py │ ├── motion_lib_robot.py │ ├── motion_utils │ │ ├── __init__.py │ │ ├── flags.py │ │ └── rotation_conversions.py │ ├── skeleton.py │ └── torch_humanoid_batch.py │ ├── terrain.py │ └── torch_utils.py ├── imgs ├── CMU-NV-logo-crop-png.png └── motion_tracking_5800.gif ├── isaac_utils ├── isaac_utils │ ├── __init__.py │ ├── maths.py │ └── rotations.py └── setup.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Python bytecode 2 | *.py[cod] 3 | # Log files 4 | *.log 5 | # * ONNX files 6 | # *.onnx 7 | 8 | # JetBrains IDE 9 | .idea/ 10 | .vscode/ 11 | 12 | # Generated by MacOS 13 | .DS_Store 14 | 15 | # Generated by Windows 16 | Thumbs.db 17 | 18 | # Applications 19 | *.app 20 | *.exe 21 | *.war 22 | 23 | # Large media files 24 | *.mp4 25 | *.tiff 26 | *.avi 27 | *.flv 28 | *.mov 29 | *.wmv 30 | 31 | # logs 32 | logs 33 | logs_eval 34 | runs 35 | outputs 36 | results/ 37 | hydra_logs/ 38 | wandb/ 39 | # other 40 | *.egg-info 41 | __pycache__ 42 | 43 | roboverse/data/motions 44 | *.pkl 45 | *.pt 46 | 47 | *.TXT 48 | 49 | sim2real/models/*.onnx 50 | sim2real/models/dec_loco/*.onnx 51 | 52 | roboverse/data/smpl 53 | data/shape 54 | data/motions 55 | roboverse/data/Recorded/ 56 | roboverse/data/AMASS/ 57 | AMASS/* 58 | 59 | *.sh 60 | *.txt 61 | 62 | eval_g129dof_checkpoints 63 | _isaac_sim 64 | scripts/batch_eval/*.log 65 | 66 | TairanTestbed_0104_checkpoints 67 | TairanTestbed_0109_checkpoints 68 | TairanTestbed_0109_eval_g129dof_anneal_23dof_checkpoints 69 | TairanTestbed_0109_eval_g129dof_anneal_23dof_checkpoints_20250112_1853 70 | TairanTestbed_0109_eval_g129dof_anneal_23dof_checkpoints_20250113_1731 71 | *.zip 72 | TairanTestbed_0109_eval_g129dof_anneal_23dof_checkpoints_20250113_2229_MinimalFriction-0.3_RfiFalse 73 | 74 | TairanTestbed_0109_eval_g129dof_anneal_23dof_checkpoints_20250118_1849_MinimalFriction-0.3_RfiTrue_Far0.325_RESUME_LARGENOISE 75 | TairanTestbed_0109_eval_g129dof_anneal_23dof_checkpoints_20250119_2018_MinimalFriction-0.3_RfiTrue_Far0.325_RESUME_LARGENOISE 76 | hubble_data 77 | 78 | osmocheckpoints 79 | 80 | ./scripts/batch_eval 81 | ./scripts/batch_osmo_scp 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 ASAP Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /humanoidverse/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/__init__.py -------------------------------------------------------------------------------- /humanoidverse/agents/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/agents/__init__.py -------------------------------------------------------------------------------- /humanoidverse/agents/base_algo/base_algo.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from torch import nn, Tensor 4 | 5 | import time 6 | import math 7 | from pathlib import Path 8 | from typing import Optional, List, Tuple, Dict 9 | 10 | 11 | from hydra.utils import instantiate 12 | 13 | from humanoidverse.envs.base_task.base_task import BaseTask 14 | 15 | class BaseAlgo: 16 | def __init__(self, env: BaseTask, config, device): 17 | self.env = env 18 | self.config = config 19 | self.device = device 20 | 21 | def setup(self): 22 | return NotImplementedError 23 | 24 | def learn(self): 25 | return NotImplementedError 26 | 27 | def load(self, path): 28 | return NotImplementedError 29 | 30 | @property 31 | def inference_model(self): 32 | return NotImplementedError 33 | 34 | def env_step(self, actions, extra_info=None): 35 | obs_dict, rewards, dones, extras = self.env.step(actions, extra_info) 36 | return obs_dict, rewards, dones, extras 37 | 38 | @torch.no_grad() 39 | def evaluate_policy(self): 40 | return NotImplementedError 41 | 42 | def save(self, path=None, name="last.ckpt"): 43 | raise NotImplementedError 44 | -------------------------------------------------------------------------------- /humanoidverse/agents/callbacks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/agents/callbacks/__init__.py -------------------------------------------------------------------------------- /humanoidverse/agents/callbacks/analysis_plot_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 38 | 39 | 40 |
41 |

Robot State Plots

42 |
43 |

Loading plots...

44 |
45 |
46 | 52 | 53 | -------------------------------------------------------------------------------- /humanoidverse/agents/callbacks/base_callback.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.nn import Module 3 | 4 | class RL_EvalCallback(Module): 5 | def __init__(self, config, training_loop): 6 | super().__init__() 7 | self.config = config 8 | self.training_loop = training_loop 9 | self.device = self.training_loop.device 10 | 11 | def on_pre_evaluate_policy(self): 12 | pass 13 | 14 | def on_pre_eval_env_step(self, actor_state): 15 | return actor_state 16 | 17 | def on_post_eval_env_step(self, actor_state): 18 | return actor_state 19 | 20 | def on_post_evaluate_policy(self): 21 | pass 22 | -------------------------------------------------------------------------------- /humanoidverse/agents/decouple/ppo_decoupled.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.optim as optim 4 | 5 | from humanoidverse.agents.modules.ppo_modules import PPOActor, PPOCritic 6 | from humanoidverse.agents.modules.data_utils import RolloutStorage 7 | from humanoidverse.envs.base_task.base_task import BaseTask 8 | from humanoidverse.agents.ppo.ppo import PPO 9 | from humanoidverse.agents.callbacks.base_callback import RL_EvalCallback 10 | from humanoidverse.utils.average_meters import TensorAverageMeterDict 11 | 12 | from torch.utils.tensorboard import SummaryWriter as TensorboardSummaryWriter 13 | import time 14 | import os 15 | import statistics 16 | from collections import deque 17 | from hydra.utils import instantiate 18 | from loguru import logger 19 | from rich.progress import track 20 | from rich.console import Console 21 | from rich.panel import Panel 22 | from rich.live import Live 23 | console = Console() 24 | 25 | class PPODecoupled(PPO): 26 | def __init__(self, 27 | env: BaseTask, 28 | config, 29 | log_dir=None, 30 | device='cpu'): 31 | super().__init__(env, config, log_dir, device) 32 | 33 | def _init_config(self): 34 | super()._init_config() 35 | self.num_act = self.env.config.robot.lower_body_actions_dim 36 | 37 | def setup(self): 38 | logger.info("Setting up PPO_Decoupled") 39 | self._setup_models_and_optimizer() 40 | logger.info(f"Setting up Storage") 41 | self._setup_storage() 42 | 43 | def _setup_models_and_optimizer(self): 44 | self.actor = PPOActor( 45 | obs_dim_dict=self.algo_obs_dim_dict, 46 | module_config_dict=self.config.module_dict.actor, 47 | num_actions=self.num_act, 48 | init_noise_std=self.config.init_noise_std 49 | ).to(self.device) 50 | 51 | self.critic = PPOCritic(self.algo_obs_dim_dict, 52 | self.config.module_dict.critic).to(self.device) 53 | 54 | self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=self.actor_learning_rate) 55 | self.critic_optimizer = optim.Adam(self.critic.parameters(), lr=self.critic_learning_rate) 56 | 57 | def _rollout_step(self, obs_dict): 58 | with torch.inference_mode(): 59 | for i in range(self.num_steps_per_env): 60 | # Compute the actions and values 61 | # actions = self.actor.act(obs_dict["actor_obs"]).detach() 62 | 63 | policy_state_dict = {} 64 | policy_state_dict = self._actor_rollout_step(obs_dict, policy_state_dict) 65 | values = self._critic_eval_step(obs_dict).detach() 66 | policy_state_dict["values"] = values 67 | 68 | ## Append states to storage 69 | for obs_key in obs_dict.keys(): 70 | self.storage.update_key(obs_key, obs_dict[obs_key]) 71 | 72 | for obs_ in policy_state_dict.keys(): 73 | self.storage.update_key(obs_, policy_state_dict[obs_]) 74 | 75 | ## Get the lower body actions 76 | actions_lower_body = policy_state_dict["actions"] 77 | ## Get the upper body actions 78 | actions_upper_body = self.env.ref_upper_dof_pos 79 | ## Concatenate the lower and upper body actions 80 | actions = torch.cat([actions_lower_body, actions_upper_body], dim=1) 81 | actor_state = {"actions": actions} 82 | obs_dict, rewards, dones, infos = self.env.step(actor_state) 83 | # critic_obs = privileged_obs if privileged_obs is not None else obs 84 | for obs_key in obs_dict.keys(): 85 | obs_dict[obs_key] = obs_dict[obs_key].to(self.device) 86 | rewards, dones = rewards.to(self.device), dones.to(self.device) 87 | 88 | self.episode_env_tensors.add(infos["to_log"]) 89 | rewards_stored = rewards.clone().unsqueeze(1) 90 | if 'time_outs' in infos: 91 | rewards_stored += self.gamma * policy_state_dict['values'] * infos['time_outs'].unsqueeze(1).to(self.device) 92 | assert len(rewards_stored.shape) == 2 93 | self.storage.update_key('rewards', rewards_stored) 94 | self.storage.update_key('dones', dones.unsqueeze(1)) 95 | self.storage.increment_step() 96 | 97 | self._process_env_step(rewards, dones, infos) 98 | 99 | if self.log_dir is not None: 100 | # Book keeping 101 | if 'episode' in infos: 102 | self.ep_infos.append(infos['episode']) 103 | self.cur_reward_sum += rewards 104 | self.cur_episode_length += 1 105 | new_ids = (dones > 0).nonzero(as_tuple=False) 106 | self.rewbuffer.extend(self.cur_reward_sum[new_ids][:, 0].cpu().numpy().tolist()) 107 | self.lenbuffer.extend(self.cur_episode_length[new_ids][:, 0].cpu().numpy().tolist()) 108 | self.cur_reward_sum[new_ids] = 0 109 | self.cur_episode_length[new_ids] = 0 110 | 111 | self.stop_time = time.time() 112 | self.collection_time = self.stop_time - self.start_time 113 | self.start_time = self.stop_time 114 | 115 | # prepare data for training 116 | 117 | returns, advantages = self._compute_returns( 118 | last_obs_dict=obs_dict, 119 | policy_state_dict=dict(values=self.storage.query_key('values'), 120 | dones=self.storage.query_key('dones'), 121 | rewards=self.storage.query_key('rewards')) 122 | ) 123 | self.storage.batch_update_data('returns', returns) 124 | self.storage.batch_update_data('advantages', advantages) 125 | 126 | # Update the upper body action scale 127 | if len(self.lenbuffer) == 0: 128 | mean_lenbuffer = 0 129 | else: mean_lenbuffer = statistics.mean(self.lenbuffer) 130 | if mean_lenbuffer > 0.9 * self.env.max_episode_length: 131 | self.env.action_scale_upper_body += 0.05 132 | else: 133 | self.env.action_scale_upper_body -= 0.01 134 | # Constraint the upper body action scale to (0, 1) 135 | self.env.action_scale_upper_body = max(0, min(self.env.action_scale_upper_body, 1)) 136 | 137 | return obs_dict 138 | 139 | def _logging_to_writer(self, log_dict, train_log_dict, env_log_dict): 140 | super()._logging_to_writer(log_dict, train_log_dict, env_log_dict) 141 | # Log the action scale for the upper body 142 | self.writer.add_scalar('Env/action_scale_upper_body', self.env.action_scale_upper_body, log_dict['it']) 143 | 144 | def env_step(self, actor_state): 145 | actions_lower_body = actor_state["actions"] 146 | actions_upper_body = self.env.ref_upper_dof_pos 147 | actions = torch.cat([actions_lower_body, actions_upper_body], dim=1) 148 | actor_state = {"actions": actions} 149 | obs_dict, rewards, dones, extras = self.env.step(actor_state) 150 | actor_state.update( 151 | {"obs": obs_dict, "rewards": rewards, "dones": dones, "extras": extras} 152 | ) 153 | return actor_state -------------------------------------------------------------------------------- /humanoidverse/agents/force_control/ppo_estimator.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torch.optim as optim 5 | 6 | 7 | from humanoidverse.agents.modules.data_utils import RolloutStorage 8 | from humanoidverse.agents.ppo.ppo import PPO 9 | from humanoidverse.envs.base_task.base_task import BaseTask 10 | from humanoidverse.agents.callbacks.base_callback import RL_EvalCallback 11 | from humanoidverse.utils.average_meters import TensorAverageMeterDict 12 | from humanoidverse.agents.modules.encoder_modules import Estimator 13 | 14 | from torch.utils.tensorboard import SummaryWriter as TensorboardSummaryWriter 15 | import time 16 | import os 17 | import statistics 18 | from collections import deque 19 | from hydra.utils import instantiate 20 | from loguru import logger 21 | from rich.progress import track 22 | from rich.console import Console 23 | from rich.panel import Panel 24 | from rich.live import Live 25 | console = Console() 26 | 27 | class PPOEstimator(PPO): 28 | def __init__(self, 29 | env: BaseTask, 30 | config, 31 | log_dir=None, 32 | device='cpu'): 33 | super().__init__(env, config, log_dir, device) 34 | 35 | def _setup_models_and_optimizer(self): 36 | super()._setup_models_and_optimizer() 37 | 38 | self.estimator = Estimator(self.algo_obs_dim_dict, 39 | self.config.module_dict.estimator).to(self.device) 40 | self.optimizer_estimator = torch.optim.Adam(self.estimator.parameters(), 41 | lr=self.config.estimator_learning_rate) 42 | 43 | def load(self, ckpt_path): 44 | if ckpt_path is not None: 45 | logger.info(f"Loading checkpoint from {ckpt_path}") 46 | loaded_dict = torch.load(ckpt_path, map_location=self.device) 47 | self.actor.load_state_dict(loaded_dict["actor_model_state_dict"]) 48 | self.critic.load_state_dict(loaded_dict["critic_model_state_dict"]) 49 | self.estimator.load_state_dict(loaded_dict["estimator_model_state_dict"]) 50 | if self.load_optimizer: 51 | self.actor_optimizer.load_state_dict(loaded_dict["actor_optimizer_state_dict"]) 52 | self.critic_optimizer.load_state_dict(loaded_dict["critic_optimizer_state_dict"]) 53 | self.optimizer_estimator.load_state_dict(loaded_dict["estimator_optimizer_state_dict"]) 54 | self.actor_learning_rate = loaded_dict['actor_optimizer_state_dict']['param_groups'][0]['lr'] 55 | self.critic_learning_rate = loaded_dict['critic_optimizer_state_dict']['param_groups'][0]['lr'] 56 | self.estimator_learning_rate = loaded_dict['estimator_optimizer_state_dict']['param_groups'][0]['lr'] 57 | self.set_learning_rate(self.actor_learning_rate, self.critic_learning_rate, self.estimator_learning_rate) 58 | logger.info(f"Optimizer loaded from checkpoint") 59 | logger.info(f"Actor Learning rate: {self.actor_learning_rate}") 60 | logger.info(f"Critic Learning rate: {self.critic_learning_rate}") 61 | logger.info(f"Estimator Learning rate: {self.estimator_learning_rate}") 62 | self.current_learning_iteration = loaded_dict["iter"] 63 | return loaded_dict["infos"] 64 | 65 | def set_learning_rate(self, actor_learning_rate, critic_learning_rate, estimator_learning_rate): 66 | self.actor_learning_rate = actor_learning_rate 67 | self.critic_learning_rate = critic_learning_rate 68 | self.estimator_learning_rate = estimator_learning_rate 69 | def save(self, path, infos=None): 70 | logger.info(f"Saving checkpoint to {path}") 71 | torch.save({ 72 | 'actor_model_state_dict': self.actor.state_dict(), 73 | 'critic_model_state_dict': self.critic.state_dict(), 74 | 'estimator_model_state_dict': self.estimator.state_dict(), 75 | 'actor_optimizer_state_dict': self.actor_optimizer.state_dict(), 76 | 'critic_optimizer_state_dict': self.critic_optimizer.state_dict(), 77 | 'estimator_optimizer_state_dict': self.optimizer_estimator.state_dict(), 78 | 'iter': self.current_learning_iteration, 79 | 'infos': infos, 80 | }, path) 81 | 82 | def _eval_mode(self): 83 | super()._eval_mode() 84 | self.estimator.eval() 85 | 86 | def _train_mode(self): 87 | super()._train_mode() 88 | self.estimator.train() 89 | 90 | def _setup_storage(self): 91 | super()._setup_storage() 92 | self.storage.register_key('estimator_output', shape=(self.algo_obs_dim_dict["estimator_target"],), dtype=torch.float) 93 | 94 | def _init_loss_dict_at_training_step(self): 95 | loss_dict = super()._init_loss_dict_at_training_step() 96 | loss_dict['Estimator_Loss'] = 0 97 | return loss_dict 98 | 99 | def _update_algo_step(self, policy_state_dict, loss_dict): 100 | loss_dict = super()._update_algo_step(policy_state_dict, loss_dict) 101 | loss_dict = self._update_estimator(policy_state_dict, loss_dict) 102 | return loss_dict 103 | 104 | def _actor_act_step(self, obs_dict): 105 | long_history = obs_dict["long_history_for_estimator"] 106 | estimator_output = self.estimator(long_history).detach() 107 | actor_obs = obs_dict["actor_obs"] 108 | actor_input = torch.cat([actor_obs, estimator_output], dim=-1) 109 | return self.actor.act(actor_input) 110 | 111 | def _update_estimator(self, policy_state_dict, loss_dict): 112 | estimator_target = policy_state_dict["estimator_target"] 113 | estimator_output = self.estimator(policy_state_dict["long_history_for_estimator"]) 114 | estimator_loss = F.mse_loss(estimator_output, estimator_target) 115 | 116 | self.optimizer_estimator.zero_grad() 117 | estimator_loss.backward() 118 | nn.utils.clip_grad_norm_(self.estimator.parameters(), self.max_grad_norm) 119 | self.optimizer_estimator.step() 120 | 121 | loss_dict['Estimator_Loss'] = estimator_loss 122 | return loss_dict 123 | 124 | ########################################################################################## 125 | # Code for Evaluation 126 | ########################################################################################## 127 | def _pre_eval_env_step(self, actor_state: dict): 128 | estimator_output = self.estimator(actor_state["obs"]['long_history_for_estimator']) 129 | actor_state.update({"estimator_output": estimator_output}) 130 | input_for_actor = torch.cat([actor_state["obs"]['actor_obs'], estimator_output], dim=-1) 131 | actions = self.eval_policy(input_for_actor) 132 | actor_state.update({"actions": actions}) 133 | for c in self.eval_callbacks: 134 | actor_state = c.on_pre_eval_env_step(actor_state) 135 | return actor_state 136 | 137 | @property 138 | def inference_model(self): 139 | return { 140 | "actor": self.actor, 141 | "critic": self.critic, 142 | "estimator": self.estimator 143 | } -------------------------------------------------------------------------------- /humanoidverse/agents/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/agents/modules/__init__.py -------------------------------------------------------------------------------- /humanoidverse/agents/modules/data_utils.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn, Tensor 3 | 4 | 5 | def compute_returns(self, rewards, values, dones, last_values, gamma, lam): 6 | advantage = 0 7 | returns = torch.zeros_like(values) 8 | for step in reversed(range(self.num_transitions_per_env)): 9 | if step == self.num_transitions_per_env - 1: 10 | next_values = last_values 11 | else: 12 | next_values = values[step + 1] 13 | next_is_not_terminal = 1.0 - dones[step].float() 14 | delta = rewards[step] + next_is_not_terminal * gamma * next_values - values[step] 15 | advantage = delta + next_is_not_terminal * gamma * lam * advantage 16 | returns[step] = advantage + values[step] 17 | 18 | # Compute and normalize the advantages 19 | advantages = returns - values 20 | advantages = (advantages - advantages.mean()) / (advantages.std() + 1e-8) 21 | 22 | class RolloutStorage(nn.Module): 23 | 24 | def __init__(self, num_envs, num_transitions_per_env, device='cpu'): 25 | 26 | super().__init__() 27 | 28 | self.device = device 29 | 30 | self.num_transitions_per_env = num_transitions_per_env 31 | self.num_envs = num_envs 32 | 33 | # rnn 34 | # self.saved_hidden_states_a = None 35 | # self.saved_hidden_states_c = None 36 | 37 | self.step = 0 38 | self.stored_keys = list() 39 | 40 | def register_key(self, key: str, shape=(), dtype=torch.float): 41 | # This class was partially copied from https://github.com/NVlabs/ProtoMotions/blob/94059259ba2b596bf908828cc04e8fc6ff901114/phys_anim/agents/utils/data_utils.py 42 | assert not hasattr(self, key), key 43 | assert isinstance(shape, (list, tuple)), "shape must be a list or tuple" 44 | buffer = torch.zeros( 45 | (self.num_transitions_per_env, self.num_envs) + shape, dtype=dtype, device=self.device 46 | ) 47 | self.register_buffer(key, buffer, persistent=False) 48 | self.stored_keys.append(key) 49 | 50 | def increment_step(self): 51 | self.step += 1 52 | 53 | def update_key(self, key: str, data: Tensor): 54 | # This class was partially copied from https://github.com/NVlabs/ProtoMotions/blob/94059259ba2b596bf908828cc04e8fc6ff901114/phys_anim/agents/utils/data_utils.py 55 | assert not data.requires_grad 56 | assert self.step < self.num_transitions_per_env, "Rollout buffer overflow" 57 | getattr(self, key)[self.step].copy_(data) 58 | 59 | def batch_update_data(self, key: str, data: Tensor): 60 | # This class was partially copied from https://github.com/NVlabs/ProtoMotions/blob/94059259ba2b596bf908828cc04e8fc6ff901114/phys_anim/agents/utils/data_utils.py 61 | assert not data.requires_grad 62 | getattr(self, key)[:] = data 63 | # self.store_dict[key] += self.total_sum() 64 | 65 | def _save_hidden_states(self, hidden_states): 66 | assert NotImplementedError 67 | if hidden_states is None or hidden_states==(None, None): 68 | return 69 | # make a tuple out of GRU hidden state sto match the LSTM format 70 | hid_a = hidden_states[0] if isinstance(hidden_states[0], tuple) else (hidden_states[0],) 71 | hid_c = hidden_states[1] if isinstance(hidden_states[1], tuple) else (hidden_states[1],) 72 | 73 | # initialize if needed 74 | if self.saved_hidden_states_a is None: 75 | self.saved_hidden_states_a = [torch.zeros(self.observations.shape[0], *hid_a[i].shape, device=self.device) for i in range(len(hid_a))] 76 | self.saved_hidden_states_c = [torch.zeros(self.observations.shape[0], *hid_c[i].shape, device=self.device) for i in range(len(hid_c))] 77 | # copy the states 78 | for i in range(len(hid_a)): 79 | self.saved_hidden_states_a[i][self.step].copy_(hid_a[i]) 80 | self.saved_hidden_states_c[i][self.step].copy_(hid_c[i]) 81 | 82 | def clear(self): 83 | self.step = 0 84 | 85 | 86 | def get_statistics(self): 87 | raise NotImplementedError 88 | done = self.dones 89 | done[-1] = 1 90 | flat_dones = done.permute(1, 0, 2).reshape(-1, 1) 91 | done_indices = torch.cat((flat_dones.new_tensor([-1], dtype=torch.int64), flat_dones.nonzero(as_tuple=False)[:, 0])) 92 | trajectory_lengths = (done_indices[1:] - done_indices[:-1]) 93 | return trajectory_lengths.float().mean(), self.rewards.mean() 94 | 95 | def query_key(self, key: str): 96 | assert hasattr(self, key), key 97 | return getattr(self, key) 98 | 99 | def mini_batch_generator(self, num_mini_batches, num_epochs=8): 100 | batch_size = self.num_envs * self.num_transitions_per_env 101 | mini_batch_size = batch_size // num_mini_batches 102 | indices = torch.randperm(num_mini_batches*mini_batch_size, requires_grad=False, device=self.device) 103 | 104 | _buffer_dict = {key: getattr(self, key)[:].flatten(0, 1) for key in self.stored_keys} 105 | 106 | for epoch in range(num_epochs): 107 | for i in range(num_mini_batches): 108 | 109 | start = i*mini_batch_size 110 | end = (i+1)*mini_batch_size 111 | batch_idx = indices[start:end] 112 | 113 | _batch_buffer_dict = {key: _buffer_dict[key][batch_idx] for key in self.stored_keys} 114 | yield _batch_buffer_dict 115 | -------------------------------------------------------------------------------- /humanoidverse/agents/modules/encoder_modules.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import torch 4 | import torch.nn as nn 5 | from .modules import BaseModule 6 | 7 | 8 | class Estimator(nn.Module): 9 | def __init__(self, obs_dim_dict, module_config_dict): 10 | super(Estimator, self).__init__() 11 | self.module = BaseModule(obs_dim_dict, module_config_dict) 12 | 13 | # def estimate(self, obs_history): 14 | # return self.module(obs_history) 15 | 16 | def forward(self, obs_history): 17 | return self.module(obs_history) -------------------------------------------------------------------------------- /humanoidverse/agents/modules/modules.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import inspect 4 | 5 | class BaseModule(nn.Module): 6 | def __init__(self, obs_dim_dict, module_config_dict): 7 | super(BaseModule, self).__init__() 8 | self.obs_dim_dict = obs_dim_dict 9 | self.module_config_dict = module_config_dict 10 | 11 | self._calculate_input_dim() 12 | self._calculate_output_dim() 13 | self._build_network_layer(self.module_config_dict.layer_config) 14 | 15 | def _calculate_input_dim(self): 16 | # calculate input dimension based on the input specifications 17 | input_dim = 0 18 | for each_input in self.module_config_dict['input_dim']: 19 | if each_input in self.obs_dim_dict: 20 | # atomic observation type 21 | input_dim += self.obs_dim_dict[each_input] 22 | elif isinstance(each_input, (int, float)): 23 | # direct numeric input 24 | input_dim += each_input 25 | else: 26 | current_function_name = inspect.currentframe().f_code.co_name 27 | raise ValueError(f"{current_function_name} - Unknown input type: {each_input}") 28 | 29 | self.input_dim = input_dim 30 | 31 | def _calculate_output_dim(self): 32 | output_dim = 0 33 | for each_output in self.module_config_dict['output_dim']: 34 | if isinstance(each_output, (int, float)): 35 | output_dim += each_output 36 | else: 37 | current_function_name = inspect.currentframe().f_code.co_name 38 | raise ValueError(f"{current_function_name} - Unknown output type: {each_output}") 39 | self.output_dim = output_dim 40 | 41 | def _build_network_layer(self, layer_config): 42 | if layer_config['type'] == 'MLP': 43 | self._build_mlp_layer(layer_config) 44 | else: 45 | raise NotImplementedError(f"Unsupported layer type: {layer_config['type']}") 46 | 47 | def _build_mlp_layer(self, layer_config): 48 | layers = [] 49 | hidden_dims = layer_config['hidden_dims'] 50 | output_dim = self.output_dim 51 | activation = getattr(nn, layer_config['activation'])() 52 | 53 | layers.append(nn.Linear(self.input_dim, hidden_dims[0])) 54 | layers.append(activation) 55 | 56 | for l in range(len(hidden_dims)): 57 | if l == len(hidden_dims) - 1: 58 | layers.append(nn.Linear(hidden_dims[l], output_dim)) 59 | else: 60 | layers.append(nn.Linear(hidden_dims[l], hidden_dims[l + 1])) 61 | layers.append(activation) 62 | 63 | self.module = nn.Sequential(*layers) 64 | 65 | def forward(self, input): 66 | return self.module(input) -------------------------------------------------------------------------------- /humanoidverse/agents/modules/ppo_modules.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from copy import deepcopy 3 | 4 | import torch 5 | import torch.nn as nn 6 | from torch.distributions import Normal 7 | 8 | from .modules import BaseModule 9 | 10 | class PPOActor(nn.Module): 11 | def __init__(self, 12 | obs_dim_dict, 13 | module_config_dict, 14 | num_actions, 15 | init_noise_std): 16 | super(PPOActor, self).__init__() 17 | 18 | module_config_dict = self._process_module_config(module_config_dict, num_actions) 19 | 20 | self.actor_module = BaseModule(obs_dim_dict, module_config_dict) 21 | 22 | # Action noise 23 | self.std = nn.Parameter(init_noise_std * torch.ones(num_actions)) 24 | self.distribution = None 25 | # disable args validation for speedup 26 | Normal.set_default_validate_args = False 27 | 28 | def _process_module_config(self, module_config_dict, num_actions): 29 | for idx, output_dim in enumerate(module_config_dict['output_dim']): 30 | if output_dim == 'robot_action_dim': 31 | module_config_dict['output_dim'][idx] = num_actions 32 | return module_config_dict 33 | 34 | @property 35 | def actor(self): 36 | return self.actor_module 37 | 38 | @staticmethod 39 | # not used at the moment 40 | def init_weights(sequential, scales): 41 | [torch.nn.init.orthogonal_(module.weight, gain=scales[idx]) for idx, module in 42 | enumerate(mod for mod in sequential if isinstance(mod, nn.Linear))] 43 | 44 | def reset(self, dones=None): 45 | pass 46 | 47 | def forward(self): 48 | raise NotImplementedError 49 | 50 | @property 51 | def action_mean(self): 52 | return self.distribution.mean 53 | 54 | @property 55 | def action_std(self): 56 | return self.distribution.stddev 57 | 58 | @property 59 | def entropy(self): 60 | return self.distribution.entropy().sum(dim=-1) 61 | 62 | def update_distribution(self, actor_obs): 63 | mean = self.actor(actor_obs) 64 | self.distribution = Normal(mean, mean*0. + self.std) 65 | 66 | def act(self, actor_obs, **kwargs): 67 | self.update_distribution(actor_obs) 68 | return self.distribution.sample() 69 | 70 | def get_actions_log_prob(self, actions): 71 | return self.distribution.log_prob(actions).sum(dim=-1) 72 | 73 | def act_inference(self, actor_obs): 74 | actions_mean = self.actor(actor_obs) 75 | return actions_mean 76 | 77 | def to_cpu(self): 78 | self.actor = deepcopy(self.actor).to('cpu') 79 | self.std.to('cpu') 80 | 81 | 82 | 83 | class PPOCritic(nn.Module): 84 | def __init__(self, 85 | obs_dim_dict, 86 | module_config_dict): 87 | super(PPOCritic, self).__init__() 88 | 89 | self.critic_module = BaseModule(obs_dim_dict, module_config_dict) 90 | 91 | @property 92 | def critic(self): 93 | return self.critic_module 94 | 95 | def reset(self, dones=None): 96 | pass 97 | 98 | def evaluate(self, critic_obs, **kwargs): 99 | value = self.critic(critic_obs) 100 | return value 101 | 102 | # Deprecated: TODO: Let Wenli Fix this 103 | class PPOActorFixSigma(PPOActor): 104 | def __init__(self, 105 | obs_dim_dict, 106 | network_dict, 107 | network_load_dict, 108 | num_actions,): 109 | super(PPOActorFixSigma, self).__init__(obs_dim_dict, network_dict, network_load_dict, num_actions, 0.0) 110 | 111 | def update_distribution(self, obs_dict): 112 | mean = self.actor(obs_dict)['head'] 113 | self.distribution = mean 114 | 115 | @property 116 | def action_mean(self): 117 | return self.distribution 118 | 119 | def get_actions_log_prob(self, actions): 120 | raise NotImplementedError 121 | 122 | def act(self, obs_dict, **kwargs): 123 | self.update_distribution(obs_dict) 124 | return self.distribution -------------------------------------------------------------------------------- /humanoidverse/agents/modules/world_models.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import numpy as np 3 | from torch.utils.tensorboard import SummaryWriter as TensorboardSummaryWriter 4 | import os 5 | import statistics 6 | from collections import deque 7 | import copy 8 | from typing import Optional, Tuple, Dict 9 | from isaacgym import gymapi 10 | from isaacgym import gymtorch 11 | from hydra.utils import instantiate 12 | 13 | 14 | class BaseWorldModel(): 15 | def __init__(self, config, device='cpu'): 16 | self.config = config 17 | self.device = device 18 | 19 | def step(self, action): 20 | raise NotImplementedError 21 | 22 | def next(self, obs, action): 23 | raise NotImplementedError 24 | 25 | def reset(self, state=None, buffer=None): 26 | raise NotImplementedError 27 | 28 | 29 | class SimWorldModel(BaseWorldModel): 30 | def __init__(self, 31 | config, 32 | env, 33 | n_samples:Optional[int]=100, 34 | device='cpu'): 35 | super(SimWorldModel, self).__init__(config, device) 36 | self.env = env 37 | self.env.set_is_evaluating() 38 | self.num_samples = n_samples 39 | self.action_dim = self.env.config.robot.actions_dim 40 | self.obs_dim = self.env.config.robot.policy_obs_dim 41 | self.rollout_ids = torch.arange(self.num_samples, device=self.device) + 1 42 | self.reset() 43 | self.states = None # states for all sim environments 44 | 45 | def reset(self, state=None, buffer=None): 46 | # Remark: privileged_obs is for critic learning, unused in model-based RL algo 47 | if state is None: 48 | self.env.reset_envs_idx(self.rollout_ids) 49 | else: 50 | self.set_envs_to_state(state, self.rollout_ids) 51 | 52 | self.states = {"dof_states": copy.deepcopy(self.env.dof_state.view(1 + self.num_samples, self.env.num_dof, 2)[1:]), 53 | "root_states": copy.deepcopy(self.env.robot_root_states[1:])} 54 | 55 | def set_envs_to_state(self, desired_state, ids=None): 56 | # TODO 57 | if ids is None: 58 | ids = list(range(self.env.num_envs)) 59 | root_states = {} 60 | for key in ["dof_states", "root_states"]: 61 | root_states[key] = desired_state[key][1:] 62 | 63 | # Create a numpy array to hold the states for all environments 64 | self.env.reset_envs_idx(self.rollout_ids, target_states=root_states) 65 | 66 | def step(self, actions): 67 | """ 68 | parameters: 69 | actions: (n_samples, action_dim) 70 | outputs: 71 | obs: (n_samples, obs_dim) 72 | rewards: (n_samples,) 73 | dones: (n_samples,) 74 | """ 75 | actions = torch.cat([torch.zeros_like(actions[[0]], device=self.device), actions], dim=0) # add a zero action for the first env 76 | obs, rewards, dones, infos = self.env.step(actions) # returns all envs' info (self.num_samples + 1) 77 | self.states = {"dof_states": copy.deepcopy(self.env.dof_state.view(1 + self.num_samples, self.env.num_dof, 2)[1:]), 78 | "root_states": copy.deepcopy(self.env.robot_root_states[1:])} 79 | self.obs_buf = obs["actor_obs"] 80 | self.privileged_obs_buf = obs["critic_obs"] 81 | return obs["actor_obs"][1:], rewards[1:], (1 - dones[1:]).bool() 82 | 83 | def next(self, states, actions): 84 | raise NotImplementedError 85 | 86 | 87 | # TODO: Implement the WorldModel class 88 | # class RSSM(BaseWorldModel): 89 | # def __init__(self, env, config, device='cpu'): 90 | # super(RSSM, self).__init__(env, config, device) 91 | # self.model = instantiate(config.model) 92 | # self.model = self.model.to(self.device) 93 | # self.optimizer = torch.optim.Adam(self.model.parameters(), lr=config.lr) 94 | # self.loss_fn = torch.nn.MSELoss() 95 | # self._dynamics = None 96 | # self._reward = None 97 | # self._pi = None 98 | # self._task_emb = None 99 | # self._critic = None 100 | # self.obs, self.privileged_obs = self.reset() 101 | 102 | # def next(self, obs, action): 103 | # raise NotImplementedError 104 | 105 | 106 | class MultiSimWorldModel(BaseWorldModel): 107 | def __init__(self, 108 | config, 109 | sim_config, 110 | n_samples:Optional[int]=100, 111 | command:Optional=None, 112 | device='cpu'): 113 | super(MultiSimWorldModel, self).__init__(config, device) 114 | self.env = instantiate(sim_config, device=device) 115 | self.env.set_is_evaluating(command) 116 | self.num_samples = n_samples 117 | self.action_dim = self.env.config.robot.actions_dim 118 | self.obs_dim = self.env.config.robot.policy_obs_dim 119 | self.rollout_ids = torch.arange(self.num_samples, device=self.device) 120 | self.reset() 121 | self.states = None 122 | 123 | def reset(self, state=None, buffer=None): 124 | # Remark: privileged_obs is for critic learning, unused in model-based RL algo 125 | if state is None: 126 | self.env.reset_envs_idx(self.rollout_ids) 127 | else: 128 | self.set_envs_to_state(state, buffer, self.rollout_ids) 129 | 130 | self.states = {"dof_states": copy.deepcopy(self.env.dof_state.view(self.num_samples, self.env.num_dof, 2)), 131 | "root_states": copy.deepcopy(self.env.robot_root_states)} 132 | 133 | def set_envs_to_state(self, desired_state, desired_buf, ids=None): 134 | if ids is None: 135 | ids = list(range(self.env.num_envs)) 136 | # Create a numpy array to hold the states for all environments 137 | self.env.reset_envs_idx(self.rollout_ids, target_states=desired_state, target_buf=desired_buf) 138 | 139 | def get_env_dim(self): 140 | # TODO 141 | # get sim setups for all envs 142 | return { 143 | "dof_shape": [self.num_samples, self.env.num_dof, 2], 144 | "root_states_shape": self.env.robot_root_states.shape, 145 | "obs_dim": self.obs_dim, 146 | } 147 | 148 | def step(self, actions): 149 | """ 150 | parameters: 151 | actions: (n_samples, action_dim) 152 | outputs: 153 | obs: (n_samples, obs_dim) 154 | rewards: (n_samples,) 155 | dones: (n_samples,) 156 | """ 157 | obs, rewards, dones, infos = self.env.step(actions) # returns all envs' info (self.num_samples + 1) 158 | self.states = {"dof_states": copy.deepcopy(self.env.dof_state.view(self.num_samples, self.env.num_dof, 2)), 159 | "root_states": copy.deepcopy(self.env.robot_root_states)} 160 | #print("commands:", self.env.commands) 161 | self.obs_buf = obs["actor_obs"] 162 | self.privileged_obs_buf = obs["critic_obs"] 163 | return obs["actor_obs"], rewards, (1 - dones).bool() 164 | 165 | def next(self, states, actions): 166 | raise NotImplementedError 167 | 168 | -------------------------------------------------------------------------------- /humanoidverse/agents/ppo_locomanip.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.optim as optim 4 | 5 | from humanoidverse.agents.modules.ppo_modules import PPOActor, PPOCritic 6 | from humanoidverse.agents.modules.data_utils import RolloutStorage 7 | from humanoidverse.envs.base_task.base_task import BaseTask 8 | from humanoidverse.agents.base_algo import BaseAlgo 9 | from humanoidverse.agents.callbacks.base_callback import RL_EvalCallback 10 | from humanoidverse.utils.average_meters import TensorAverageMeterDict 11 | 12 | from torch.utils.tensorboard import SummaryWriter as TensorboardSummaryWriter 13 | import time 14 | import os 15 | import statistics 16 | from collections import deque 17 | from hydra.utils import instantiate 18 | from loguru import logger 19 | from rich.progress import track 20 | from rich.console import Console 21 | from rich.panel import Panel 22 | from rich.live import Live 23 | console = Console() 24 | 25 | ################################################################## 26 | ######## Note: This agent is ONLY for EVALUATION purposes ######## 27 | ################################################################## 28 | class PPOLocoManip(BaseAlgo): 29 | def __init__(self, 30 | env: BaseTask, 31 | config, 32 | log_dir=None, 33 | device='cpu'): 34 | 35 | self.device= device 36 | self.env = env 37 | self.config = config 38 | self.log_dir = log_dir 39 | 40 | self._init_config() 41 | 42 | self.tot_timesteps = 0 43 | self.tot_time = 0 44 | 45 | # Book keeping 46 | self.ep_infos = [] 47 | self.rewbuffer = deque(maxlen=100) 48 | self.lenbuffer = deque(maxlen=100) 49 | self.cur_reward_sum = torch.zeros(self.env.num_envs, dtype=torch.float, device=self.device) 50 | self.cur_episode_length = torch.zeros(self.env.num_envs, dtype=torch.float, device=self.device) 51 | 52 | self.eval_callbacks: list[RL_EvalCallback] = [] 53 | self.episode_env_tensors = TensorAverageMeterDict() 54 | _ = self.env.reset_all() 55 | 56 | # Actor observations for stand and loco policies 57 | self.actor_obs = ['actor_stand_obs', 'actor_loco_obs'] 58 | 59 | def _init_config(self): 60 | # Env related Config 61 | self.num_envs: int = self.env.config.num_envs 62 | self.algo_obs_dim_dict = self.env.config.robot.algo_obs_dim_dict 63 | self.num_act = self.env.config.robot.lower_body_actions_dim 64 | 65 | def setup(self): 66 | logger.info("Setting up PPO Loco Manip") 67 | self._setup_models_and_optimizer() 68 | 69 | def _setup_models_and_optimizer(self): 70 | self.actor_stand = PPOActor( 71 | obs_dim_dict=self.algo_obs_dim_dict, 72 | module_config_dict=self.config.module_dict.actor_stand, 73 | num_actions=self.num_act, 74 | init_noise_std=self.config.init_noise_std 75 | ).to(self.device) 76 | self.actor_loco = PPOActor( 77 | obs_dim_dict=self.algo_obs_dim_dict, 78 | module_config_dict=self.config.module_dict.actor_loco, 79 | num_actions=self.num_act, 80 | init_noise_std=self.config.init_noise_std 81 | ).to(self.device) 82 | self.actor = [self.actor_stand, self.actor_loco] 83 | 84 | def _eval_mode(self): 85 | self.actor[0].eval() 86 | self.actor[1].eval() 87 | 88 | def load(self, ckpt_stand_path, ckpt_loco_path): 89 | if ckpt_stand_path is not None: 90 | logger.info(f"Loading standing checkpoint from {ckpt_stand_path}") 91 | loaded_dict_stand = torch.load(ckpt_stand_path, map_location=self.device) 92 | self.actor[0].load_state_dict(loaded_dict_stand["actor_model_state_dict"]) 93 | if ckpt_loco_path is not None: 94 | logger.info(f"Loading locomotion checkpoint from {ckpt_loco_path}") 95 | loaded_dict_loco = torch.load(ckpt_loco_path, map_location=self.device) 96 | self.actor[1].load_state_dict(loaded_dict_loco["actor_model_state_dict"]) 97 | return loaded_dict_stand['infos'], loaded_dict_loco["infos"] 98 | 99 | def _process_env_step(self, rewards, dones, infos): 100 | self.actor[self.env.control_mode].reset(dones) 101 | 102 | def _actor_act_step(self, obs_dict): 103 | return self.actor[self.env.control_mode].act(obs_dict) 104 | 105 | @property 106 | def inference_model(self): 107 | return self.actor 108 | 109 | ########################################################################################## 110 | # Code for Evaluation 111 | ########################################################################################## 112 | 113 | def env_step(self, actor_state): 114 | actions_lower_body = actor_state["actions"] 115 | actions_upper_body = self.env.ref_upper_dof_pos 116 | actions = torch.cat([actions_lower_body, actions_upper_body], dim=1) 117 | obs_dict, rewards, dones, extras = self.env.step(actions) 118 | actor_state.update( 119 | {"obs": obs_dict, "rewards": rewards, "dones": dones, "extras": extras} 120 | ) 121 | return actor_state 122 | 123 | @torch.no_grad() 124 | def get_example_obs(self): 125 | obs_dict = self.env.reset_all() 126 | for obs_key in obs_dict.keys(): 127 | print(obs_key, sorted(self.env.config.obs.obs_dict[obs_key])) 128 | # move to cpu 129 | for k in obs_dict: 130 | obs_dict[k] = obs_dict[k].cpu() 131 | return obs_dict 132 | 133 | @torch.no_grad() 134 | def evaluate_loco_manip_policy(self): 135 | self._create_eval_callbacks() 136 | self._pre_evaluate_policy() 137 | actor_state = self._create_actor_state() 138 | step = 0 139 | self.eval_policy = self._get_inference_policy() 140 | obs_dict = self.env.reset_all() 141 | init_actions = torch.zeros(self.env.num_envs, self.num_act, device=self.device) 142 | actor_state.update({"obs": obs_dict, "actions": init_actions}) 143 | actor_state = self._pre_eval_env_step(actor_state) 144 | while True: 145 | actor_state["step"] = step 146 | actor_state = self._pre_eval_env_step(actor_state) 147 | actor_state = self.env_step(actor_state) 148 | actor_state = self._post_eval_env_step(actor_state) 149 | step += 1 150 | 151 | def _create_actor_state(self): 152 | return {"done_indices": [], "stop": False} 153 | 154 | def _create_eval_callbacks(self): 155 | if self.config.eval_callbacks is not None: 156 | for cb in self.config.eval_callbacks: 157 | self.eval_callbacks.append(instantiate(self.config.eval_callbacks[cb], training_loop=self)) 158 | 159 | def _pre_evaluate_policy(self, reset_env=True): 160 | self._eval_mode() 161 | self.env.set_is_evaluating() 162 | if reset_env: 163 | _ = self.env.reset_all() 164 | 165 | for c in self.eval_callbacks: 166 | c.on_pre_evaluate_policy() 167 | 168 | def _post_evaluate_policy(self): 169 | for c in self.eval_callbacks: 170 | c.on_post_evaluate_policy() 171 | 172 | def _pre_eval_env_step(self, actor_state: dict): 173 | eval_policy = self.eval_policy[self.env.control_mode] 174 | actor_obs = actor_state["obs"][self.actor_obs[self.env.control_mode]] 175 | actions = eval_policy(actor_obs) 176 | actor_state.update({"actions": actions}) 177 | for c in self.eval_callbacks: 178 | actor_state = c.on_pre_eval_env_step(actor_state) 179 | return actor_state 180 | 181 | def _post_eval_env_step(self, actor_state): 182 | for c in self.eval_callbacks: 183 | actor_state = c.on_post_eval_env_step(actor_state) 184 | return actor_state 185 | 186 | def _get_inference_policy(self, device=None): 187 | self._eval_mode() 188 | if device is not None: 189 | self.actor[0].to(device) 190 | self.actor[1].to(device) 191 | return [self.actor[0].act_inference, 192 | self.actor[1].act_inference] -------------------------------------------------------------------------------- /humanoidverse/config/algo/ppo.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | algo: 4 | _target_: humanoidverse.agents.ppo.ppo.PPO 5 | _recursive_: False 6 | config: 7 | num_learning_epochs: 5 8 | num_mini_batches: 4 9 | clip_param: 0.2 10 | gamma: 0.99 11 | lam: 0.95 12 | value_loss_coef: 1.0 13 | entropy_coef: 0.01 14 | actor_learning_rate: 1.e-3 # 5e-4 # 1.e-3 15 | critic_learning_rate: 1.e-3 # 5e-4 # 1.e-3 16 | max_grad_norm: 1.0 17 | use_clipped_value_loss: True 18 | schedule: "adaptive" 19 | desired_kl: 0.01 20 | 21 | num_steps_per_env: 24 22 | save_interval: 100 23 | 24 | load_optimizer: True 25 | 26 | init_noise_std: 0.8 27 | 28 | num_learning_iterations: 1000000 29 | init_at_random_ep_len: True 30 | eval_callbacks: null 31 | 32 | module_dict: 33 | actor: 34 | input_dim: [actor_obs] 35 | output_dim: [robot_action_dim] 36 | layer_config: 37 | type: MLP 38 | hidden_dims: [512, 256, 128] 39 | activation: ELU 40 | critic: 41 | type: MLP 42 | input_dim: [critic_obs] 43 | output_dim: [1] 44 | layer_config: 45 | type: MLP 46 | hidden_dims: [512, 256, 128] 47 | activation: ELU -------------------------------------------------------------------------------- /humanoidverse/config/base.yaml: -------------------------------------------------------------------------------- 1 | # First we define the global structures that will be used by all the configs. 2 | defaults: 3 | # - base/fabric 4 | - _self_ 5 | - base/hydra 6 | - base/structure 7 | 8 | # These are global variables that all levels of the config can access. 9 | ## Experiment setup 10 | seed: 0 11 | codebase_version: 1.0 # this is recorded to enable auto-conversion of models between different versions of the codebase 12 | headless: True 13 | num_envs: 4096 14 | 15 | ### Checkpoint logic 16 | auto_load_latest: False 17 | checkpoint: null 18 | 19 | ### Naming and dir structure 20 | project_name: TEST 21 | experiment_name: TEST 22 | 23 | base_dir: logs 24 | timestamp: ${now:%Y%m%d_%H%M%S} 25 | experiment_dir: ${base_dir}/${project_name}/${timestamp}-${experiment_name}-${log_task_name}-${robot.asset.robot_type} 26 | save_dir: ${experiment_dir}/.hydra 27 | 28 | force_flat_terrain: False 29 | 30 | use_wandb: False 31 | log_task_name: TEST 32 | 33 | ### Simulation 34 | sim_type: isaacgym 35 | env_spacing: 20 36 | output_dir: ${experiment_dir}/output 37 | 38 | eval_overrides: 39 | headless: False 40 | num_envs: 1 41 | auto_load_latest: False 42 | use_wandb: False 43 | -------------------------------------------------------------------------------- /humanoidverse/config/base/fabric.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | fabric: 4 | _target_: lightning.fabric.Fabric 5 | _convert_: all 6 | accelerator: gpu 7 | devices: ${ngpu} 8 | num_nodes: ${nodes} 9 | strategy: 10 | _target_: lightning.fabric.strategies.DDPStrategy 11 | precision: ${amp_precision} 12 | loggers: 13 | - _target_: lightning.fabric.loggers.TensorBoardLogger 14 | root_dir: ${save_dir} 15 | 16 | # These are global variables that all levels of the config can access. 17 | ## Compute setup 18 | ngpu: 1 19 | nodes: 1 20 | torch_deterministic: False 21 | amp_precision: 32-true 22 | force_flat_terrain: False 23 | 24 | eval_overrides: 25 | ngpu: 1 26 | nodes: 1 27 | 28 | fabric: 29 | loggers: null 30 | -------------------------------------------------------------------------------- /humanoidverse/config/base/hydra.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | hydra: # So hydra will put your config info in the same dir as your checkpoints 4 | run: 5 | dir: ${save_dir} 6 | sweep: 7 | dir: ${save_dir} 8 | job: 9 | chdir: False 10 | # job_logging: 11 | # disable_existing_loggers: true 12 | # hydra_logging: 13 | # disable_existing_loggers: true 14 | -------------------------------------------------------------------------------- /humanoidverse/config/base/structure.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | algo: ??? 4 | 5 | env: ??? 6 | 7 | robot: ??? 8 | 9 | terrain: ??? # This is defined in the terrain configs 10 | -------------------------------------------------------------------------------- /humanoidverse/config/base_eval.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | eval_timestamp: ${now:%Y%m%d_%H%M%S} 4 | eval_name: TEST 5 | eval_log_dir: logs_eval/${eval_name}/${eval_timestamp} 6 | hydra: 7 | run: 8 | dir: ${eval_log_dir} 9 | -------------------------------------------------------------------------------- /humanoidverse/config/domain_rand/NO_domain_rand.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | 4 | defaults: 5 | - domain_rand_base 6 | 7 | domain_rand: 8 | push_robots : False 9 | push_interval_s : [5, 10] 10 | max_push_vel_xy : 1.0 11 | 12 | randomize_friction : False 13 | # randomize_friction : False 14 | friction_range : [-0.6, 1.2] 15 | 16 | randomize_base_mass : False # replaced by randomize_link_mass 17 | added_mass_range : [-5., 10.] 18 | 19 | 20 | randomize_base_com : False 21 | base_com_range: #kg 22 | x : [-0.1, 0.1] 23 | y : [-0.1, 0.1] 24 | z : [-0.01, 0.01] 25 | 26 | randomize_link_mass : False 27 | link_mass_range : [0.7, 1.3] # *factor 28 | randomize_link_body_names : [ 29 | 'pelvis', 'left_hip_yaw_link', 'left_hip_roll_link', 'left_hip_pitch_link', 'left_knee_link', 30 | 'right_hip_yaw_link', 'right_hip_roll_link', 'right_hip_pitch_link', 'right_knee_link', 31 | ] 32 | 33 | randomize_pd_gain : False 34 | kp_range : [0.75, 1.25] 35 | kd_range : [0.75, 1.25] 36 | 37 | 38 | randomize_torque_rfi : False 39 | rfi_lim : 0.1 40 | randomize_rfi_lim : False 41 | rfi_lim_range : [0.5, 1.5] 42 | 43 | randomize_ctrl_delay : False 44 | ctrl_delay_step_range : [0, 2] # integer max real delay is 90ms 45 | 46 | randomize_motion_ref_xyz: False # head only for now 47 | motion_ref_xyz_range : [[-0.02, 0.02],[-0.02, 0.02],[-0.1, 0.1]] 48 | 49 | motion_package_loss: False 50 | package_loss_range: [1, 10] # dt = 0.02s, delay for 0.02s - 0.2s 51 | package_loss_interval_s : 2 52 | 53 | 54 | born_offset : False 55 | born_offset_curriculum: False 56 | born_offset_level_down_threshold: 50 57 | born_offset_level_up_threshold: 120 58 | level_degree: 0.00005 59 | born_distance : 0.25 60 | born_offset_range: [0.0, 1] 61 | born_offset_possibility : 1.0 62 | 63 | born_heading_curriculum: False 64 | born_heading_randomization : False 65 | born_heading_level_down_threshold: 50 66 | born_heading_level_up_threshold: 120 67 | born_heading_degree: 10 68 | born_heading_range: [0, 180] 69 | born_heading_level_degree: 0.00005 70 | -------------------------------------------------------------------------------- /humanoidverse/config/domain_rand/domain_rand_base.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | domain_rand: 4 | # push robots 5 | push_robots : True 6 | push_interval_s : [5, 10] 7 | max_push_vel_xy : 1.0 8 | 9 | # base com 10 | randomize_base_com : True 11 | base_com_range: 12 | x : [-0.1., 0.1.] 13 | y : [-0.1., 0.1.] 14 | z : [-0.1, 0.1] 15 | 16 | # link mass 17 | randomize_link_mass : True 18 | link_mass_range : [0.8, 1.2] 19 | 20 | # pd gain 21 | randomize_pd_gain : True 22 | kp_range : [0.75, 1.25] 23 | kd_range : [0.75, 1.25] 24 | 25 | # friction 26 | randomize_friction : True 27 | friction_range : [0.5, 1.25] 28 | 29 | # base mass 30 | randomize_base_mass : False 31 | 32 | # rfi 33 | randomize_torque_rfi : True 34 | rfi_lim : 0.1 35 | randomize_rfi_lim : True 36 | rfi_lim_range : [0.5, 1.5] 37 | 38 | 39 | # control delay 40 | randomize_ctrl_delay : True 41 | ctrl_delay_step_range : [0, 2] # integer max real delay is 90ms -------------------------------------------------------------------------------- /humanoidverse/config/env/base_task.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | env: 4 | _target_: humanoidverse.envs.base_task.base_task.BaseTask 5 | _recursive_: False 6 | config: 7 | experiment_name: ${experiment_name} 8 | num_envs: ${num_envs} 9 | headless: ${headless} 10 | simulator: ${simulator} 11 | save_rendering_dir: null 12 | ckpt_dir: null 13 | 14 | # Globally accessible parameters 15 | log_task_name: base_task -------------------------------------------------------------------------------- /humanoidverse/config/env/legged_base.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - base_task 5 | 6 | # Env structure 7 | env: 8 | _target_: humanoidverse.envs.legged_base_task.legged_robot_base.LeggedRobotBase 9 | _recursive_: False 10 | config: 11 | robot: ${robot} 12 | domain_rand: ${domain_rand} 13 | rewards: ${rewards} 14 | terrain: ${terrain} 15 | obs: ${obs} 16 | env_spacing: 5.0 17 | max_episode_length_s: 20 18 | 19 | normalization: 20 | clip_actions: 100.0 21 | clip_observations: 100.0 22 | 23 | # simulator: 24 | # sim: 25 | # fps: 200 # 1/dt , dt = 0.005 26 | # control_decimation: 4 # decimation 27 | # substeps: 1 28 | termination: 29 | terminate_when_close_to_dof_pos_limit: False 30 | terminate_when_close_to_dof_vel_limit: False 31 | terminate_when_close_to_torque_limit: False 32 | termination_scales: 33 | termination_close_to_dof_pos_limit : 0.98 34 | termination_close_to_dof_vel_limit : 0.98 35 | termination_close_to_torque_limit : 0.98 36 | 37 | # Globally accessible parameters 38 | log_task_name: legged_base -------------------------------------------------------------------------------- /humanoidverse/config/env/locomotion.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - legged_base 5 | 6 | # Env structure 7 | env: 8 | _target_: humanoidverse.envs.locomotion.locomotion.LeggedRobotLocomotion 9 | config: 10 | max_episode_length_s: 20 11 | locomotion_obs_scales: 12 | lin_vel: 1.0 13 | ang_vel: 1.0 14 | dof_pos: 1.0 15 | dof_vel: 1.0 16 | humanoid_commands_scale: 1.0 17 | locomotion_command_ranges: 18 | lin_vel_x: [-1.0, 1.0] 19 | lin_vel_y: [-1.0, 1.0] 20 | ang_vel_yaw: [-1.0, 1.0] 21 | heading: [-3.14, 3.14] 22 | locomotion_command_resampling_time: 10.0 23 | 24 | termination: 25 | terminate_by_contact: False # problematic in isaacgym when g1+terrain 26 | # terminate_by_lin_vel: False 27 | # terminate_by_ang_vel: False 28 | terminate_by_gravity: True 29 | terminate_by_low_height: False 30 | 31 | termination_scales: 32 | termination_min_base_height : 0.3 33 | # termination_max_base_vel : 10.0 34 | # termination_max_base_ang_vel : 5.0 35 | termination_gravity_x : 0.8 36 | termination_gravity_y : 0.8 37 | 38 | 39 | 40 | # Globally accessible parameters 41 | log_task_name: locomotion 42 | 43 | eval_overrides: 44 | env: 45 | config: 46 | max_episode_length_s: 100000 47 | -------------------------------------------------------------------------------- /humanoidverse/config/env/locomotion_genesis.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - legged_base 5 | 6 | # Env structure 7 | env: 8 | _target_: humanoidverse.envs.locomotion.locomotion.LeggedRobotLocomotion 9 | config: 10 | max_episode_length_s: 20 11 | locomotion_obs_scales: 12 | lin_vel: 1.0 13 | ang_vel: 1.0 14 | dof_pos: 1.0 15 | dof_vel: 1.0 16 | humanoid_commands_scale: 1.0 17 | locomotion_command_ranges: 18 | lin_vel_x: [-1.0, 1.0] 19 | lin_vel_y: [-1.0, 1.0] 20 | ang_vel_yaw: [-1.0, 1.0] 21 | heading: [-3.14, 3.14] 22 | locomotion_command_resampling_time: 10.0 23 | obs_history: 24 | history_len: 0 25 | 26 | termination: 27 | terminate_by_contact: True # problematic in isaacgym when g1+terrain 28 | terminate_by_lin_vel: True 29 | terminate_by_ang_vel: True 30 | terminate_by_gravity: True 31 | terminate_by_low_height: True 32 | 33 | termination_scales: 34 | termination_min_base_height : 0.3 35 | termination_max_base_vel : 10.0 36 | termination_max_base_ang_vel : 5.0 37 | termination_gravity_x : 0.8 38 | termination_gravity_y : 0.8 39 | 40 | 41 | 42 | # Globally accessible parameters 43 | log_task_name: locomotion 44 | 45 | eval_overrides: 46 | env: 47 | config: 48 | max_episode_length_s: 100000 49 | -------------------------------------------------------------------------------- /humanoidverse/config/env/motion_tracking.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - legged_base 5 | 6 | # Env structure 7 | env: 8 | _target_: humanoidverse.envs.motion_tracking.motion_tracking.LeggedRobotMotionTracking 9 | config: 10 | max_episode_length_s: 20 11 | termination: 12 | terminate_by_contact: False 13 | terminate_by_gravity: True 14 | terminate_by_low_height: False 15 | terminate_when_motion_end: True 16 | terminate_when_motion_far: False 17 | terminate_when_close_to_dof_pos_limit: False 18 | terminate_when_close_to_dof_vel_limit: False 19 | terminate_when_close_to_torque_limit: False 20 | termination_scales: 21 | termination_min_base_height : 0.2 22 | termination_gravity_x : 0.8 23 | termination_gravity_y : 0.8 24 | termination_motion_far_threshold : 1.5 25 | termination_close_to_dof_pos_limit : 0.98 26 | termination_close_to_dof_vel_limit : 0.98 27 | termination_close_to_torque_limit : 0.98 28 | termination_probality: 29 | terminate_when_close_to_dof_pos_limit: 0.25 30 | terminate_when_close_to_dof_vel_limit: 0.25 31 | terminate_when_close_to_torque_limit: 0.25 32 | termination_curriculum: 33 | terminate_when_motion_far_curriculum: False 34 | terminate_when_motion_far_initial_threshold: 1.5 35 | terminate_when_motion_far_threshold_max: 2.0 36 | terminate_when_motion_far_threshold_min: 0.25 37 | terminate_when_motion_far_curriculum_degree: 0.0000025 38 | terminate_when_motion_far_curriculum_level_down_threshold: 40 39 | terminate_when_motion_far_curriculum_level_up_threshold: 42 40 | 41 | resample_motion_when_training: True 42 | resample_time_interval_s: 2000 43 | 44 | noise_to_initial_level: 0 45 | init_noise_scale: 46 | dof_pos: 0.1 47 | dof_vel: 0.15 48 | root_pos: 0.05 49 | root_rot: 10 # degree, * 3.14 / 180 50 | root_vel: 0.01 51 | root_ang_vel: 0.01 52 | 53 | use_teleop_control: False 54 | enforce_randomize_motion_start_eval: False 55 | 56 | 57 | # Globally accessible parameters 58 | log_task_name: motion_tracking 59 | 60 | eval_overrides: 61 | env: 62 | config: 63 | max_episode_length_s: 100000 64 | -------------------------------------------------------------------------------- /humanoidverse/config/exp/base_exp.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - /algo: base_algo 5 | - /env: base_task 6 | 7 | experiment_name: TESTBaseExp -------------------------------------------------------------------------------- /humanoidverse/config/exp/legged_base.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - /algo: ppo 5 | - /env: legged_base 6 | 7 | experiment_name: TESTLeggedBase -------------------------------------------------------------------------------- /humanoidverse/config/exp/locomotion.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - /algo: ppo 5 | - /env: locomotion 6 | 7 | experiment_name: TEST_Locomotion -------------------------------------------------------------------------------- /humanoidverse/config/exp/motion_tracking.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - /algo: ppo 5 | - /env: motion_tracking 6 | 7 | experiment_name: TEST_Motion_Tracking -------------------------------------------------------------------------------- /humanoidverse/config/obs/legged_obs.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: ??? 7 | critic_obs: ??? 8 | 9 | # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 10 | obs_auxiliary: ??? 11 | 12 | obs_scales: ??? 13 | 14 | noise_scales: ??? 15 | 16 | obs_dims: ??? 17 | # Will store values after preprocessing, don't put anything here 18 | post_compute_config: {} 19 | -------------------------------------------------------------------------------- /humanoidverse/config/obs/loco/leggedloco_obs_history_wolinvel.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: [ 7 | base_ang_vel, 8 | projected_gravity, 9 | command_lin_vel, 10 | command_ang_vel, 11 | dof_pos, 12 | dof_vel, 13 | actions, 14 | short_history 15 | ] 16 | 17 | critic_obs: [ 18 | base_lin_vel, 19 | base_ang_vel, 20 | projected_gravity, 21 | command_lin_vel, 22 | command_ang_vel, 23 | dof_pos, 24 | dof_vel, 25 | actions, 26 | short_history 27 | ] 28 | 29 | # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 30 | obs_auxiliary: 31 | short_history: { 32 | base_ang_vel: 5, 33 | projected_gravity: 5, 34 | dof_pos: 5, 35 | dof_vel: 5, 36 | actions: 5, 37 | command_lin_vel: 5, 38 | command_ang_vel: 5, 39 | } 40 | 41 | obs_scales: { 42 | base_lin_vel: 2.0, 43 | base_ang_vel: 0.25, 44 | projected_gravity: 1.0, 45 | command_lin_vel: 1.0, 46 | command_ang_vel: 1.0, 47 | dof_pos: 1.0, 48 | dof_vel: 0.05, 49 | history: 1.0, 50 | actions: 1.0, 51 | } 52 | 53 | noise_scales: { 54 | base_lin_vel: 0.0, 55 | base_ang_vel: 0.0, 56 | projected_gravity: 0.0, 57 | command_lin_vel: 0.0, 58 | command_ang_vel: 0.0, 59 | dof_pos: 0.0, 60 | dof_vel: 0.0, 61 | actions: 0.0, 62 | history: 0.0, 63 | } 64 | 65 | # obs_dims should use list instead of dict 66 | # will be converted to dict in `pre_process_config` 67 | obs_dims: 68 | - base_lin_vel: 3 69 | - base_ang_vel: 3 70 | - projected_gravity: 3 71 | - command_lin_vel: 2 72 | - command_ang_vel: 1 73 | - dof_pos: ${robot.dof_obs_size} 74 | - dof_vel: ${robot.dof_obs_size} 75 | - actions: ${robot.dof_obs_size} 76 | -------------------------------------------------------------------------------- /humanoidverse/config/obs/loco/leggedloco_obs_singlestep_withlinvel.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: [ 7 | base_lin_vel, 8 | base_ang_vel, 9 | projected_gravity, 10 | command_lin_vel, 11 | command_ang_vel, 12 | dof_pos, 13 | dof_vel, 14 | actions, 15 | # history, 16 | ] 17 | 18 | critic_obs: [ 19 | base_lin_vel, 20 | base_ang_vel, 21 | projected_gravity, 22 | command_lin_vel, 23 | command_ang_vel, 24 | dof_pos, 25 | dof_vel, 26 | actions, 27 | # history 28 | ] 29 | 30 | # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 31 | obs_auxiliary: 32 | history_long: { 33 | dof_pos: 20, 34 | dof_vel: 2, 35 | actions: 15, 36 | } 37 | 38 | history_short: { 39 | dof_pos: 3, 40 | dof_vel: 2, 41 | actions: 1, 42 | } 43 | 44 | 45 | obs_scales: { 46 | base_lin_vel: 2.0, 47 | base_ang_vel: 0.25, 48 | projected_gravity: 1.0, 49 | command_lin_vel: 1.0, 50 | command_ang_vel: 1.0, 51 | dof_pos: 1.0, 52 | dof_vel: 0.05, 53 | history: 1.0, 54 | actions: 1.0, 55 | } 56 | 57 | noise_scales: { 58 | base_lin_vel: 0.0, 59 | base_ang_vel: 0.0, 60 | projected_gravity: 0.0, 61 | command_lin_vel: 0.0, 62 | command_ang_vel: 0.0, 63 | dof_pos: 0.0, 64 | dof_vel: 0.0, 65 | actions: 0.0, 66 | history: 0.0, 67 | } 68 | 69 | add_noise_currculum: False 70 | noise_initial_value: 0.05 71 | noise_value_max: 1.00 72 | noise_value_min: 0.00001 73 | soft_dof_pos_curriculum_degree: 0.00001 74 | soft_dof_pos_curriculum_level_down_threshold: 100 75 | soft_dof_pos_curriculum_level_up_threshold: 900 76 | 77 | # obs_dims should use list instead of dict 78 | # will be converted to dict in `pre_process_config` 79 | obs_dims: 80 | - base_lin_vel: 3 81 | - base_ang_vel: 3 82 | - projected_gravity: 3 83 | - command_lin_vel: 2 84 | - command_ang_vel: 1 85 | - dof_pos: ${robot.dof_obs_size} 86 | - dof_vel: ${robot.dof_obs_size} 87 | - actions: ${robot.dof_obs_size} 88 | -------------------------------------------------------------------------------- /humanoidverse/config/obs/loco/leggedloco_obs_singlestep_wolinvel.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: [ 7 | # base_lin_vel, 8 | base_ang_vel, 9 | projected_gravity, 10 | command_lin_vel, 11 | command_ang_vel, 12 | dof_pos, 13 | dof_vel, 14 | actions, 15 | # history, 16 | ] 17 | 18 | critic_obs: [ 19 | # base_lin_vel, 20 | base_ang_vel, 21 | projected_gravity, 22 | command_lin_vel, 23 | command_ang_vel, 24 | dof_pos, 25 | dof_vel, 26 | actions, 27 | # history, 28 | ] 29 | 30 | obs_auxiliary: # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 31 | history: { 32 | base_ang_vel: 20, 33 | projected_gravity: 20, 34 | dof_pos: 20, 35 | dof_vel: 20, 36 | actions: 20, 37 | command_lin_vel: 20, 38 | command_ang_vel: 20, 39 | } 40 | 41 | obs_scales: { 42 | base_lin_vel: 2.0, 43 | base_ang_vel: 0.25, 44 | projected_gravity: 1.0, 45 | command_lin_vel: 1.0, 46 | command_ang_vel: 1.0, 47 | dof_pos: 1.0, 48 | dof_vel: 0.05, 49 | history: 1.0, 50 | actions: 1.0, 51 | } 52 | 53 | noise_scales: { 54 | base_lin_vel: 0.0, 55 | base_ang_vel: 0.0, 56 | projected_gravity: 0.0, 57 | command_lin_vel: 0.0, 58 | command_ang_vel: 0.0, 59 | dof_pos: 0.0, 60 | dof_vel: 0.0, 61 | actions: 0.0, 62 | history: 0.0, 63 | } 64 | 65 | # obs_dims should use list instead of dict 66 | # will be converted to dict in `pre_process_config` 67 | obs_dims: 68 | - base_lin_vel: 3 69 | - base_ang_vel: 3 70 | - projected_gravity: 3 71 | - command_lin_vel: 2 72 | - command_ang_vel: 1 73 | - dof_pos: ${robot.dof_obs_size} 74 | - dof_vel: ${robot.dof_obs_size} 75 | - actions: ${robot.dof_obs_size} -------------------------------------------------------------------------------- /humanoidverse/config/obs/loco/leggedloco_obs_singlestep_wolinvel_a2c.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: [ 7 | base_ang_vel, 8 | projected_gravity, 9 | command_lin_vel, 10 | command_ang_vel, 11 | dof_pos, 12 | dof_vel, 13 | actions, 14 | ] 15 | 16 | critic_obs: [ 17 | base_lin_vel, 18 | base_ang_vel, 19 | projected_gravity, 20 | command_lin_vel, 21 | command_ang_vel, 22 | dof_pos, 23 | dof_vel, 24 | actions, 25 | ] 26 | 27 | 28 | obs_auxiliary: # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 29 | history: { 30 | dof_pos: 5, 31 | dof_vel: 5, 32 | actions: 5, 33 | } 34 | 35 | obs_scales: { 36 | base_lin_vel: 2.0, 37 | base_ang_vel: 0.25, 38 | projected_gravity: 1.0, 39 | command_lin_vel: 1.0, 40 | command_ang_vel: 1.0, 41 | dof_pos: 1.0, 42 | dof_vel: 0.05, 43 | history: 1.0, 44 | actions: 1.0, 45 | } 46 | 47 | noise_scales: { 48 | base_lin_vel: 0.0, 49 | base_ang_vel: 0.0, 50 | projected_gravity: 0.0, 51 | command_lin_vel: 0.0, 52 | command_ang_vel: 0.0, 53 | dof_pos: 0.0, 54 | dof_vel: 0.0, 55 | actions: 0.0, 56 | history: 0.0, 57 | } 58 | 59 | # obs_dims should use list instead of dict 60 | # will be converted to dict in `pre_process_config` 61 | obs_dims: 62 | - base_lin_vel: 3 63 | - base_ang_vel: 3 64 | - projected_gravity: 3 65 | - command_lin_vel: 2 66 | - command_ang_vel: 1 67 | - dof_pos: ${robot.dof_obs_size} 68 | - dof_vel: ${robot.dof_obs_size} 69 | - actions: ${robot.dof_obs_size} 70 | -------------------------------------------------------------------------------- /humanoidverse/config/obs/motion_tracking/deepmimic.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: [ 7 | base_lin_vel, 8 | base_ang_vel, 9 | projected_gravity, 10 | dof_pos, 11 | dof_vel, 12 | actions, 13 | ref_motion_phase 14 | # dif_local_rigid_body_pos, 15 | # local_ref_rigid_body_pos, 16 | # history, 17 | ] 18 | 19 | critic_obs: [ 20 | base_lin_vel, 21 | base_ang_vel, 22 | projected_gravity, 23 | dof_pos, 24 | dof_vel, 25 | actions, 26 | ref_motion_phase 27 | # dif_local_rigid_body_pos, 28 | # local_ref_rigid_body_pos, 29 | ] 30 | 31 | obs_auxiliary: # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 32 | history: { 33 | dof_pos: 5, 34 | dof_vel: 5, 35 | actions: 5, 36 | } 37 | 38 | obs_scales: { 39 | base_lin_vel: 2.0, 40 | base_ang_vel: 0.25, 41 | projected_gravity: 1.0, 42 | dof_pos: 1.0, 43 | dof_vel: 0.05, 44 | history: 1.0, 45 | actions: 1.0, 46 | dif_local_rigid_body_pos: 1.0, 47 | local_ref_rigid_body_pos: 1.0, 48 | ref_motion_phase: 1.0, 49 | } 50 | 51 | noise_scales: { 52 | base_lin_vel: 0.0, 53 | base_ang_vel: 0.0, 54 | projected_gravity: 0.0, 55 | dof_pos: 0.0, 56 | dof_vel: 0.0, 57 | actions: 0.0, 58 | history: 0.0, 59 | dif_local_rigid_body_pos: 0.0, 60 | local_ref_rigid_body_pos: 0.0, 61 | ref_motion_phase: 0.0, 62 | } 63 | 64 | obs_dims: 65 | - base_lin_vel: 3 66 | - base_ang_vel: 3 67 | - projected_gravity: 3 68 | - dof_pos: ${robot.dof_obs_size} 69 | - dof_vel: ${robot.dof_obs_size} 70 | - actions: ${robot.dof_obs_size} 71 | - dif_local_rigid_body_pos: ${eval:'3 * ${robot.num_bodies} + 9'} # hardcoded for 3 extended body 72 | - local_ref_rigid_body_pos: ${eval:'3 * ${robot.num_bodies} + 9'} 73 | - ref_motion_phase: 1 74 | 75 | post_compute_config: {} # Will store values after preprocessing, don't put anything here -------------------------------------------------------------------------------- /humanoidverse/config/obs/motion_tracking/deepmimic_a2c.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: [ 7 | base_lin_vel, 8 | base_ang_vel, 9 | projected_gravity, 10 | dof_pos, 11 | dof_vel, 12 | actions, 13 | ref_motion_phase 14 | # dif_local_rigid_body_pos, 15 | # local_ref_rigid_body_pos, 16 | # history, 17 | ] 18 | 19 | critic_obs: [ 20 | base_lin_vel, 21 | base_ang_vel, 22 | projected_gravity, 23 | dof_pos, 24 | dof_vel, 25 | actions, 26 | ref_motion_phase, 27 | dif_local_rigid_body_pos, 28 | local_ref_rigid_body_pos, 29 | ] 30 | 31 | obs_auxiliary: # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 32 | history: { 33 | dof_pos: 5, 34 | dof_vel: 5, 35 | actions: 5, 36 | } 37 | 38 | obs_scales: { 39 | base_lin_vel: 2.0, 40 | base_ang_vel: 0.25, 41 | projected_gravity: 1.0, 42 | dof_pos: 1.0, 43 | dof_vel: 0.05, 44 | history: 1.0, 45 | actions: 1.0, 46 | dif_local_rigid_body_pos: 1.0, 47 | local_ref_rigid_body_pos: 1.0, 48 | ref_motion_phase: 1.0, 49 | } 50 | 51 | noise_scales: { 52 | base_lin_vel: 0.0, 53 | base_ang_vel: 0.0, 54 | projected_gravity: 0.0, 55 | dof_pos: 0.0, 56 | dof_vel: 0.0, 57 | actions: 0.0, 58 | history: 0.0, 59 | dif_local_rigid_body_pos: 0.0, 60 | local_ref_rigid_body_pos: 0.0, 61 | ref_motion_phase: 0.0, 62 | } 63 | 64 | obs_dims: 65 | - base_lin_vel: 3 66 | - base_ang_vel: 3 67 | - projected_gravity: 3 68 | - dof_pos: ${robot.dof_obs_size} 69 | - dof_vel: ${robot.dof_obs_size} 70 | - actions: ${robot.dof_obs_size} 71 | - dif_local_rigid_body_pos: ${eval:'3 * ${robot.num_bodies} + 9'} # hardcoded for 3 extended body 72 | - local_ref_rigid_body_pos: ${eval:'3 * ${robot.num_bodies} + 9'} 73 | - ref_motion_phase: 1 74 | 75 | post_compute_config: {} # Will store values after preprocessing, don't put anything here -------------------------------------------------------------------------------- /humanoidverse/config/obs/motion_tracking/deepmimic_a2c_nolinvel_LARGEnoise_history.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: [ 7 | base_ang_vel, 8 | projected_gravity, 9 | dof_pos, 10 | dof_vel, 11 | actions, 12 | ref_motion_phase, 13 | # dif_local_rigid_body_pos, 14 | # local_ref_rigid_body_pos, 15 | # history, 16 | history_actor 17 | ] 18 | 19 | critic_obs: [ 20 | base_lin_vel, 21 | base_ang_vel, 22 | projected_gravity, 23 | dof_pos, 24 | dof_vel, 25 | actions, 26 | ref_motion_phase, 27 | dif_local_rigid_body_pos, 28 | local_ref_rigid_body_pos, 29 | history_critic 30 | ] 31 | 32 | obs_auxiliary: # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 33 | 34 | history_actor: { 35 | base_ang_vel: 4, 36 | projected_gravity: 4, 37 | dof_pos: 4, 38 | dof_vel: 4, 39 | actions: 4, 40 | ref_motion_phase: 4 41 | } 42 | 43 | history_critic: { 44 | base_lin_vel: 4, 45 | base_ang_vel: 4, 46 | projected_gravity: 4, 47 | dof_pos: 4, 48 | dof_vel: 4, 49 | actions: 4, 50 | ref_motion_phase: 4 51 | } 52 | 53 | obs_scales: { 54 | base_lin_vel: 2.0, 55 | base_ang_vel: 0.25, 56 | projected_gravity: 1.0, 57 | dof_pos: 1.0, 58 | dof_vel: 0.05, 59 | actions: 1.0, 60 | dif_local_rigid_body_pos: 1.0, 61 | local_ref_rigid_body_pos: 1.0, 62 | ref_motion_phase: 1.0, 63 | history_actor: 1.0, 64 | history_critic: 1.0, 65 | } 66 | 67 | noise_scales: { 68 | base_lin_vel: 0.0, 69 | base_ang_vel: 0.3, 70 | projected_gravity: 0.2, 71 | dof_pos: 0.01, 72 | dof_vel: 1.0, 73 | actions: 0.0, 74 | dif_local_rigid_body_pos: 0.0, 75 | local_ref_rigid_body_pos: 0.0, 76 | ref_motion_phase: 0.0, 77 | history_actor: 0.0, 78 | history_critic: 0.0, 79 | } 80 | 81 | add_noise_currculum: False 82 | noise_initial_value: 0.05 83 | noise_value_max: 1.0 84 | noise_value_min: 0.00001 85 | soft_dof_pos_curriculum_degree: 0.00001 86 | soft_dof_pos_curriculum_level_down_threshold: 40 87 | soft_dof_pos_curriculum_level_up_threshold: 42 88 | 89 | obs_dims: 90 | - base_lin_vel: 3 91 | - base_ang_vel: 3 92 | - projected_gravity: 3 93 | - dof_pos: ${robot.dof_obs_size} 94 | - dof_vel: ${robot.dof_obs_size} 95 | - actions: ${robot.dof_obs_size} 96 | - dif_local_rigid_body_pos: ${eval:'3 * ${robot.num_bodies} + 9'} # hardcoded for 3 extended body 97 | - local_ref_rigid_body_pos: ${eval:'3 * ${robot.num_bodies} + 9'} 98 | - ref_motion_phase: 1 99 | 100 | post_compute_config: {} # Will store values after preprocessing, don't put anything here -------------------------------------------------------------------------------- /humanoidverse/config/obs/motion_tracking/motion_tracking.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Be careful when using _raw, history 4 | obs: 5 | obs_dict: 6 | actor_obs: [ 7 | base_lin_vel, 8 | base_ang_vel, 9 | projected_gravity, 10 | dof_pos, 11 | dof_vel, 12 | actions, 13 | dif_local_rigid_body_pos, 14 | local_ref_rigid_body_pos, 15 | # history, 16 | ] 17 | 18 | critic_obs: [ 19 | base_lin_vel, 20 | base_ang_vel, 21 | projected_gravity, 22 | dof_pos, 23 | dof_vel, 24 | actions, 25 | dif_local_rigid_body_pos, 26 | local_ref_rigid_body_pos, 27 | ] 28 | 29 | obs_auxiliary: # define those coumpounds in obs_dict, for example, you can define different long/short history with different length 30 | history: { 31 | dof_pos: 5, 32 | dof_vel: 5, 33 | actions: 5, 34 | } 35 | 36 | obs_scales: { 37 | base_lin_vel: 2.0, 38 | base_ang_vel: 0.25, 39 | projected_gravity: 1.0, 40 | dof_pos: 1.0, 41 | dof_vel: 0.05, 42 | history: 1.0, 43 | actions: 1.0, 44 | dif_local_rigid_body_pos: 1.0, 45 | local_ref_rigid_body_pos: 1.0, 46 | } 47 | 48 | noise_scales: { 49 | base_lin_vel: 0.0, 50 | base_ang_vel: 0.0, 51 | projected_gravity: 0.0, 52 | dof_pos: 0.0, 53 | dof_vel: 0.0, 54 | actions: 0.0, 55 | history: 0.0, 56 | dif_local_rigid_body_pos: 0.0, 57 | local_ref_rigid_body_pos: 0.0, 58 | } 59 | 60 | 61 | obs_dims: 62 | - base_lin_vel: 3 63 | - base_ang_vel: 3 64 | - projected_gravity: 3 65 | - dof_pos: ${robot.dof_obs_size} 66 | - dof_vel: ${robot.dof_obs_size} 67 | - actions: ${robot.dof_obs_size} 68 | - dif_local_rigid_body_pos: ${eval:'3 * ${robot.num_bodies} + 3 * ${robot.motion.nums_extend_bodies}'} 69 | - local_ref_rigid_body_pos: ${eval:'3 * ${robot.num_bodies} + 3 * ${robot.motion.nums_extend_bodies}'} 70 | - vr_3point_pos: 9 71 | 72 | 73 | post_compute_config: {} # Will store values after preprocessing, don't put anything here -------------------------------------------------------------------------------- /humanoidverse/config/opt/eval_analysis_plot_locomotion.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | algo: 4 | config: 5 | eval_callbacks: 6 | analysis_plot_cb: 7 | _target_: humanoidverse.agents.callbacks.analysis_plot_locomotion.AnalysisPlotLocomotion 8 | config: 9 | sim_dt: 0.02 10 | log_single_robot: False 11 | plot_update_interval: 100 -------------------------------------------------------------------------------- /humanoidverse/config/opt/eval_analysis_plot_motion_tracking.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | algo: 4 | config: 5 | eval_callbacks: 6 | analysis_plot_cb: 7 | _target_: humanoidverse.agents.callbacks.analysis_plot_motion_tracking.AnalysisPlotMotionTracking 8 | config: 9 | sim_dt: 0.02 10 | log_single_robot: False 11 | plot_update_interval: 100 12 | compute_metrics: False -------------------------------------------------------------------------------- /humanoidverse/config/opt/record.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | env: 4 | config: 5 | save_motion: False 6 | eval_timestamp: ${eval_timestamp} 7 | save_note: null 8 | ckpt_dir: null 9 | save_total_steps: 10000 -------------------------------------------------------------------------------- /humanoidverse/config/opt/wandb.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | use_wandb: True 4 | 5 | wandb: 6 | wandb_project: null 7 | wandb_tags: 'online' # 'online' or 'offline' or 'disabled' 8 | wandb_group: null 9 | wandb_id: null 10 | wandb_entity: agileh2o 11 | wandb_dir: ${experiment_dir}/.wandb -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_g1_locomotion.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Yuanhang 8 | set_reward_date: 20250206 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | penalty_lin_vel_z: -2.0 14 | penalty_ang_vel_xy: -1.0 15 | penalty_orientation: -1.0 16 | penalty_torques: -0.00001 17 | # penalty_dof_vel: -0.0001 18 | penalty_dof_acc: -3.5e-8 19 | penalty_action_rate: -0.01 20 | # penalty_feet_contact_forces: -0.01 21 | # penalty_stumble: -10.0 22 | penalty_slippage: -1.0 23 | penalty_feet_ori: -2.0 24 | limits_dof_pos: -10.0 25 | # limits_dof_vel: -5.0 26 | # limits_torque: -0.1 27 | feet_air_time: 1.0 28 | base_height: -10.0 29 | penalty_feet_height: -2.5 30 | # termination: -500.0 31 | # penalty_in_the_air: -100.0 32 | # feet_max_height_for_this_air: -100.0 33 | upperbody_joint_angle_freeze: -0.2 34 | feet_heading_alignment: -0.3 35 | penalty_close_feet_xy: -10. 36 | penalty_ang_vel_xy_torso: -1.0 37 | penalty_hip_pos: -1.0 38 | 39 | 40 | reward_tracking_sigma: 41 | lin_vel: 0.25 42 | ang_vel: 0.25 43 | reward_limit: 44 | soft_dof_pos_limit: 0.9 45 | soft_dof_vel_limit: 0.9 46 | soft_torque_limit: 0.825 47 | 48 | reward_limits_curriculum: 49 | soft_dof_pos_curriculum: False 50 | soft_dof_pos_initial_limit: 1.15 51 | soft_dof_pos_max_limit: 1.15 52 | soft_dof_pos_min_limit: 0.95 53 | soft_dof_pos_curriculum_degree: 0.00000025 54 | soft_dof_pos_curriculum_level_down_threshold: 40 55 | soft_dof_pos_curriculum_level_up_threshold: 42 56 | 57 | soft_dof_vel_curriculum: False 58 | soft_dof_vel_initial_limit: 1.15 59 | soft_dof_vel_max_limit: 1.25 60 | soft_dof_vel_min_limit: 0.95 61 | soft_dof_vel_curriculum_degree: 0.00000025 62 | soft_dof_vel_curriculum_level_down_threshold: 40 63 | soft_dof_vel_curriculum_level_up_threshold: 42 64 | 65 | soft_torque_curriculum: False 66 | soft_torque_initial_limit: 1.15 67 | soft_torque_max_limit: 1.25 68 | soft_torque_min_limit: 0.85 69 | soft_torque_curriculum_degree: 0.00000025 70 | soft_torque_curriculum_level_down_threshold: 40 71 | soft_torque_curriculum_level_up_threshold: 42 72 | 73 | feet_height_target: 0.12 74 | locomotion_max_contact_force: 200.0 75 | desired_feet_max_height_for_this_air: 0.12 76 | desired_base_height: 0.78 77 | close_feet_threshold: 0.15 78 | 79 | reward_penalty_curriculum: False 80 | reward_initial_penalty_scale : 1.0 81 | reward_min_penalty_scale: 0.0 82 | reward_max_penalty_scale: 1.0 83 | reward_penalty_level_down_threshold: 400 84 | reward_penalty_level_up_threshold: 700 85 | reward_penalty_degree: 0.00001 86 | num_compute_average_epl: 10000 87 | 88 | reward_penalty_reward_names : [ 89 | "penalty_lin_vel_z", 90 | "penalty_ang_vel_xy", 91 | "penalty_orientation", 92 | "penalty_torques", 93 | "penalty_dof_acc", 94 | "penalty_dof_vel", 95 | "penalty_action_rate", 96 | "penalty_feet_contact_forces", 97 | "penalty_stumble", 98 | "penalty_slippage", 99 | "penalty_feet_ori", 100 | "penalty_in_the_air", 101 | "limits_dof_pos", 102 | "limits_dof_vel", 103 | "limits_torque", 104 | "termination", 105 | "feet_air_time", 106 | "feet_max_height_for_this_air", 107 | "penalty_feet_height", 108 | "upperbody_joint_angle_freeze", 109 | "penalty_close_feet_xy", 110 | "penalty_ang_vel_xy_torso", 111 | "penalty_hip_pos"] 112 | 113 | -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_g1_unitree.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Tairan 8 | set_reward_date: 20241024 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | penalty_lin_vel_z: -2.0 14 | penalty_ang_vel_xy: -0.05 15 | penalty_orientation: -1.0 16 | penalty_torques: -0.00001 17 | # penalty_dof_vel: -0.0001 18 | penalty_dof_acc: -2.5e-8 19 | penalty_action_rate: -0.01 20 | # penalty_feet_contact_forces: -0.01 21 | # penalty_stumble: -10.0 22 | penalty_slippage: 0. # -1.0 23 | # penalty_feet_ori: -10.0 24 | limits_dof_pos: -5.0 25 | # limits_dof_vel: -5.0 26 | # limits_torque: -0.1 27 | feet_air_time: 1.0 28 | base_height: -10.0 29 | # termination: -500.0 30 | # penalty_in_the_air: -100.0 31 | penalty_feet_height: 0. # -100.0 32 | feet_heading_alignment: 0. # -0.0 33 | 34 | 35 | reward_tracking_sigma: 36 | lin_vel: 0.25 37 | ang_vel: 0.25 38 | reward_limit: 39 | soft_dof_pos_limit: 0.9 40 | soft_dof_vel_limit: 1.0 41 | soft_torque_limit: 1.0 42 | 43 | locomotion_max_contact_force: 200.0 44 | desired_feet_max_height_for_this_air: 0.15 45 | feet_height_target: 0.20 46 | desired_base_height: 0.728 47 | 48 | reward_penalty_curriculum: False 49 | reward_initial_penalty_scale : 1.0 50 | reward_min_penalty_scale: 0.0 51 | reward_max_penalty_scale: 1.0 52 | reward_penalty_level_down_threshold: 400 53 | reward_penalty_level_up_threshold: 900 54 | reward_penalty_degree: 0.00001 55 | num_compute_average_epl: 10000 56 | 57 | reward_penalty_reward_names : [ 58 | "penalty_torques", 59 | "penalty_dof_acc", 60 | "penalty_dof_vel", 61 | "penalty_action_rate", 62 | "penalty_feet_contact_forces", 63 | "penalty_stumble", 64 | "penalty_slippage", 65 | "penalty_feet_ori", 66 | "penalty_in_the_air", 67 | "penalty_lin_vel_z", 68 | "penalty_ang_vel_xy", 69 | "penalty_orientation", 70 | "base_height", 71 | "penalty_feet_height", 72 | "limits_dof_pos", 73 | "limits_dof_vel", 74 | "limits_torque", 75 | "termination", 76 | "feet_air_time", 77 | "feet_max_height_for_this_air"] 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_go2_locomotion.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Unitree_RL GYM EXACT REWARD 8 | set_reward_date: 20241008 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | penalty_lin_vel_z: -2.0 14 | penalty_ang_vel_xy: -0.05 15 | penalty_orientation: -0.0 16 | penalty_torques: -0.0002 17 | # penalty_dof_vel: -0.0001 18 | penalty_dof_acc: -2.5e-7 19 | penalty_action_rate: -0.01 20 | # penalty_feet_contact_forces: -0.01 21 | # penalty_stumble: -10.0 22 | penalty_slippage: -0.0 23 | penalty_feet_ori: -0.0 24 | limits_dof_pos: -10.0 25 | # limits_dof_vel: -5.0 26 | # limits_torque: -0.1 27 | feet_air_time: 1.0 28 | base_height: 0.0 29 | penalty_feet_height: -0. 30 | # termination: -500.0 31 | # penalty_in_the_air: -100.0 32 | feet_max_height_for_this_air: -100.0 33 | upperbody_joint_angle_freeze: -0.0 34 | 35 | 36 | 37 | reward_tracking_sigma: 38 | lin_vel: 0.25 39 | ang_vel: 0.25 40 | reward_limit: 41 | soft_dof_pos_limit: 0.9 42 | soft_dof_vel_limit: 0.9 43 | soft_torque_limit: 0.9 44 | 45 | feet_height_target: 0.12 46 | locomotion_max_contact_force: 200.0 47 | desired_feet_max_height_for_this_air: 0.12 48 | desired_base_height: 0.25 49 | 50 | reward_penalty_curriculum: False 51 | reward_initial_penalty_scale : 1.0 52 | reward_min_penalty_scale: 0.0 53 | reward_max_penalty_scale: 1.0 54 | reward_penalty_level_down_threshold: 400 55 | reward_penalty_level_up_threshold: 700 56 | reward_penalty_degree: 0.00001 57 | num_compute_average_epl: 10000 58 | 59 | reward_penalty_reward_names : [ 60 | "penalty_torques", 61 | "penalty_dof_acc", 62 | "penalty_dof_vel", 63 | "penalty_action_rate", 64 | "penalty_feet_contact_forces", 65 | "penalty_stumble", 66 | "penalty_slippage", 67 | "penalty_feet_ori", 68 | "penalty_in_the_air", 69 | "limits_dof_pos", 70 | "limits_dof_vel", 71 | "limits_torque", 72 | "termination", 73 | "feet_air_time", 74 | "feet_max_height_for_this_air"] 75 | 76 | -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_go2_locomotion_sysid.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Unitree_RL GYM EXACT REWARD 8 | set_reward_date: 20241008 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | penalty_lin_vel_z: -2.0 14 | penalty_ang_vel_xy: -0.05 15 | penalty_orientation: -0.0 16 | penalty_torques: -0.0002 17 | # penalty_dof_vel: -0.0001 18 | penalty_dof_acc: -2.5e-7 19 | penalty_action_rate: -0.01 20 | # penalty_feet_contact_forces: -0.01 21 | # penalty_stumble: -10.0 22 | penalty_slippage: -0.0 23 | penalty_feet_ori: -0.0 24 | limits_dof_pos: -10.0 25 | # limits_dof_vel: -5.0 26 | # limits_torque: -0.1 27 | custom_feet_air_time: 1.0 28 | feet_no_contact: 10.0 29 | base_height: 0.0 30 | penalty_feet_height: -0. 31 | # termination: -500.0 32 | # penalty_in_the_air: -100.0 33 | feet_max_height_for_this_air: -100.0 34 | upperbody_joint_angle_freeze: -0.0 35 | 36 | 37 | 38 | reward_tracking_sigma: 39 | lin_vel: 0.25 40 | ang_vel: 0.25 41 | reward_limit: 42 | soft_dof_pos_limit: 0.9 43 | soft_dof_vel_limit: 0.9 44 | soft_torque_limit: 0.9 45 | 46 | feet_height_target: 0.12 47 | locomotion_max_contact_force: 200.0 48 | desired_feet_max_height_for_this_air: 0.12 49 | desired_base_height: 0.25 50 | 51 | reward_penalty_curriculum: False 52 | reward_initial_penalty_scale : 1.0 53 | reward_min_penalty_scale: 0.0 54 | reward_max_penalty_scale: 1.0 55 | reward_penalty_level_down_threshold: 400 56 | reward_penalty_level_up_threshold: 700 57 | reward_penalty_degree: 0.00001 58 | num_compute_average_epl: 10000 59 | 60 | reward_penalty_reward_names : [ 61 | "penalty_torques", 62 | "penalty_dof_acc", 63 | "penalty_dof_vel", 64 | "penalty_action_rate", 65 | "penalty_feet_contact_forces", 66 | "penalty_stumble", 67 | "penalty_slippage", 68 | "penalty_feet_ori", 69 | "penalty_in_the_air", 70 | "limits_dof_pos", 71 | "limits_dof_vel", 72 | "limits_torque", 73 | "termination", 74 | "custom_feet_air_time", 75 | "feet_no_contact", 76 | "feet_max_height_for_this_air"] 77 | 78 | -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_h1_2_locomotion.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Jiawei 8 | set_reward_date: 20241204 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | penalty_lin_vel_z: -2.0 14 | penalty_ang_vel_xy: -0.05 15 | penalty_orientation: -1.0 16 | penalty_torques: -0.00001 17 | # penalty_dof_vel: -0.0001 18 | penalty_dof_acc: -2.5e-8 19 | penalty_action_rate: -0.01 20 | # penalty_feet_contact_forces: -0.01 21 | # penalty_stumble: -10.0 22 | # penalty_slippage: -1.0 23 | # penalty_feet_ori: -2.0 24 | limits_dof_pos: -10.0 25 | # limits_dof_vel: -5.0 26 | # limits_torque: -0.1 27 | feet_air_time: 1.0 28 | base_height: -100.0 29 | penalty_feet_height: -5. 30 | 31 | # termination: -500.0 32 | # penalty_in_the_air: -100.0 33 | # feet_max_height_for_this_air: -100.0 34 | upperbody_joint_angle_freeze: -0.2 35 | # feet_heading_alignment: -0.2 36 | penalty_close_feet_xy: -5. #-10. 37 | # penalty_ang_vel_xy_torso: -1.0 38 | 39 | 40 | 41 | reward_tracking_sigma: 42 | lin_vel: 0.25 43 | ang_vel: 0.25 44 | reward_limit: 45 | soft_dof_pos_limit: 0.9 46 | soft_dof_vel_limit: 0.9 47 | soft_torque_limit: 0.9 48 | 49 | feet_height_target: 0.2 50 | locomotion_max_contact_force: 200.0 51 | desired_feet_max_height_for_this_air: 0.2 52 | desired_base_height: 0.98 53 | close_feet_threshold: 0.3 54 | 55 | reward_penalty_curriculum: False 56 | reward_initial_penalty_scale : 1.0 57 | reward_min_penalty_scale: 0.0 58 | reward_max_penalty_scale: 1.0 59 | reward_penalty_level_down_threshold: 400 60 | reward_penalty_level_up_threshold: 700 61 | reward_penalty_degree: 0.00001 62 | num_compute_average_epl: 10000 63 | 64 | reward_penalty_reward_names : [ 65 | "penalty_torques", 66 | "penalty_dof_acc", 67 | "penalty_dof_vel", 68 | "penalty_action_rate", 69 | "penalty_feet_contact_forces", 70 | "penalty_stumble", 71 | "penalty_slippage", 72 | "penalty_feet_ori", 73 | "penalty_in_the_air", 74 | "penalty_lin_vel_z", 75 | "penalty_ang_vel_xy", 76 | "penalty_orientation", 77 | #"base_height", 78 | "penalty_feet_height", 79 | "limits_dof_pos", 80 | "limits_dof_vel", 81 | "limits_torque", 82 | "termination", 83 | "feet_air_time", 84 | "feet_max_height_for_this_air", 85 | #"upperbody_joint_angle_freeze", 86 | #"penalty_close_feet_xy", 87 | #"penalty_ang_vel_xy_torso" 88 | ] -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_h1_locomotion.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Unitree_RL GYM EXACT REWARD 8 | set_reward_date: 20241008 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | penalty_lin_vel_z: -2.0 14 | penalty_ang_vel_xy: -1.0 15 | penalty_orientation: -1.0 16 | penalty_torques: -0.00001 17 | # penalty_dof_vel: -0.0001 18 | penalty_dof_acc: -3.5e-8 19 | penalty_action_rate: -0.01 20 | # penalty_feet_contact_forces: -0.01 21 | # penalty_stumble: -10.0 22 | # penalty_slippage: -1.0 23 | penalty_feet_ori: -2.0 24 | limits_dof_pos: -10.0 25 | # limits_dof_vel: -5.0 26 | # limits_torque: -0.1 27 | feet_air_time: 1.0 28 | base_height: -100.0 29 | penalty_feet_height: -5. 30 | # termination: -500.0 31 | # penalty_in_the_air: -100.0 32 | # feet_max_height_for_this_air: -100.0 33 | 34 | 35 | 36 | 37 | reward_tracking_sigma: 38 | lin_vel: 0.25 39 | ang_vel: 0.25 40 | reward_limit: 41 | soft_dof_pos_limit: 0.9 42 | soft_dof_vel_limit: 0.9 43 | soft_torque_limit: 0.9 44 | 45 | feet_height_target: 0.2 46 | locomotion_max_contact_force: 200.0 47 | desired_feet_max_height_for_this_air: 0.2 48 | desired_base_height: 0.98 49 | 50 | reward_penalty_curriculum: False 51 | reward_initial_penalty_scale : 1.0 52 | reward_min_penalty_scale: 0.0 53 | reward_max_penalty_scale: 1.0 54 | reward_penalty_level_down_threshold: 400 55 | reward_penalty_level_up_threshold: 700 56 | reward_penalty_degree: 0.00001 57 | num_compute_average_epl: 10000 58 | 59 | reward_penalty_reward_names : [ 60 | "penalty_torques", 61 | "penalty_dof_acc", 62 | "penalty_dof_vel", 63 | "penalty_action_rate", 64 | "penalty_feet_contact_forces", 65 | "penalty_stumble", 66 | "penalty_slippage", 67 | "penalty_feet_ori", 68 | "penalty_in_the_air", 69 | "limits_dof_pos", 70 | "limits_dof_vel", 71 | "limits_torque", 72 | "termination", 73 | "feet_air_time", 74 | "feet_max_height_for_this_air"] 75 | 76 | -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_h1_locomotion_10dof.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Jiawei & Tairan 8 | set_reward_date: 20241125 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | penalty_lin_vel_z: -2.0 14 | penalty_ang_vel_xy: -1.0 15 | penalty_orientation: -1.0 16 | penalty_torques: -0.00001 17 | # penalty_dof_vel: -0.0001 18 | penalty_dof_acc: -3.5e-8 19 | penalty_action_rate: -0.01 20 | # penalty_feet_contact_forces: -0.01 21 | # penalty_stumble: -10.0 22 | # penalty_slippage: -1.0 23 | penalty_feet_ori: -2.0 24 | limits_dof_pos: -10.0 25 | # limits_dof_vel: -5.0 26 | # limits_torque: -0.1 27 | feet_air_time: 1.0 28 | base_height: -100.0 29 | penalty_feet_height: -5. 30 | # termination: -500.0 31 | # penalty_in_the_air: -100.0 32 | # feet_max_height_for_this_air: -100.0 33 | 34 | 35 | 36 | 37 | reward_tracking_sigma: 38 | lin_vel: 0.25 39 | ang_vel: 0.25 40 | reward_limit: 41 | soft_dof_pos_limit: 0.9 42 | soft_dof_vel_limit: 0.9 43 | soft_torque_limit: 0.9 44 | 45 | feet_height_target: 0.2 46 | locomotion_max_contact_force: 200.0 47 | desired_feet_max_height_for_this_air: 0.2 48 | desired_base_height: 0.98 49 | 50 | reward_penalty_curriculum: False 51 | reward_initial_penalty_scale : 1.0 52 | reward_min_penalty_scale: 0.0 53 | reward_max_penalty_scale: 1.0 54 | reward_penalty_level_down_threshold: 400 55 | reward_penalty_level_up_threshold: 700 56 | reward_penalty_degree: 0.00001 57 | num_compute_average_epl: 10000 58 | 59 | reward_penalty_reward_names : [ 60 | "penalty_torques", 61 | "penalty_dof_acc", 62 | "penalty_dof_vel", 63 | "penalty_action_rate", 64 | "penalty_feet_contact_forces", 65 | "penalty_stumble", 66 | "penalty_slippage", 67 | "penalty_feet_ori", 68 | "penalty_in_the_air", 69 | "limits_dof_pos", 70 | "limits_dof_vel", 71 | "limits_torque", 72 | "termination", 73 | "feet_air_time", 74 | "feet_max_height_for_this_air"] 75 | 76 | -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_h1_locomotion_19dof_2real.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Unitree_RL GYM EXACT REWARD 8 | set_reward_date: 20241008 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | penalty_lin_vel_z: -2.0 14 | penalty_ang_vel_xy: -1.0 15 | penalty_orientation: -1.0 16 | penalty_torques: -0.00001 17 | # penalty_dof_vel: -0.0001 18 | penalty_dof_acc: -3.5e-8 19 | penalty_action_rate: -0.01 20 | # penalty_feet_contact_forces: -0.01 21 | # penalty_stumble: -10.0 22 | # penalty_slippage: -1.0 23 | penalty_feet_ori: -2.0 24 | limits_dof_pos: -10.0 25 | # limits_dof_vel: -5.0 26 | # limits_torque: -0.1 27 | feet_air_time: 1.0 28 | base_height: -100.0 29 | penalty_feet_height: -5. 30 | # termination: -500.0 31 | # penalty_in_the_air: -100.0 32 | # feet_max_height_for_this_air: -100.0 33 | upperbody_joint_angle_freeze: -0.2 34 | 35 | 36 | 37 | 38 | reward_tracking_sigma: 39 | lin_vel: 0.25 40 | ang_vel: 0.25 41 | reward_limit: 42 | soft_dof_pos_limit: 0.9 43 | soft_dof_vel_limit: 0.9 44 | soft_torque_limit: 0.9 45 | 46 | feet_height_target: 0.2 47 | locomotion_max_contact_force: 200.0 48 | desired_feet_max_height_for_this_air: 0.2 49 | desired_base_height: 0.98 50 | 51 | reward_penalty_curriculum: False 52 | reward_initial_penalty_scale : 1.0 53 | reward_min_penalty_scale: 0.0 54 | reward_max_penalty_scale: 1.0 55 | reward_penalty_level_down_threshold: 400 56 | reward_penalty_level_up_threshold: 700 57 | reward_penalty_degree: 0.00001 58 | num_compute_average_epl: 10000 59 | 60 | reward_penalty_reward_names : [ 61 | "penalty_lin_vel_z", 62 | "penalty_ang_vel_xy", 63 | "penalty_orientation", 64 | "penalty_torques", 65 | "penalty_dof_acc", 66 | "penalty_dof_vel", 67 | "penalty_action_rate", 68 | "penalty_feet_contact_forces", 69 | "penalty_stumble", 70 | "penalty_slippage", 71 | "penalty_feet_ori", 72 | "penalty_in_the_air", 73 | "limits_dof_pos", 74 | "limits_dof_vel", 75 | "limits_torque", 76 | "termination", 77 | "feet_air_time", 78 | "feet_max_height_for_this_air", 79 | "penalty_feet_height", 80 | "upperbody_joint_angle_freeze"] 81 | 82 | -------------------------------------------------------------------------------- /humanoidverse/config/rewards/loco/reward_h1_locomotion_positiveonly.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Unitree_RL GYM EXACT REWARD 8 | set_reward_date: 20241008 9 | only_positive_rewards: False 10 | reward_scales: 11 | tracking_lin_vel: 1.0 12 | tracking_ang_vel: 0.5 13 | 14 | 15 | 16 | 17 | reward_tracking_sigma: 18 | lin_vel: 0.25 19 | ang_vel: 0.25 20 | reward_limit: 21 | soft_dof_pos_limit: 0.9 22 | soft_dof_vel_limit: 0.9 23 | soft_torque_limit: 0.9 24 | 25 | feet_height_target: 0.2 26 | locomotion_max_contact_force: 200.0 27 | desired_feet_max_height_for_this_air: 0.2 28 | desired_base_height: 0.98 29 | 30 | reward_penalty_curriculum: False 31 | reward_initial_penalty_scale : 1.0 32 | reward_min_penalty_scale: 0.0 33 | reward_max_penalty_scale: 1.0 34 | reward_penalty_level_down_threshold: 400 35 | reward_penalty_level_up_threshold: 700 36 | reward_penalty_degree: 0.00001 37 | num_compute_average_epl: 10000 38 | 39 | reward_penalty_reward_names : [ 40 | "penalty_torques", 41 | "penalty_dof_acc", 42 | "penalty_dof_vel", 43 | "penalty_action_rate", 44 | "penalty_feet_contact_forces", 45 | "penalty_stumble", 46 | "penalty_slippage", 47 | "penalty_feet_ori", 48 | "penalty_in_the_air", 49 | "limits_dof_pos", 50 | "limits_dof_vel", 51 | "limits_torque", 52 | "termination", 53 | "feet_air_time", 54 | "feet_max_height_for_this_air"] 55 | 56 | -------------------------------------------------------------------------------- /humanoidverse/config/rewards/motion_tracking/reward_motion_tracking_basic.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Tairan 8 | set_reward_date: 20241025 9 | only_positive_rewards: False 10 | reward_scales: 11 | teleop_body_position_extend: 1.0 12 | teleop_vr_3point: 1.0 13 | teleop_body_position_feet: 1.0 14 | teleop_body_rotation_extend: 0.5 15 | teleop_body_ang_velocity_extend: 0.5 16 | teleop_body_velocity_extend: 0.5 17 | teleop_joint_position: 0.5 18 | teleop_joint_velocity: 0.5 19 | penalty_torques: -0.000001 20 | # penalty_dof_vel: -0.0001 21 | # penalty_dof_acc: -2.5e-8 22 | penalty_action_rate: -0.001 23 | # penalty_feet_contact_forces: -0.01 24 | # penalty_stumble: -10.0 25 | # penalty_slippage: -1.0 26 | # penalty_feet_ori: -10.0 27 | limits_dof_pos: -10.0 28 | limits_dof_vel: -5.0 29 | limits_torque: -0.1 30 | termination: -200.0 31 | # feet_max_height_for_this_air: -100.0 32 | 33 | teleop_body_pos_lowerbody_weight : 0.5 34 | teleop_body_pos_upperbody_weight : 1.0 35 | 36 | reward_tracking_sigma: 37 | teleop_upper_body_pos: 0.03 38 | teleop_lower_body_pos: 0.1 39 | teleop_vr_3point_pos: 0.03 40 | teleop_feet_pos: 0.03 41 | 42 | teleop_body_rot: 1.0 43 | teleop_body_vel: 1.0 44 | teleop_body_ang_vel: 1.0 45 | teleop_joint_pos: 1.0 46 | teleop_joint_vel: 1.0 47 | 48 | 49 | reward_limit: 50 | soft_dof_pos_limit: 0.95 51 | soft_dof_vel_limit: 0.95 52 | soft_torque_limit: 0.95 53 | 54 | reward_limits_curriculum: 55 | soft_dof_pos_curriculum: False 56 | soft_dof_pos_initial_limit: 1.25 57 | soft_dof_pos_max_limit: 1.25 58 | soft_dof_pos_min_limit: 0.95 59 | soft_dof_pos_curriculum_degree: 0.0000003 60 | soft_dof_pos_curriculum_level_down_threshold: 40 61 | soft_dof_pos_curriculum_level_up_threshold: 42 62 | 63 | soft_dof_vel_curriculum: False 64 | soft_dof_vel_initial_limit: 1.25 65 | soft_dof_vel_max_limit: 1.25 66 | soft_dof_vel_min_limit: 0.95 67 | soft_dof_vel_curriculum_degree: 0.0000003 68 | soft_dof_vel_curriculum_level_down_threshold: 40 69 | soft_dof_vel_curriculum_level_up_threshold: 42 70 | 71 | soft_torque_curriculum: False 72 | soft_torque_initial_limit: 1.25 73 | soft_torque_max_limit: 1.25 74 | soft_torque_min_limit: 0.85 75 | soft_torque_curriculum_degree: 0.0000003 76 | soft_torque_curriculum_level_down_threshold: 40 77 | soft_torque_curriculum_level_up_threshold: 42 78 | 79 | # locomotion_max_contact_force: 200.0 80 | # desired_feet_max_height_for_this_air: 0.2 81 | 82 | reward_penalty_curriculum: False 83 | reward_initial_penalty_scale : 0.1 84 | reward_min_penalty_scale: 0.0 85 | reward_max_penalty_scale: 1.0 86 | reward_penalty_level_down_threshold: 50 87 | reward_penalty_level_up_threshold: 100 88 | reward_penalty_degree: 0.00001 89 | num_compute_average_epl: 10000 90 | 91 | reward_penalty_reward_names : [ 92 | "penalty_torques", 93 | "penalty_dof_acc", 94 | "penalty_dof_vel", 95 | "penalty_action_rate", 96 | "limits_dof_pos", 97 | "limits_dof_vel", 98 | "limits_torque"] -------------------------------------------------------------------------------- /humanoidverse/config/rewards/motion_tracking/reward_motion_tracking_dm_2real.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # defaults: 4 | # - reward_base 5 | 6 | rewards: 7 | set_reward: Tairan 8 | set_reward_date: 20241025 9 | only_positive_rewards: False 10 | reward_scales: 11 | teleop_body_position_extend: 1.0 12 | teleop_vr_3point: 1.6 13 | teleop_body_position_feet: 2.1 14 | teleop_body_rotation_extend: 0.5 15 | teleop_body_ang_velocity_extend: 0.5 16 | teleop_body_velocity_extend: 0.5 17 | teleop_joint_position: 0.75 18 | teleop_joint_velocity: 0.5 19 | penalty_torques: -0.000001 20 | # penalty_dof_vel: -0.0001 21 | # penalty_dof_acc: -2.5e-8 22 | penalty_action_rate: -0.5 # need to be tuned up to -0.5 for real robot 23 | # penalty_feet_contact_forces: -0.01 24 | # penalty_stumble: -10.0 25 | 26 | # better for landing 27 | penalty_feet_ori: -2.0 28 | feet_heading_alignment: -0.1 29 | penalty_slippage: -1.0 30 | 31 | limits_dof_pos: -10.0 32 | limits_dof_vel: -5.0 33 | limits_torque: -5.0 34 | termination: -200.0 35 | # feet_max_height_for_this_air: -100.0 36 | 37 | 38 | teleop_body_pos_lowerbody_weight : 0.5 39 | teleop_body_pos_upperbody_weight : 1.0 40 | 41 | desired_feet_max_height_for_this_air: 0.2 42 | 43 | reward_tracking_sigma: 44 | teleop_upper_body_pos: 0.03 45 | teleop_lower_body_pos: 0.1 46 | teleop_vr_3point_pos: 0.03 47 | teleop_feet_pos: 0.03 48 | 49 | teleop_body_rot: 1.0 50 | teleop_body_vel: 1.0 51 | teleop_body_ang_vel: 1.0 52 | teleop_joint_pos: 1.0 53 | teleop_joint_vel: 1.0 54 | 55 | 56 | 57 | # locomotion_max_contact_force: 200.0 58 | # desired_feet_max_height_for_this_air: 0.2 59 | 60 | reward_penalty_curriculum: False 61 | reward_initial_penalty_scale : 0.10 62 | reward_min_penalty_scale: 0.0 63 | reward_max_penalty_scale: 1.0 64 | reward_penalty_level_down_threshold: 40 65 | reward_penalty_level_up_threshold: 42 # shortest motion in TairanTestbed is 92, therefore 46 is the middle point, we set 42 here for curriculum learning level up 66 | reward_penalty_degree: 0.000003 # 0.00001 67 | num_compute_average_epl: 10000 68 | 69 | reward_limit: 70 | soft_dof_pos_limit: 0.9 71 | soft_dof_vel_limit: 0.9 72 | soft_torque_limit: 0.825 73 | 74 | reward_limits_curriculum: 75 | soft_dof_pos_curriculum: True 76 | soft_dof_pos_initial_limit: 1.15 77 | soft_dof_pos_max_limit: 1.15 78 | soft_dof_pos_min_limit: 0.95 79 | soft_dof_pos_curriculum_degree: 0.00000025 80 | soft_dof_pos_curriculum_level_down_threshold: 40 81 | soft_dof_pos_curriculum_level_up_threshold: 42 82 | 83 | soft_dof_vel_curriculum: True 84 | soft_dof_vel_initial_limit: 1.15 85 | soft_dof_vel_max_limit: 1.25 86 | soft_dof_vel_min_limit: 0.95 87 | soft_dof_vel_curriculum_degree: 0.00000025 88 | soft_dof_vel_curriculum_level_down_threshold: 40 89 | soft_dof_vel_curriculum_level_up_threshold: 42 90 | 91 | soft_torque_curriculum: True 92 | soft_torque_initial_limit: 1.15 93 | soft_torque_max_limit: 1.25 94 | soft_torque_min_limit: 0.85 95 | soft_torque_curriculum_degree: 0.00000025 96 | soft_torque_curriculum_level_down_threshold: 40 97 | soft_torque_curriculum_level_up_threshold: 42 98 | 99 | reward_penalty_reward_names : [ 100 | "penalty_torques", 101 | "penalty_dof_acc", 102 | "penalty_dof_vel", 103 | "penalty_action_rate", 104 | "limits_dof_pos", 105 | "limits_dof_vel", 106 | "limits_torque", 107 | "feet_heading_alignment", 108 | "penalty_feet_ori", 109 | "penalty_slippage"] -------------------------------------------------------------------------------- /humanoidverse/config/robot/robot_base.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | robot: 4 | # Observation parameters 5 | dof_obs_size: ??? 6 | number_of_actions: ??? 7 | self_obs_max_coords: ??? 8 | num_bodies: ??? 9 | 10 | # Control parameters 11 | # dof_body_ids: ??? 12 | # dof_offsets: ??? 13 | 14 | algo_obs_dim_dict: ??? 15 | 16 | key_bodies: null 17 | contact_bodies: null 18 | 19 | foot_name: null 20 | 21 | init_state: null 22 | 23 | contact_pairs_multiplier: 16 24 | 25 | num_key_bodies: ${len:${robot.key_bodies}} 26 | mimic_small_marker_bodies: null 27 | 28 | randomize_link_body_names: ??? 29 | 30 | control: 31 | # Can be "isaac_pd" or "P"/"V"/"T" for Proportional, Velocity, Torque control 32 | control_type: isaac_pd 33 | # PD Drive parameters: 34 | stiffness: null 35 | damping: null 36 | # action scale: target angle = actionScale * action + defaultAngle 37 | # only used in manual PD control 38 | action_scale: 1.0 39 | # Used with isaac pd controller 40 | isaac_pd_scale: False # This is needed for the SMPL model due to weight variations 41 | clamp_actions: 1.0 42 | clip_torques: ??? 43 | 44 | asset: 45 | collapse_fixed_joints: null 46 | replace_cylinder_with_capsule: null 47 | flip_visual_attachments: null 48 | armature: null 49 | thickness: null 50 | max_angular_velocity: null 51 | max_linear_velocity: null 52 | density: null 53 | angular_damping: null 54 | linear_damping: null 55 | disable_gravity: null 56 | fix_base_link: null 57 | default_dof_drive_mode: 1 # see GymDofDriveModeFlags (0 is none, 1 is pos tgt, 2 is vel tgt, 3 effort) 58 | 59 | robot_type: ??? 60 | urdf_file: null 61 | usd_file: null 62 | xml_file: null 63 | asset_root: "humanoidverse/data/robots" 64 | self_collisions: True 65 | filter_ints: null 66 | 67 | # motion_lib: 68 | # _target_: phys_anim.utils.motion_lib.MotionLib 69 | # motion_file: ${motion_file} 70 | # ref_height_adjust: 0. 71 | # fix_motion_heights: True 72 | -------------------------------------------------------------------------------- /humanoidverse/config/simulator/genesis.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Env structure 4 | simulator: 5 | _target_: humanoidverse.simulator.genesis.genesis.Genesis 6 | _recursive_: False 7 | config: 8 | name: "genesis" 9 | terrain: ${terrain} 10 | plane: 11 | static_friction: 1.0 12 | dynamic_friction: 1.0 13 | restitution: 0.0 14 | sim: 15 | fps: 200 16 | control_decimation: 4 17 | substeps: 1 18 | render_mode: "human" # [None, "human", "rgb_array"] 19 | render_interval: 1 20 | 21 | scene: 22 | num_envs: ${num_envs} 23 | env_spacing: ${env.config.env_spacing} 24 | replicate_physics: True -------------------------------------------------------------------------------- /humanoidverse/config/simulator/isaacgym.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Env structure 4 | simulator: 5 | _target_: humanoidverse.simulator.isaacgym.isaacgym.IsaacGym 6 | _recursive_: False 7 | config: 8 | name: "isaacgym" 9 | terrain: ${terrain} 10 | plane: 11 | static_friction: 1.0 12 | dynamic_friction: 1.0 13 | restitution: 0.0 14 | sim: 15 | fps: 200 16 | control_decimation: 4 17 | substeps: 1 18 | physx: 19 | num_threads: 4 20 | solver_type: 1 # 0: pgs, 1: tgs 21 | num_position_iterations: 4 22 | num_velocity_iterations: 0 23 | contact_offset: 0.01 24 | rest_offset: 0.0 25 | bounce_threshold_velocity: 0.5 26 | max_depenetration_velocity: 1.0 27 | default_buffer_size_multiplier: 5 28 | contact_collection: 2 -------------------------------------------------------------------------------- /humanoidverse/config/simulator/isaacsim.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Env structure 4 | simulator: 5 | _target_: humanoidverse.simulator.isaacsim.isaacsim.IsaacSim 6 | _recursive_: False 7 | config: 8 | name: "isaacsim" 9 | terrain: ${terrain} 10 | plane: 11 | static_friction: 1.0 12 | dynamic_friction: 1.0 13 | restitution: 0.0 14 | sim: 15 | fps: 200 16 | control_decimation: 4 17 | substeps: 1 18 | physx: 19 | num_threads: 10 20 | solver_type: 1 # 0: pgs, 1: tgs 21 | num_position_iterations: 4 22 | num_velocity_iterations: 0 23 | contact_offset: 0.01 24 | rest_offset: 0.0 25 | bounce_threshold_velocity: 0.5 26 | max_depenetration_velocity: 1.0 27 | default_buffer_size_multiplier: 5 28 | contact_collection: 2 29 | render_mode: "human" # [None, "human", "rgb_array"] 30 | render_interval: 4 31 | 32 | scene: 33 | num_envs: ${num_envs} 34 | env_spacing: ${env.config.env_spacing} 35 | replicate_physics: True -------------------------------------------------------------------------------- /humanoidverse/config/simulator/mujoco.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | # Env structure 4 | simulator: 5 | _target_: humanoidverse.simulator.mujoco.mujoco.MuJoCo 6 | _recursive_: False 7 | config: 8 | name: "mujoco" 9 | terrain: ${terrain} 10 | plane: 11 | static_friction: 1.0 12 | dynamic_friction: 1.0 13 | restitution: 0.0 14 | sim: 15 | fps: 200 16 | control_decimation: 4 17 | substeps: 1 18 | render_mode: "human" # [None, "human", "rgb_array"] 19 | render_interval: 1 20 | 21 | scene: 22 | num_envs: ${num_envs} 23 | env_spacing: ${env.config.env_spacing} -------------------------------------------------------------------------------- /humanoidverse/config/terrain/terrain_base.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | terrain: 4 | static_friction: 1.0 5 | dynamic_friction: 1.0 6 | restitution: 0.0 -------------------------------------------------------------------------------- /humanoidverse/config/terrain/terrain_locomotion.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - terrain_base 5 | 6 | terrain: 7 | mesh_type : 'trimesh' # "heightfield" # none, plane, heightfield or trimesh 8 | horizontal_scale : 0.1 # [m] 9 | vertical_scale : 0.005 # [m] 10 | border_size : 40 # [m] 11 | curriculum : False 12 | # curriculum : False 13 | static_friction: 1.0 14 | dynamic_friction: 1.0 15 | restitution: 0.0 16 | # rough terrain only: 17 | measure_heights : False # keep it False 18 | measured_points_x : [ 0.] # 1mx1.6m rectangle (without center line) 19 | measured_points_y : [ 0.] 20 | selected : False # select a unique terrain type and pass all arguments 21 | terrain_kwargs : null # Dict of arguments for selected terrain 22 | max_init_terrain_level : 9 # starting curriculum state 23 | terrain_length : 8. 24 | terrain_width : 8. 25 | num_rows: 10 # number of terrain rows (levels) 26 | num_cols : 20 # number of terrain cols (types) 27 | terrain_types : ['flat', 'rough', 'low_obst', 'smooth_slope', 'rough_slope'] # do not duplicate! 28 | terrain_proportions : [0.2, 0.6, 0.2, 0.0, 0.0] 29 | # trimesh only: 30 | slope_treshold : 0.75 # slopes above this threshold will be corrected to vertical surfaces -------------------------------------------------------------------------------- /humanoidverse/config/terrain/terrain_locomotion_plane.yaml: -------------------------------------------------------------------------------- 1 | # @package _global_ 2 | 3 | defaults: 4 | - terrain_base 5 | 6 | terrain: 7 | mesh_type : 'plane' # "heightfield" # none, plane, heightfield or trimesh 8 | horizontal_scale : 0.1 # [m] 9 | vertical_scale : 0.005 # [m] 10 | border_size : 40 # [m] 11 | curriculum : False 12 | # curriculum : False 13 | static_friction: 1.0 14 | dynamic_friction: 1.0 15 | restitution: 0.0 16 | # rough terrain only: 17 | measure_heights : False # keep it False 18 | measured_points_x : [ 0.] # 1mx1.6m rectangle (without center line) 19 | measured_points_y : [ 0.] 20 | selected : False # select a unique terrain type and pass all arguments 21 | terrain_kwargs : null # Dict of arguments for selected terrain 22 | max_init_terrain_level : 9 # starting curriculum state 23 | terrain_length : 8. 24 | terrain_width : 8. 25 | num_rows: 10 # number of terrain rows (levels) 26 | num_cols : 20 # number of terrain cols (types) 27 | terrain_types : ['flat', 'rough', 'low_obst', 'smooth_slope', 'rough_slope'] # do not duplicate! 28 | terrain_proportions : [0.2, 0.6, 0.2, 0.0, 0.0] 29 | # trimesh only: 30 | slope_treshold : 0.75 # slopes above this threshold will be corrected to vertical surfaces -------------------------------------------------------------------------------- /humanoidverse/data/motions/g1_29dof_anneal_23dof/TairanTestbed/singles/0-TairanTestbed_TairanTestbed_CR7_video_CR7_level1_filter_amass.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/motions/g1_29dof_anneal_23dof/TairanTestbed/singles/0-TairanTestbed_TairanTestbed_CR7_video_CR7_level1_filter_amass.pkl -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/.asset_hash: -------------------------------------------------------------------------------- 1 | b3de36f52e27b977487af75b6c3a10bf -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/g1_29dof_anneal_23dof.usd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/g1_29dof_anneal_23dof.usd -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/head_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/head_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_ankle_pitch_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_ankle_pitch_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_ankle_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_ankle_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_elbow_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_elbow_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_elbow_link_merge.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_elbow_link_merge.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hand_index_0_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hand_index_0_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hand_index_1_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hand_index_1_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hand_middle_0_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hand_middle_0_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hand_middle_1_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hand_middle_1_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hand_palm_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hand_palm_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hand_thumb_0_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hand_thumb_0_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hand_thumb_1_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hand_thumb_1_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hand_thumb_2_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hand_thumb_2_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hip_pitch_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hip_pitch_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hip_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hip_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_hip_yaw_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_hip_yaw_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_knee_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_knee_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_rubber_hand.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_rubber_hand.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_shoulder_pitch_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_shoulder_pitch_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_shoulder_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_shoulder_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_shoulder_yaw_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_shoulder_yaw_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_wrist_pitch_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_wrist_pitch_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_wrist_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_wrist_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_wrist_roll_rubber_hand.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_wrist_roll_rubber_hand.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/left_wrist_yaw_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/left_wrist_yaw_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/logo_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/logo_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/pelvis.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/pelvis.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/pelvis_contour_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/pelvis_contour_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_ankle_pitch_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_ankle_pitch_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_ankle_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_ankle_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_elbow_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_elbow_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_elbow_link_merge.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_elbow_link_merge.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hand_index_0_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hand_index_0_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hand_index_1_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hand_index_1_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hand_middle_0_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hand_middle_0_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hand_middle_1_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hand_middle_1_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hand_palm_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hand_palm_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hand_thumb_0_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hand_thumb_0_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hand_thumb_1_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hand_thumb_1_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hand_thumb_2_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hand_thumb_2_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hip_pitch_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hip_pitch_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hip_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hip_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_hip_yaw_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_hip_yaw_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_knee_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_knee_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_rubber_hand.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_rubber_hand.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_shoulder_pitch_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_shoulder_pitch_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_shoulder_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_shoulder_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_shoulder_yaw_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_shoulder_yaw_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_wrist_pitch_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_wrist_pitch_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_wrist_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_wrist_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_wrist_roll_rubber_hand.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_wrist_roll_rubber_hand.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/right_wrist_yaw_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/right_wrist_yaw_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/torso_constraint_L_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/torso_constraint_L_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/torso_constraint_L_rod_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/torso_constraint_L_rod_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/torso_constraint_R_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/torso_constraint_R_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/torso_constraint_R_rod_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/torso_constraint_R_rod_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/torso_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/torso_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/waist_constraint_L.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/waist_constraint_L.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/waist_constraint_R.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/waist_constraint_R.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/waist_roll_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/waist_roll_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/waist_support_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/waist_support_link.STL -------------------------------------------------------------------------------- /humanoidverse/data/robots/g1/meshes/waist_yaw_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/data/robots/g1/meshes/waist_yaw_link.STL -------------------------------------------------------------------------------- /humanoidverse/envs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/envs/__init__.py -------------------------------------------------------------------------------- /humanoidverse/envs/base_task/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/envs/base_task/__init__.py -------------------------------------------------------------------------------- /humanoidverse/envs/env_utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/envs/env_utils/__init__.py -------------------------------------------------------------------------------- /humanoidverse/envs/env_utils/command_generator.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | from humanoidverse.envs.env_utils.general import class_to_dict 4 | from isaac_utils.maths import torch_rand_float 5 | 6 | class CommandGenerator: 7 | def __init__(self, config, device, num_envs): 8 | self.config = config 9 | self.device = device 10 | self.num_envs = num_envs 11 | 12 | self.command_ranges = self.config.locomotion_command_ranges 13 | self.commands = torch.zeros( 14 | (num_envs, 3), dtype=torch.float32, device=self.device 15 | ) 16 | 17 | def get_commands(self, env_ids): 18 | return self.commands[env_ids] 19 | 20 | def resample_commands(self, env_ids): 21 | self.commands[env_ids, 0] = torch_rand_float(self.command_ranges["lin_vel_x"][0], self.command_ranges["lin_vel_x"][1], (len(env_ids), 1), device=str(self.device)).squeeze(1) 22 | self.commands[env_ids, 1] = torch_rand_float(self.command_ranges["lin_vel_y"][0], self.command_ranges["lin_vel_y"][1], (len(env_ids), 1), device=str(self.device)).squeeze(1) 23 | self.commands[env_ids, 2] = torch_rand_float(self.command_ranges["ang_vel_yaw"][0], self.command_ranges["ang_vel_yaw"][1], (len(env_ids), 1), device=str(self.device)).squeeze(1) 24 | 25 | def reset(self, env_ids): 26 | self.commands[env_ids] = torch.zeros( 27 | (env_ids.shape[0], 3), dtype=torch.float32, device=self.device 28 | ) 29 | -------------------------------------------------------------------------------- /humanoidverse/envs/env_utils/general.py: -------------------------------------------------------------------------------- 1 | import os 2 | import copy 3 | import torch 4 | import numpy as np 5 | 6 | def class_to_dict(obj) -> dict: 7 | if not hasattr(obj,"__dict__"): 8 | return obj 9 | result = {} 10 | for key in dir(obj): 11 | if key.startswith("_"): 12 | continue 13 | element = [] 14 | val = getattr(obj, key) 15 | if isinstance(val, list): 16 | for item in val: 17 | element.append(class_to_dict(item)) 18 | else: 19 | element = class_to_dict(val) 20 | result[key] = element 21 | return result 22 | 23 | def update_class_from_dict(obj, dict): 24 | for key, val in dict.items(): 25 | attr = getattr(obj, key, None) 26 | if isinstance(attr, type): 27 | update_class_from_dict(attr, val) 28 | else: 29 | setattr(obj, key, val) 30 | return -------------------------------------------------------------------------------- /humanoidverse/envs/env_utils/history_handler.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import Tensor 3 | from termcolor import colored 4 | from loguru import logger 5 | 6 | class HistoryHandler: 7 | 8 | def __init__(self, num_envs, history_config, obs_dims, device): 9 | self.obs_dims = obs_dims 10 | self.device = device 11 | self.num_envs = num_envs 12 | self.history = {} 13 | 14 | self.buffer_config = {} 15 | for aux_key, aux_config in history_config.items(): 16 | for obs_key, obs_num in aux_config.items(): 17 | if obs_key in self.buffer_config: 18 | self.buffer_config[obs_key] = max(self.buffer_config[obs_key], obs_num) 19 | else: 20 | self.buffer_config[obs_key] = obs_num 21 | 22 | for key in self.buffer_config.keys(): 23 | self.history[key] = torch.zeros(num_envs, self.buffer_config[key], obs_dims[key], device=self.device) 24 | 25 | logger.info(colored("History Handler Initialized", "green")) 26 | for key, value in self.buffer_config.items(): 27 | logger.info(f"Key: {key}, Value: {value}") 28 | 29 | def reset(self, reset_ids): 30 | if len(reset_ids)==0: 31 | return 32 | assert set(self.buffer_config.keys()) == set(self.history.keys()), f"History keys mismatch\n{self.buffer_config.keys()}\n{self.history.keys()}" 33 | for key in self.history.keys(): 34 | self.history[key][reset_ids] *= 0. 35 | 36 | def add(self, key: str, value: Tensor): 37 | assert key in self.history.keys(), f"Key {key} not found in history" 38 | val = self.history[key].clone() 39 | self.history[key][:, 1:] = val[:, :-1] 40 | self.history[key][:, 0] = value.clone() 41 | 42 | def query(self, key: str): 43 | assert key in self.history.keys(), f"Key {key} not found in history" 44 | return self.history[key].clone() -------------------------------------------------------------------------------- /humanoidverse/envs/env_utils/visualization.py: -------------------------------------------------------------------------------- 1 | 2 | class Point: 3 | # this is for visualization 4 | def __init__(self, pt): 5 | self.x = pt[0] 6 | self.y = pt[1] 7 | self.z = pt[2] -------------------------------------------------------------------------------- /humanoidverse/envs/legged_base_task/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/envs/legged_base_task/__init__.py -------------------------------------------------------------------------------- /humanoidverse/envs/locomotion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/envs/locomotion/__init__.py -------------------------------------------------------------------------------- /humanoidverse/envs/motion_tracking/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/envs/motion_tracking/__init__.py -------------------------------------------------------------------------------- /humanoidverse/simulator/base_simulator/base_simulator.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | from loguru import logger 4 | import torch 5 | 6 | class BaseSimulator: 7 | """ 8 | Base class for robotic simulation environments, providing a framework for simulation setup, 9 | environment creation, and control over robotic assets and simulation properties. 10 | """ 11 | def __init__(self, config, device): 12 | """ 13 | Initializes the base simulator with configuration settings and simulation device. 14 | 15 | Args: 16 | config (dict): Configuration dictionary for the simulation. 17 | device (str): Device type for simulation ('cpu' or 'cuda'). 18 | """ 19 | self.config = config 20 | self.sim_device = device 21 | self.headless = False 22 | 23 | self._rigid_body_pos: torch.Tensor 24 | self._rigid_body_rot: torch.Tensor 25 | self._rigid_body_vel: torch.Tensor 26 | self._rigid_body_ang_vel: torch.Tensor 27 | 28 | # ----- Configuration Setup Methods ----- 29 | 30 | def set_headless(self, headless): 31 | """ 32 | Sets the headless mode for the simulator. 33 | 34 | Args: 35 | headless (bool): If True, runs the simulation without graphical display. 36 | """ 37 | self.headless = headless 38 | 39 | def setup(self): 40 | """ 41 | Initializes the simulator parameters and environment. This method should be implemented 42 | by subclasses to set specific simulator configurations. 43 | """ 44 | raise NotImplementedError("The 'setup' method must be implemented in subclasses.") 45 | 46 | # ----- Terrain Setup Methods ----- 47 | 48 | def setup_terrain(self, mesh_type): 49 | """ 50 | Configures the terrain based on specified mesh type. 51 | 52 | Args: 53 | mesh_type (str): Type of terrain mesh ('plane', 'heightfield', 'trimesh'). 54 | """ 55 | raise NotImplementedError("The 'setup_terrain' method must be implemented in subclasses.") 56 | 57 | # ----- Robot Asset Setup Methods ----- 58 | 59 | def load_assets(self, robot_config): 60 | """ 61 | Loads the robot assets into the simulation environment. 62 | save self.num_dofs, self.num_bodies, self.dof_names, self.body_names 63 | Args: 64 | robot_config (dict): HumanoidVerse Configuration for the robot asset. 65 | """ 66 | raise NotImplementedError("The 'load_assets' method must be implemented in subclasses.") 67 | 68 | # ----- Environment Creation Methods ----- 69 | 70 | def create_envs(self, num_envs, env_origins, base_init_state, env_config): 71 | """ 72 | Creates and initializes environments with specified configurations. 73 | 74 | Args: 75 | num_envs (int): Number of environments to create. 76 | env_origins (list): List of origin positions for each environment. 77 | base_init_state (array): Initial state of the base. 78 | env_config (dict): Configuration for each environment. 79 | """ 80 | raise NotImplementedError("The 'create_envs' method must be implemented in subclasses.") 81 | 82 | # ----- Property Retrieval Methods ----- 83 | 84 | def get_dof_limits_properties(self): 85 | """ 86 | Retrieves the DOF (degrees of freedom) limits and properties. 87 | 88 | Returns: 89 | Tuple of tensors representing position limits, velocity limits, and torque limits for each DOF. 90 | """ 91 | raise NotImplementedError("The 'get_dof_limits_properties' method must be implemented in subclasses.") 92 | 93 | def find_rigid_body_indice(self, body_name): 94 | """ 95 | Finds the index of a specified rigid body. 96 | 97 | Args: 98 | body_name (str): Name of the rigid body to locate. 99 | 100 | Returns: 101 | int: Index of the rigid body. 102 | """ 103 | raise NotImplementedError("The 'find_rigid_body_indice' method must be implemented in subclasses.") 104 | 105 | # ----- Simulation Preparation and Refresh Methods ----- 106 | 107 | def prepare_sim(self): 108 | """ 109 | Prepares the simulation environment and refreshes any relevant tensors. 110 | """ 111 | raise NotImplementedError("The 'prepare_sim' method must be implemented in subclasses.") 112 | 113 | def refresh_sim_tensors(self): 114 | """ 115 | Refreshes the state tensors in the simulation to ensure they are up-to-date. 116 | """ 117 | raise NotImplementedError("The 'refresh_sim_tensors' method must be implemented in subclasses.") 118 | 119 | # ----- Control Application Methods ----- 120 | 121 | def apply_torques_at_dof(self, torques): 122 | """ 123 | Applies the specified torques to the robot's degrees of freedom (DOF). 124 | 125 | Args: 126 | torques (tensor): Tensor containing torques to apply. 127 | """ 128 | raise NotImplementedError("The 'apply_torques_at_dof' method must be implemented in subclasses.") 129 | 130 | def set_actor_root_state_tensor(self, set_env_ids, root_states): 131 | """ 132 | Sets the root state tensor for specified actors within environments. 133 | 134 | Args: 135 | set_env_ids (tensor): Tensor of environment IDs where states will be set. 136 | root_states (tensor): New root states to apply. 137 | """ 138 | raise NotImplementedError("The 'set_actor_root_state_tensor' method must be implemented in subclasses.") 139 | 140 | def set_dof_state_tensor(self, set_env_ids, dof_states): 141 | """ 142 | Sets the DOF state tensor for specified actors within environments. 143 | 144 | Args: 145 | set_env_ids (tensor): Tensor of environment IDs where states will be set. 146 | dof_states (tensor): New DOF states to apply. 147 | """ 148 | raise NotImplementedError("The 'set_dof_state_tensor' method must be implemented in subclasses.") 149 | 150 | def simulate_at_each_physics_step(self): 151 | """ 152 | Advances the simulation by a single physics step. 153 | """ 154 | raise NotImplementedError("The 'simulate_at_each_physics_step' method must be implemented in subclasses.") 155 | 156 | # ----- Viewer Setup and Rendering Methods ----- 157 | 158 | def setup_viewer(self): 159 | """ 160 | Sets up a viewer for visualizing the simulation, allowing keyboard interactions. 161 | """ 162 | raise NotImplementedError("The 'setup_viewer' method must be implemented in subclasses.") 163 | 164 | def render(self, sync_frame_time=True): 165 | """ 166 | Renders the simulation frame-by-frame, syncing frame time if required. 167 | 168 | Args: 169 | sync_frame_time (bool): Whether to synchronize the frame time. 170 | """ 171 | raise NotImplementedError("The 'render' method must be implemented in subclasses.") 172 | -------------------------------------------------------------------------------- /humanoidverse/simulator/genesis/genesis_viewer.py: -------------------------------------------------------------------------------- 1 | 2 | class Viewer: 3 | """This class handles controlling the camera associated with a viewport in the simulator. 4 | 5 | It can be used to set the viewpoint camera to track different origin types: 6 | 7 | - **world**: the center of the world (static) 8 | - **env**: the center of an environment (static) 9 | - **asset_root**: the root of an asset in the scene (e.g. tracking a robot moving in the scene) 10 | 11 | On creation, the camera is set to track the origin type specified in the configuration. 12 | 13 | For the :attr:`asset_root` origin type, the camera is updated at each rendering step to track the asset's 14 | root position. For this, it registers a callback to the post update event stream from the simulation app. 15 | """ 16 | 17 | def __init__(self): 18 | """Initialize the ViewportCameraController. 19 | 20 | Args: 21 | env: The environment. 22 | cfg: The configuration for the viewport camera controller. 23 | 24 | Raises: 25 | ValueError: If origin type is configured to be "env" but :attr:`cfg.env_index` is out of bounds. 26 | ValueError: If origin type is configured to be "asset_root" but :attr:`cfg.asset_name` is unset. 27 | 28 | """ 29 | self._cfg = None 30 | return 31 | 32 | def __del__(self): 33 | """Unsubscribe from the callback.""" 34 | # use hasattr to handle case where __init__ has not completed before __del__ is called 35 | return 36 | 37 | """ 38 | Properties 39 | """ 40 | 41 | @property 42 | def cfg(self): 43 | """The configuration for the viewer.""" 44 | return self._cfg 45 | 46 | """ 47 | Public Functions 48 | """ 49 | 50 | def set_view_env_index(self, env_index: int): 51 | """Sets the environment index for the camera view. 52 | 53 | Args: 54 | env_index: The index of the environment to set the camera view to. 55 | 56 | Raises: 57 | ValueError: If the environment index is out of bounds. It should be between 0 and num_envs - 1. 58 | """ 59 | return 60 | 61 | def update_view_to_world(self): 62 | """Updates the viewer's origin to the origin of the world which is (0, 0, 0).""" 63 | return 64 | 65 | def update_view_to_env(self): 66 | """Updates the viewer's origin to the origin of the selected environment.""" 67 | return 68 | 69 | def update_view_to_asset_root(self, asset_name: str): 70 | """Updates the viewer's origin based upon the root of an asset in the scene. 71 | 72 | Args: 73 | asset_name: The name of the asset in the scene. The name should match the name of the 74 | asset in the scene. 75 | 76 | Raises: 77 | ValueError: If the asset is not in the scene. 78 | """ 79 | return 80 | 81 | def update_view_location(self, eye, lookat): 82 | """Updates the camera view pose based on the current viewer origin and the eye and lookat positions. 83 | 84 | Args: 85 | eye: The eye position of the camera. If None, the current eye position is used. 86 | lookat: The lookat position of the camera. If None, the current lookat position is used. 87 | """ 88 | return 89 | 90 | """ 91 | Private Functions 92 | """ 93 | 94 | def _update_tracking_callback(self, event): 95 | """Updates the camera view at each rendering step.""" 96 | return 97 | -------------------------------------------------------------------------------- /humanoidverse/simulator/genesis/tmp_gs_utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | 4 | 5 | def wrap_to_pi(angles): 6 | angles %= 2 * np.pi 7 | angles -= 2 * np.pi * (angles > np.pi) 8 | return angles 9 | 10 | 11 | def gs_rand_float(lower, upper, shape, device): 12 | return (upper - lower) * torch.rand(size=shape, device=device) + lower 13 | 14 | 15 | def gs_inv_quat(quat): 16 | qw, qx, qy, qz = quat.unbind(-1) 17 | inv_quat = torch.stack([1.0 * qw, -qx, -qy, -qz], dim=-1) 18 | return inv_quat 19 | 20 | 21 | def gs_transform_by_quat(pos, quat): 22 | qw, qx, qy, qz = quat.unbind(-1) 23 | 24 | rot_matrix = torch.stack( 25 | [ 26 | 1.0 - 2 * qy**2 - 2 * qz**2, 27 | 2 * qx * qy - 2 * qz * qw, 28 | 2 * qx * qz + 2 * qy * qw, 29 | 2 * qx * qy + 2 * qz * qw, 30 | 1 - 2 * qx**2 - 2 * qz**2, 31 | 2 * qy * qz - 2 * qx * qw, 32 | 2 * qx * qz - 2 * qy * qw, 33 | 2 * qy * qz + 2 * qx * qw, 34 | 1 - 2 * qx**2 - 2 * qy**2, 35 | ], 36 | dim=-1, 37 | ).reshape(*quat.shape[:-1], 3, 3) 38 | rotated_pos = torch.matmul(rot_matrix, pos.unsqueeze(-1)).squeeze(-1) 39 | 40 | return rotated_pos 41 | 42 | 43 | def gs_quat2euler(quat): # xyz 44 | # Extract quaternion components 45 | qw, qx, qy, qz = quat.unbind(-1) 46 | 47 | # Roll (x-axis rotation) 48 | sinr_cosp = 2 * (qw * qx + qy * qz) 49 | cosr_cosp = 1 - 2 * (qx * qx + qy * qy) 50 | roll = torch.atan2(sinr_cosp, cosr_cosp) 51 | 52 | # Pitch (y-axis rotation) 53 | sinp = 2 * (qw * qy - qz * qx) 54 | pitch = torch.where( 55 | torch.abs(sinp) >= 1, 56 | torch.sign(sinp) * torch.tensor(torch.pi / 2), 57 | torch.asin(sinp), 58 | ) 59 | 60 | # Yaw (z-axis rotation) 61 | siny_cosp = 2 * (qw * qz + qx * qy) 62 | cosy_cosp = 1 - 2 * (qy * qy + qz * qz) 63 | yaw = torch.atan2(siny_cosp, cosy_cosp) 64 | 65 | return torch.stack([roll, pitch, yaw], dim=-1) 66 | 67 | 68 | def gs_euler2quat(xyz): # xyz 69 | 70 | roll, pitch, yaw = xyz.unbind(-1) 71 | 72 | cosr = (roll * 0.5).cos() 73 | sinr = (roll * 0.5).sin() 74 | cosp = (pitch * 0.5).cos() 75 | sinp = (pitch * 0.5).sin() 76 | cosy = (yaw * 0.5).cos() 77 | siny = (yaw * 0.5).sin() 78 | 79 | qw = cosr * cosp * cosy + sinr * sinp * siny 80 | qx = sinr * cosp * cosy - cosr * sinp * siny 81 | qy = cosr * sinp * cosy + sinr * cosp * siny 82 | qz = cosr * cosp * siny - sinr * sinp * cosy 83 | 84 | return torch.stack([qw, qx, qy, qz], dim=-1) 85 | 86 | 87 | def gs_quat_from_angle_axis(angle, axis): 88 | theta = (angle / 2).unsqueeze(-1) 89 | xyz = normalize(axis) * theta.sin() 90 | w = theta.cos() 91 | return normalize(torch.cat([w, xyz], dim=-1)) 92 | 93 | 94 | def normalize(x, eps: float = 1e-9): 95 | return x / x.norm(p=2, dim=-1).clamp(min=eps, max=None).unsqueeze(-1) 96 | 97 | 98 | def gs_quat_mul(a, b): 99 | assert a.shape == b.shape 100 | shape = a.shape 101 | a = a.reshape(-1, 4) 102 | b = b.reshape(-1, 4) 103 | 104 | w1, x1, y1, z1 = a[:, 0], a[:, 1], a[:, 2], a[:, 3] 105 | w2, x2, y2, z2 = b[:, 0], b[:, 1], b[:, 2], b[:, 3] 106 | ww = (z1 + x1) * (x2 + y2) 107 | yy = (w1 - y1) * (w2 + z2) 108 | zz = (w1 + y1) * (w2 - z2) 109 | xx = ww + yy + zz 110 | qq = 0.5 * (xx + (z1 - x1) * (x2 - y2)) 111 | w = qq - ww + (z1 - y1) * (y2 - z2) 112 | x = qq - xx + (x1 + w1) * (x2 + w2) 113 | y = qq - yy + (w1 - x1) * (y2 + z2) 114 | z = qq - zz + (z1 + y1) * (w2 - x2) 115 | 116 | quat = torch.stack([w, x, y, z], dim=-1).view(shape) 117 | 118 | return quat 119 | 120 | 121 | def gs_quat_apply(a, b): 122 | shape = b.shape 123 | a = a.reshape(-1, 4) 124 | b = b.reshape(-1, 3) 125 | xyz = a[:, 1:] 126 | t = xyz.cross(b, dim=-1) * 2 127 | return (b + a[:, :1] * t + xyz.cross(t, dim=-1)).view(shape) 128 | 129 | 130 | def gs_quat_apply_yaw(quat, vec): 131 | quat_yaw = quat.clone().view(-1, 4) 132 | quat_yaw[:, 1:3] = 0. 133 | quat_yaw = normalize(quat_yaw) 134 | return gs_quat_apply(quat_yaw, vec) 135 | 136 | 137 | def gs_quat_conjugate(a): 138 | shape = a.shape 139 | a = a.reshape(-1, 4) 140 | return torch.cat((a[:, :1], -a[:, 1:], ), dim=-1).view(shape) 141 | -------------------------------------------------------------------------------- /humanoidverse/simulator/isaacsim/event_cfg.py: -------------------------------------------------------------------------------- 1 | 2 | from omni.isaac.lab.managers import EventTermCfg as EventTerm 3 | 4 | from omni.isaac.lab.managers import SceneEntityCfg 5 | from omni.isaac.lab.utils import configclass 6 | 7 | 8 | import omni.isaac.lab.envs.mdp as mdp 9 | 10 | # @configclass 11 | # class EventCfg: 12 | # """Configuration for events.""" 13 | 14 | # scale_body_mass = EventTerm( 15 | # func=mdp.randomize_rigid_body_mass, 16 | # mode="startup", 17 | # params={ 18 | # "asset_cfg": SceneEntityCfg("robot", body_names=".*"), 19 | # "mass_distribution_params": (0.8, 1.2), 20 | # "operation": "scale", 21 | # }, 22 | # ) 23 | 24 | # random_joint_friction = EventTerm( 25 | # func=mdp.randomize_joint_parameters, 26 | # mode="startup", 27 | # params={ 28 | # "asset_cfg": SceneEntityCfg("robot", joint_names=".*"), 29 | # "friction_distribution_params": (0.5, 1.25), 30 | # "operation": "scale", 31 | # }, 32 | # ) 33 | 34 | @configclass 35 | class EventCfg: 36 | """Configuration for events.""" 37 | scale_body_mass = None 38 | random_joint_friction = None 39 | 40 | 41 | -------------------------------------------------------------------------------- /humanoidverse/simulator/isaacsim/events.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import numpy as np 4 | import torch 5 | from typing import TYPE_CHECKING, Literal 6 | 7 | import omni.isaac.lab.envs.mdp as mdp 8 | import omni.isaac.lab.utils.math as math_utils 9 | from omni.isaac.lab.assets import Articulation, RigidObject 10 | from omni.isaac.lab.managers import SceneEntityCfg 11 | 12 | from omni.isaac.lab.envs import ManagerBasedEnv 13 | 14 | def resolve_dist_fn( 15 | distribution: Literal["uniform", "log_uniform", "gaussian"] = "uniform", 16 | ): 17 | dist_fn = math_utils.sample_uniform 18 | 19 | if distribution == "uniform": 20 | dist_fn = math_utils.sample_uniform 21 | elif distribution == "log_uniform": 22 | dist_fn = math_utils.sample_log_uniform 23 | elif distribution == "gaussian": 24 | dist_fn = math_utils.sample_gaussian 25 | else: 26 | raise ValueError(f"Unrecognized distribution {distribution}") 27 | 28 | return dist_fn 29 | 30 | def randomize_body_com( 31 | env: ManagerBasedEnv, 32 | env_ids: torch.Tensor | None, 33 | asset_cfg: SceneEntityCfg, 34 | distribution_params: tuple[float, float] | tuple[torch.Tensor, torch.Tensor], 35 | operation: Literal["add", "abs", "scale"], 36 | distribution: Literal["uniform", "log_uniform", "gaussian"] = "uniform", 37 | num_envs: int = 1, # number of environments 38 | ): 39 | """Randomize the com of the bodies by adding, scaling or setting random values. 40 | 41 | This function allows randomizing the center of mass of the bodies of the asset. The function samples random values from the 42 | given distribution parameters and adds, scales or sets the values into the physics simulation based on the operation. 43 | 44 | .. tip:: 45 | This function uses CPU tensors to assign the body masses. It is recommended to use this function 46 | only during the initialization of the environment. 47 | """ 48 | # extract the used quantities (to enable type-hinting) 49 | asset: RigidObject | Articulation = env.scene[asset_cfg.name] 50 | 51 | # resolve environment ids 52 | if env_ids is None: 53 | env_ids = torch.arange(num_envs, device="cpu") 54 | else: 55 | env_ids = env_ids.cpu() 56 | 57 | # resolve body indices 58 | if asset_cfg.body_ids == slice(None): 59 | body_ids = torch.arange(asset.num_bodies, dtype=torch.int, device="cpu") 60 | else: 61 | body_ids = torch.tensor(asset_cfg.body_ids, dtype=torch.int, device="cpu") 62 | 63 | # get the current masses of the bodies (num_assets, num_bodies) 64 | coms = asset.root_physx_view.get_coms() 65 | # apply randomization on default values 66 | # import ipdb; ipdb.set_trace() 67 | coms[env_ids[:, None], body_ids] = env.default_coms[env_ids[:, None], body_ids].clone() 68 | 69 | dist_fn = resolve_dist_fn(distribution) 70 | 71 | if isinstance(distribution_params[0], torch.Tensor): 72 | distribution_params = (distribution_params[0].to(coms.device), distribution_params[1].to(coms.device)) 73 | 74 | env.base_com_bias[env_ids, :] = dist_fn( 75 | *distribution_params, (env_ids.shape[0], env.base_com_bias.shape[1]), device=coms.device 76 | ) 77 | 78 | # sample from the given range 79 | if operation == "add": 80 | coms[env_ids[:, None], body_ids, :3] += env.base_com_bias[env_ids[:, None], :] 81 | elif operation == "abs": 82 | coms[env_ids[:, None], body_ids, :3] = env.base_com_bias[env_ids[:, None], :] 83 | elif operation == "scale": 84 | coms[env_ids[:, None], body_ids, :3] *= env.base_com_bias[env_ids[:, None], :] 85 | else: 86 | raise ValueError( 87 | f"Unknown operation: '{operation}' for property randomization. Please use 'add', 'abs' or 'scale'." 88 | ) 89 | # set the mass into the physics simulation 90 | asset.root_physx_view.set_coms(coms, env_ids) -------------------------------------------------------------------------------- /humanoidverse/simulator/isaacsim/isaacsim_articulation_cfg.py: -------------------------------------------------------------------------------- 1 | 2 | import omni.isaac.lab.sim as sim_utils 3 | from omni.isaac.lab.actuators import ActuatorNetMLPCfg, DCMotorCfg, ImplicitActuatorCfg 4 | from omni.isaac.lab.assets.articulation import ArticulationCfg 5 | from omni.isaac.lab.utils.assets import ISAACLAB_NUCLEUS_DIR 6 | 7 | ARTICULATION_CFG = ArticulationCfg( 8 | spawn=sim_utils.UsdFileCfg( 9 | # usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/Unitree/H1/h1.usd", 10 | usd_path="humanoidverse/data/robots/h1/h1.usd", 11 | activate_contact_sensors=True, 12 | rigid_props=sim_utils.RigidBodyPropertiesCfg( 13 | disable_gravity=False, 14 | retain_accelerations=False, 15 | linear_damping=0.0, 16 | angular_damping=0.0, 17 | max_linear_velocity=1000.0, 18 | max_angular_velocity=1000.0, 19 | max_depenetration_velocity=1.0, 20 | ), 21 | articulation_props=sim_utils.ArticulationRootPropertiesCfg( 22 | enabled_self_collisions=False, solver_position_iteration_count=4, solver_velocity_iteration_count=4 23 | ), 24 | ), 25 | init_state=ArticulationCfg.InitialStateCfg( 26 | pos=(0.0, 0.0, 1.05), 27 | joint_pos={ 28 | ".*_hip_yaw_joint": 0.0, 29 | ".*_hip_roll_joint": 0.0, 30 | ".*_hip_pitch_joint": -0.28, # -16 degrees 31 | ".*_knee_joint": 0.79, # 45 degrees 32 | ".*_ankle_joint": -0.52, # -30 degrees 33 | "torso_joint": 0.0, 34 | ".*_shoulder_pitch_joint": 0.28, 35 | ".*_shoulder_roll_joint": 0.0, 36 | ".*_shoulder_yaw_joint": 0.0, 37 | ".*_elbow_joint": 0.52, 38 | }, 39 | joint_vel={".*": 0.0}, 40 | ), 41 | soft_joint_pos_limit_factor=0.9, 42 | actuators={ 43 | "legs": ImplicitActuatorCfg( 44 | joint_names_expr=[".*_hip_yaw_joint", ".*_hip_roll_joint", ".*_hip_pitch_joint", ".*_knee_joint", "torso_joint"], 45 | effort_limit=300, 46 | velocity_limit=100.0, 47 | stiffness={ 48 | ".*_hip_yaw_joint": 150.0, 49 | ".*_hip_roll_joint": 150.0, 50 | ".*_hip_pitch_joint": 200.0, 51 | ".*_knee_joint": 200.0, 52 | "torso_joint": 200.0, 53 | }, 54 | damping={ 55 | ".*_hip_yaw_joint": 5.0, 56 | ".*_hip_roll_joint": 5.0, 57 | ".*_hip_pitch_joint": 5.0, 58 | ".*_knee_joint": 5.0, 59 | "torso_joint": 5.0, 60 | }, 61 | ), 62 | "feet": ImplicitActuatorCfg( 63 | joint_names_expr=[".*_ankle_joint"], 64 | effort_limit=100, 65 | velocity_limit=100.0, 66 | stiffness={".*_ankle_joint": 20.0}, 67 | damping={".*_ankle_joint": 4.0}, 68 | ), 69 | "arms": ImplicitActuatorCfg( 70 | joint_names_expr=[".*_shoulder_pitch_joint", ".*_shoulder_roll_joint", ".*_shoulder_yaw_joint", ".*_elbow_joint"], 71 | effort_limit=300, 72 | velocity_limit=100.0, 73 | stiffness={ 74 | ".*_shoulder_pitch_joint": 40.0, 75 | ".*_shoulder_roll_joint": 40.0, 76 | ".*_shoulder_yaw_joint": 40.0, 77 | ".*_elbow_joint": 40.0, 78 | }, 79 | damping={ 80 | ".*_shoulder_pitch_joint": 10.0, 81 | ".*_shoulder_roll_joint": 10.0, 82 | ".*_shoulder_yaw_joint": 10.0, 83 | ".*_elbow_joint": 10.0, 84 | }, 85 | ), 86 | }, 87 | ) -------------------------------------------------------------------------------- /humanoidverse/train_agent.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from pathlib import Path 4 | 5 | import hydra 6 | from hydra.core.hydra_config import HydraConfig 7 | from hydra.core.config_store import ConfigStore 8 | from hydra.utils import instantiate 9 | from omegaconf import OmegaConf 10 | 11 | import logging 12 | from loguru import logger 13 | 14 | 15 | 16 | 17 | from utils.config_utils import * # noqa: E402, F403 18 | 19 | 20 | @hydra.main(config_path="config", config_name="base", version_base="1.1") 21 | def main(config: OmegaConf): 22 | # import ipdb; ipdb.set_trace() 23 | simulator_type = config.simulator['_target_'].split('.')[-1] 24 | # import ipdb; ipdb.set_trace() 25 | if simulator_type == 'IsaacSim': 26 | from omni.isaac.lab.app import AppLauncher 27 | import argparse 28 | parser = argparse.ArgumentParser(description="Train an RL agent with RSL-RL.") 29 | AppLauncher.add_app_launcher_args(parser) 30 | 31 | args_cli, hydra_args = parser.parse_known_args() 32 | sys.argv = [sys.argv[0]] + hydra_args 33 | args_cli.num_envs = config.num_envs 34 | args_cli.seed = config.seed 35 | args_cli.env_spacing = config.env.config.env_spacing # config.env_spacing 36 | args_cli.output_dir = config.output_dir 37 | args_cli.headless = config.headless 38 | 39 | app_launcher = AppLauncher(args_cli) 40 | simulation_app = app_launcher.app 41 | 42 | # import ipdb; ipdb.set_trace() 43 | if simulator_type == 'IsaacGym': 44 | import isaacgym # noqa: F401 45 | 46 | 47 | # have to import torch after isaacgym 48 | import torch # noqa: E402 49 | from utils.common import seeding 50 | import wandb 51 | from humanoidverse.envs.base_task.base_task import BaseTask # noqa: E402 52 | from humanoidverse.agents.base_algo.base_algo import BaseAlgo # noqa: E402 53 | from humanoidverse.utils.helpers import pre_process_config 54 | from humanoidverse.utils.logging import HydraLoggerBridge 55 | 56 | # resolve=False is important otherwise overrides 57 | # at inference time won't work properly 58 | # also, I believe this must be done before instantiation 59 | 60 | # logging to hydra log file 61 | hydra_log_path = os.path.join(HydraConfig.get().runtime.output_dir, "train.log") 62 | logger.remove() 63 | logger.add(hydra_log_path, level="DEBUG") 64 | 65 | # Get log level from LOGURU_LEVEL environment variable or use INFO as default 66 | console_log_level = os.environ.get("LOGURU_LEVEL", "INFO").upper() 67 | logger.add(sys.stdout, level=console_log_level, colorize=True) 68 | 69 | logging.basicConfig(level=logging.DEBUG) 70 | logging.getLogger().addHandler(HydraLoggerBridge()) 71 | 72 | unresolved_conf = OmegaConf.to_container(config, resolve=False) 73 | os.chdir(hydra.utils.get_original_cwd()) 74 | 75 | if config.use_wandb: 76 | project_name = f"{config.project_name}" 77 | run_name = f"{config.timestamp}_{config.experiment_name}_{config.log_task_name}_{config.robot.asset.robot_type}" 78 | wandb_dir = Path(config.wandb.wandb_dir) 79 | wandb_dir.mkdir(exist_ok=True, parents=True) 80 | logger.info(f"Saving wandb logs to {wandb_dir}") 81 | wandb.init(project=project_name, 82 | entity=config.wandb.wandb_entity, 83 | name=run_name, 84 | sync_tensorboard=True, 85 | config=unresolved_conf, 86 | dir=wandb_dir) 87 | 88 | if hasattr(config, 'device'): 89 | if config.device is not None: 90 | device = config.device 91 | else: 92 | device = "cuda:0" if torch.cuda.is_available() else "cpu" 93 | else: 94 | device = "cuda:0" if torch.cuda.is_available() else "cpu" 95 | 96 | pre_process_config(config) 97 | 98 | # torch.set_float32_matmul_precision("medium") 99 | 100 | # fabric: Fabric = instantiate(config.fabric) 101 | # fabric.launch() 102 | 103 | # if config.seed is not None: 104 | # rank = fabric.global_rank 105 | # if rank is None: 106 | # rank = 0 107 | # fabric.seed_everything(config.seed + rank) 108 | # seeding(config.seed + rank, torch_deterministic=config.torch_deterministic) 109 | config.env.config.save_rendering_dir = str(Path(config.experiment_dir) / "renderings_training") 110 | env: BaseEnv = instantiate(config=config.env, device=device) 111 | 112 | 113 | experiment_save_dir = Path(config.experiment_dir) 114 | experiment_save_dir.mkdir(exist_ok=True, parents=True) 115 | 116 | logger.info(f"Saving config file to {experiment_save_dir}") 117 | with open(experiment_save_dir / "config.yaml", "w") as file: 118 | OmegaConf.save(unresolved_conf, file) 119 | 120 | algo: BaseAlgo = instantiate(device=device, env=env, config=config.algo, log_dir=experiment_save_dir) 121 | algo.setup() 122 | # import ipdb; ipdb.set_trace() 123 | if config.checkpoint is not None: 124 | algo.load(config.checkpoint) 125 | 126 | # handle saving config 127 | algo.learn() 128 | 129 | if simulator_type == 'IsaacSim': 130 | simulation_app.close() 131 | 132 | if __name__ == "__main__": 133 | main() 134 | -------------------------------------------------------------------------------- /humanoidverse/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/utils/__init__.py -------------------------------------------------------------------------------- /humanoidverse/utils/average_meters.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | import torch.nn as nn 4 | 5 | 6 | class AverageMeter(nn.Module): 7 | def __init__(self, in_shape, max_size): 8 | super(AverageMeter, self).__init__() 9 | self.max_size = max_size 10 | self.current_size = 0 11 | self.register_buffer("mean", torch.zeros(in_shape, dtype=torch.float32)) 12 | 13 | def update(self, values): 14 | size = values.size()[0] 15 | if size == 0: 16 | return 17 | new_mean = torch.mean(values.float(), dim=0) 18 | size = np.clip(size, 0, self.max_size) 19 | old_size = min(self.max_size - size, self.current_size) 20 | size_sum = old_size + size 21 | self.current_size = size_sum 22 | self.mean = (self.mean * old_size + new_mean * size) / size_sum 23 | 24 | def clear(self): 25 | self.current_size = 0 26 | self.mean.fill_(0) 27 | 28 | def __len__(self): 29 | return self.current_size 30 | 31 | def get_mean(self): 32 | return self.mean.squeeze(0).cpu().numpy() 33 | 34 | 35 | class TensorAverageMeter: 36 | def __init__(self): 37 | self.tensors = [] 38 | 39 | def add(self, x): 40 | if len(x.shape) == 0: 41 | x = x.unsqueeze(0) 42 | self.tensors.append(x) 43 | 44 | def mean(self): 45 | if len(self.tensors) == 0: 46 | return 0 47 | cat = torch.cat(self.tensors, dim=0) 48 | if cat.numel() == 0: 49 | return 0 50 | else: 51 | return cat.mean() 52 | 53 | def clear(self): 54 | self.tensors = [] 55 | 56 | def mean_and_clear(self): 57 | mean = self.mean() 58 | self.clear() 59 | return mean 60 | 61 | 62 | class TensorAverageMeterDict: 63 | def __init__(self): 64 | self.data = {} 65 | 66 | def add(self, data_dict): 67 | for k, v in data_dict.items(): 68 | # Originally used a defaultdict, this had lambda 69 | # pickling issues with DDP. 70 | if k not in self.data: 71 | self.data[k] = TensorAverageMeter() 72 | self.data[k].add(v) 73 | 74 | def mean(self): 75 | mean_dict = {k: v.mean() for k, v in self.data.items()} 76 | return mean_dict 77 | 78 | def clear(self): 79 | self.data = {} 80 | 81 | def mean_and_clear(self): 82 | mean = self.mean() 83 | self.clear() 84 | return mean -------------------------------------------------------------------------------- /humanoidverse/utils/common.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-2022, NVIDIA Corporation 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its 15 | # contributors may be used to endorse or promote products derived from 16 | # this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import argparse 30 | import os 31 | import random 32 | import sys 33 | from datetime import datetime 34 | 35 | import numpy as np 36 | import torch 37 | 38 | 39 | # if there's overlap between args_list and commandline input, use commandline input 40 | def solve_argv_conflict(args_list): 41 | arguments_to_be_removed = [] 42 | arguments_size = [] 43 | 44 | for argv in sys.argv[1:]: 45 | if argv.startswith("-"): 46 | size_count = 1 47 | for i, args in enumerate(args_list): 48 | if args == argv: 49 | arguments_to_be_removed.append(args) 50 | for more_args in args_list[i + 1 :]: 51 | if not more_args.startswith("-"): 52 | size_count += 1 53 | else: 54 | break 55 | arguments_size.append(size_count) 56 | break 57 | 58 | for args, size in zip(arguments_to_be_removed, arguments_size): 59 | args_index = args_list.index(args) 60 | for _ in range(size): 61 | args_list.pop(args_index) 62 | 63 | 64 | def print_error(*message): 65 | print("\033[91m", "ERROR ", *message, "\033[0m") 66 | raise RuntimeError 67 | 68 | 69 | def print_ok(*message): 70 | print("\033[92m", *message, "\033[0m") 71 | 72 | 73 | def print_warning(*message): 74 | print("\033[93m", *message, "\033[0m") 75 | 76 | 77 | def print_info(*message): 78 | print("\033[96m", *message, "\033[0m") 79 | 80 | 81 | def get_time_stamp(): 82 | now = datetime.now() 83 | year = now.strftime("%Y") 84 | month = now.strftime("%m") 85 | day = now.strftime("%d") 86 | hour = now.strftime("%H") 87 | minute = now.strftime("%M") 88 | second = now.strftime("%S") 89 | return "{}-{}-{}-{}-{}-{}".format(month, day, year, hour, minute, second) 90 | 91 | 92 | def parse_model_args(model_args_path): 93 | fp = open(model_args_path, "r") 94 | model_args = eval(fp.read()) 95 | model_args = argparse.Namespace(**model_args) 96 | 97 | return model_args 98 | 99 | 100 | def seeding(seed=0, torch_deterministic=False): 101 | print("Setting seed: {}".format(seed)) 102 | 103 | random.seed(seed) 104 | np.random.seed(seed) 105 | torch.manual_seed(seed) 106 | os.environ["PYTHONHASHSEED"] = str(seed) 107 | torch.cuda.manual_seed(seed) 108 | torch.cuda.manual_seed_all(seed) 109 | 110 | if torch_deterministic: 111 | # refer to https://docs.nvidia.com/cuda/cublas/index.html#cublasApi_reproducibility 112 | os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" 113 | torch.backends.cudnn.benchmark = False 114 | torch.backends.cudnn.deterministic = True 115 | torch.use_deterministic_algorithms(True) 116 | else: 117 | torch.backends.cudnn.benchmark = True 118 | torch.backends.cudnn.deterministic = False 119 | 120 | return seed 121 | 122 | 123 | def distance_l2(root_pos, wp_pos): 124 | return torch.norm(wp_pos - root_pos, dim=0) 125 | 126 | 127 | def value_to_color(value, min_value, max_value): 128 | """ 129 | Converts a numerical value to an RGB color. 130 | The color will range from blue (low values) to red (high values). 131 | """ 132 | # Ensure value is within the range [0, max_value] 133 | value = max(min_value, min(value, max_value)) 134 | 135 | # Calculate the proportion of the value 136 | red = (value - min_value) / (max_value - min_value) 137 | 138 | # Map the proportion to the red channel for a red gradient 139 | # Blue for minimum value and red for maximum value 140 | blue = 1 - red 141 | green = 0 # Keep green constant for simplicity 142 | 143 | # Return the RGB color 144 | return red, green, blue 145 | -------------------------------------------------------------------------------- /humanoidverse/utils/config_utils.py: -------------------------------------------------------------------------------- 1 | import math 2 | from loguru import logger 3 | from omegaconf import OmegaConf 4 | 5 | try: 6 | OmegaConf.register_new_resolver("eval", eval) 7 | OmegaConf.register_new_resolver("if", lambda pred, a, b: a if pred else b) 8 | OmegaConf.register_new_resolver("eq", lambda x, y: x.lower() == y.lower()) 9 | OmegaConf.register_new_resolver("sqrt", lambda x: math.sqrt(float(x))) 10 | OmegaConf.register_new_resolver("sum", lambda x: sum(x)) 11 | OmegaConf.register_new_resolver("ceil", lambda x: math.ceil(x)) 12 | OmegaConf.register_new_resolver("int", lambda x: int(x)) 13 | OmegaConf.register_new_resolver("len", lambda x: len(x)) 14 | OmegaConf.register_new_resolver("sum_list", lambda lst: sum(lst)) 15 | except Exception as e: 16 | logger.warning(f"Warning: Some resolvers already registered: {e}") 17 | 18 | # OmegaConf.register_new_resolver("eval", eval) 19 | # OmegaConf.register_new_resolver("if", lambda pred, a, b: a if pred else b) 20 | # OmegaConf.register_new_resolver("eq", lambda x, y: x.lower() == y.lower()) 21 | # OmegaConf.register_new_resolver("sqrt", lambda x: math.sqrt(float(x))) 22 | # OmegaConf.register_new_resolver("sum", lambda x: sum(x)) 23 | # OmegaConf.register_new_resolver("ceil", lambda x: math.ceil(x)) 24 | # OmegaConf.register_new_resolver("int", lambda x: int(x)) 25 | # OmegaConf.register_new_resolver("len", lambda x: len(x)) 26 | # OmegaConf.register_new_resolver("sum_list", lambda lst: sum(lst)) 27 | -------------------------------------------------------------------------------- /humanoidverse/utils/helpers.py: -------------------------------------------------------------------------------- 1 | import os 2 | import copy 3 | import torch 4 | from torch import nn 5 | import numpy as np 6 | import random 7 | 8 | from typing import Any, List, Dict 9 | from termcolor import colored 10 | from loguru import logger 11 | 12 | def class_to_dict(obj) -> dict: 13 | if not hasattr(obj,"__dict__"): 14 | return obj 15 | result = {} 16 | for key in dir(obj): 17 | if key.startswith("_"): 18 | continue 19 | element = [] 20 | val = getattr(obj, key) 21 | if isinstance(val, list): 22 | for item in val: 23 | element.append(class_to_dict(item)) 24 | else: 25 | element = class_to_dict(val) 26 | result[key] = element 27 | return result 28 | 29 | def pre_process_config(config) -> None: 30 | 31 | # compute observation_dim 32 | # config.robot.policy_obs_dim = -1 33 | # config.robot.critic_obs_dim = -1 34 | 35 | obs_dim_dict = dict() 36 | _obs_key_list = config.env.config.obs.obs_dict 37 | _aux_obs_key_list = config.env.config.obs.obs_auxiliary 38 | 39 | assert set(config.env.config.obs.noise_scales.keys()) == set(config.env.config.obs.obs_scales.keys()) 40 | 41 | # convert obs_dims to list of dicts 42 | each_dict_obs_dims = {k: v for d in config.env.config.obs.obs_dims for k, v in d.items()} 43 | config.env.config.obs.obs_dims = each_dict_obs_dims 44 | logger.info(f"obs_dims: {each_dict_obs_dims}") 45 | auxiliary_obs_dims = {} 46 | for aux_obs_key, aux_config in _aux_obs_key_list.items(): 47 | auxiliary_obs_dims[aux_obs_key] = 0 48 | for _key, _num in aux_config.items(): 49 | assert _key in config.env.config.obs.obs_dims.keys() 50 | auxiliary_obs_dims[aux_obs_key] += config.env.config.obs.obs_dims[_key] * _num 51 | logger.info(f"auxiliary_obs_dims: {auxiliary_obs_dims}") 52 | for obs_key, obs_config in _obs_key_list.items(): 53 | obs_dim_dict[obs_key] = 0 54 | for key in obs_config: 55 | if key.endswith("_raw"): key = key[:-4] 56 | if key in config.env.config.obs.obs_dims.keys(): 57 | obs_dim_dict[obs_key] += config.env.config.obs.obs_dims[key] 58 | logger.info(f"{obs_key}: {key} has dim: {config.env.config.obs.obs_dims[key]}") 59 | else: 60 | obs_dim_dict[obs_key] += auxiliary_obs_dims[key] 61 | logger.info(f"{obs_key}: {key} has dim: {auxiliary_obs_dims[key]}") 62 | config.robot.algo_obs_dim_dict = obs_dim_dict 63 | logger.info(f"algo_obs_dim_dict: {config.robot.algo_obs_dim_dict}") 64 | 65 | # compute action_dim for ppo 66 | # for agent in config.algo.config.network_dict.keys(): 67 | # for network in config.algo.config.network_dict[agent].keys(): 68 | # output_dim = config.algo.config.network_dict[agent][network].output_dim 69 | # if output_dim == "action_dim": 70 | # config.algo.config.network_dict[agent][network].output_dim = config.env.config.robot.actions_dim 71 | 72 | # print the config 73 | logger.debug(f"PPO CONFIG") 74 | logger.debug(f"{config.algo.config.module_dict}") 75 | # logger.debug(f"{config.algo.config.network_dict}") 76 | 77 | def parse_observation(cls: Any, 78 | key_list: List, 79 | buf_dict: Dict, 80 | obs_scales: Dict, 81 | noise_scales: Dict, 82 | current_noise_curriculum_value: Any) -> None: 83 | """ Parse observations for the legged_robot_base class 84 | """ 85 | 86 | for obs_key in key_list: 87 | if obs_key.endswith("_raw"): 88 | obs_key = obs_key[:-4] 89 | obs_noise = 0. 90 | else: 91 | obs_noise = noise_scales[obs_key] * current_noise_curriculum_value 92 | 93 | # print(f"obs_key: {obs_key}, obs_noise: {obs_noise}") 94 | 95 | actor_obs = getattr(cls, f"_get_obs_{obs_key}")().clone() 96 | obs_scale = obs_scales[obs_key] 97 | # Yuanhang: use rand_like (uniform 0-1) instead of randn_like (N~[0,1]) 98 | # buf_dict[obs_key] = actor_obs * obs_scale + (torch.randn_like(actor_obs)* 2. - 1.) * obs_noise 99 | # print("noise_scales", noise_scales) 100 | # print("obs_noise", obs_noise) 101 | buf_dict[obs_key] = (actor_obs + (torch.rand_like(actor_obs)* 2. - 1.) * obs_noise) * obs_scale 102 | 103 | 104 | def export_policy_as_jit(actor_critic, path): 105 | if hasattr(actor_critic, 'memory_a'): 106 | # assumes LSTM: TODO add GRU 107 | exporter = PolicyExporterLSTM(actor_critic) 108 | exporter.export(path) 109 | else: 110 | os.makedirs(path, exist_ok=True) 111 | path = os.path.join(path, 'policy_1.pt') 112 | model = copy.deepcopy(actor_critic.actor).to('cpu') 113 | traced_script_module = torch.jit.script(model) 114 | traced_script_module.save(path) 115 | 116 | class PolicyExporterLSTM(torch.nn.Module): 117 | def __init__(self, actor_critic): 118 | super().__init__() 119 | self.actor = copy.deepcopy(actor_critic.actor) 120 | self.is_recurrent = actor_critic.is_recurrent 121 | self.memory = copy.deepcopy(actor_critic.memory_a.rnn) 122 | self.memory.cpu() 123 | self.register_buffer(f'hidden_state', torch.zeros(self.memory.num_layers, 1, self.memory.hidden_size)) 124 | self.register_buffer(f'cell_state', torch.zeros(self.memory.num_layers, 1, self.memory.hidden_size)) 125 | 126 | def forward(self, x): 127 | out, (h, c) = self.memory(x.unsqueeze(0), (self.hidden_state, self.cell_state)) 128 | self.hidden_state[:] = h 129 | self.cell_state[:] = c 130 | return self.actor(out.squeeze(0)) 131 | 132 | @torch.jit.export 133 | def reset_memory(self): 134 | self.hidden_state[:] = 0. 135 | self.cell_state[:] = 0. 136 | 137 | def export(self, path): 138 | os.makedirs(path, exist_ok=True) 139 | path = os.path.join(path, 'policy_lstm_1.pt') 140 | self.to('cpu') 141 | traced_script_module = torch.jit.script(self) 142 | traced_script_module.save(path) 143 | -------------------------------------------------------------------------------- /humanoidverse/utils/inference_helpers.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | import os 4 | import copy 5 | 6 | def export_policy_as_jit(actor_critic, path, exported_policy_name): 7 | os.makedirs(path, exist_ok=True) 8 | path = os.path.join(path, exported_policy_name) 9 | model = copy.deepcopy(actor_critic.actor).to('cpu') 10 | traced_script_module = torch.jit.script(model) 11 | traced_script_module.save(path) 12 | 13 | def export_policy_as_onnx(inference_model, path, exported_policy_name, example_obs_dict): 14 | os.makedirs(path, exist_ok=True) 15 | path = os.path.join(path, exported_policy_name) 16 | 17 | actor = copy.deepcopy(inference_model['actor']).to('cpu') 18 | 19 | class PPOWrapper(nn.Module): 20 | def __init__(self, actor): 21 | """ 22 | model: The original PyTorch model. 23 | input_keys: List of input names as keys for the input dictionary. 24 | """ 25 | super(PPOWrapper, self).__init__() 26 | self.actor = actor 27 | 28 | def forward(self, actor_obs): 29 | """ 30 | Dynamically creates a dictionary from the input keys and args. 31 | """ 32 | return self.actor.act_inference(actor_obs) 33 | 34 | wrapper = PPOWrapper(actor) 35 | example_input_list = example_obs_dict["actor_obs"] 36 | torch.onnx.export( 37 | wrapper, 38 | example_input_list, # Pass x1 and x2 as separate inputs 39 | path, 40 | verbose=True, 41 | input_names=["actor_obs"], # Specify the input names 42 | output_names=["action"], # Name the output 43 | opset_version=13 # Specify the opset version, if needed 44 | ) 45 | 46 | def export_policy_and_estimator_as_onnx(inference_model, path, exported_policy_name, example_obs_dict): 47 | os.makedirs(path, exist_ok=True) 48 | path = os.path.join(path, exported_policy_name) 49 | 50 | actor = copy.deepcopy(inference_model['actor']).to('cpu') 51 | left_hand_force_estimator = copy.deepcopy(inference_model['left_hand_force_estimator']).to('cpu') 52 | right_hand_force_estimator = copy.deepcopy(inference_model['right_hand_force_estimator']).to('cpu') 53 | 54 | class PPOForceEstimatorWrapper(nn.Module): 55 | def __init__(self, actor, left_hand_force_estimator, right_hand_force_estimator): 56 | """ 57 | model: The original PyTorch model. 58 | input_keys: List of input names as keys for the input dictionary. 59 | """ 60 | super(PPOForceEstimatorWrapper, self).__init__() 61 | self.actor = actor 62 | self.left_hand_force_estimator = left_hand_force_estimator 63 | self.right_hand_force_estimator = right_hand_force_estimator 64 | 65 | def forward(self, inputs): 66 | """ 67 | Dynamically creates a dictionary from the input keys and args. 68 | """ 69 | actor_obs, history_for_estimator = inputs 70 | left_hand_force_estimator_output = self.left_hand_force_estimator(history_for_estimator) 71 | right_hand_force_estimator_output = self.right_hand_force_estimator(history_for_estimator) 72 | input_for_actor = torch.cat([actor_obs, left_hand_force_estimator_output, right_hand_force_estimator_output], dim=-1) 73 | return self.actor.act_inference(input_for_actor), left_hand_force_estimator_output, right_hand_force_estimator_output 74 | 75 | wrapper = PPOForceEstimatorWrapper(actor, left_hand_force_estimator, right_hand_force_estimator) 76 | example_input_list = [example_obs_dict["actor_obs"], example_obs_dict["long_history_for_estimator"]] 77 | torch.onnx.export( 78 | wrapper, 79 | example_input_list, # Pass x1 and x2 as separate inputs 80 | path, 81 | verbose=True, 82 | input_names=["actor_obs", "long_history_for_estimator"], # Specify the input names 83 | output_names=["action", "left_hand_force_estimator_output", "right_hand_force_estimator_output"], # Name the output 84 | opset_version=13 # Specify the opset version, if needed 85 | ) -------------------------------------------------------------------------------- /humanoidverse/utils/logging.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from loguru import logger 3 | from contextlib import contextmanager 4 | import sys 5 | import os 6 | 7 | class HydraLoggerBridge(logging.Handler): 8 | def emit(self, record): 9 | # Get corresponding loguru level 10 | try: 11 | level = logger.level(record.levelname).name 12 | except ValueError: 13 | level = record.levelno 14 | 15 | # Find caller from where the logged message originated 16 | frame, depth = logging.currentframe(), 2 17 | while frame and frame.f_code.co_filename == logging.__file__: 18 | frame = frame.f_back 19 | depth += 1 20 | 21 | logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage()) 22 | 23 | class LoguruStream: 24 | def write(self, message): 25 | if message.strip(): # Only log non-empty messages 26 | logger.info(message.strip()) # Changed to debug level 27 | 28 | def flush(self): 29 | pass 30 | 31 | @contextmanager 32 | def capture_stdout_to_loguru(): 33 | logger.remove() 34 | logger.add(sys.stdout, level="INFO") 35 | loguru_stream = LoguruStream() 36 | old_stdout = sys.stdout 37 | sys.stdout = loguru_stream 38 | try: 39 | yield 40 | finally: 41 | sys.stdout = old_stdout 42 | logger.remove() 43 | console_log_level = os.environ.get("LOGURU_LEVEL", "INFO").upper() 44 | logger.add(sys.stdout, level=console_log_level, colorize=True) -------------------------------------------------------------------------------- /humanoidverse/utils/math.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its 15 | # contributors may be used to endorse or promote products derived from 16 | # this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | # 29 | # Copyright (c) 2021 ETH Zurich, Nikita Rudin 30 | 31 | import torch 32 | from torch import Tensor 33 | import numpy as np 34 | from humanoidverse.utils.torch_utils import quat_apply, normalize 35 | from typing import Tuple 36 | 37 | # @ torch.jit.script 38 | def quat_apply_yaw(quat, vec): 39 | quat_yaw = quat.clone().view(-1, 4) 40 | quat_yaw[:, :2] = 0. 41 | quat_yaw = normalize(quat_yaw) 42 | return quat_apply(quat_yaw, vec) 43 | 44 | # @ torch.jit.script 45 | def wrap_to_pi(angles): 46 | angles %= 2*np.pi 47 | angles -= 2*np.pi * (angles > np.pi) 48 | return angles 49 | 50 | # @ torch.jit.script 51 | def torch_rand_sqrt_float(lower, upper, shape, device): 52 | # type: (float, float, Tuple[int, int], str) -> Tensor 53 | r = 2*torch.rand(*shape, device=device) - 1 54 | r = torch.where(r<0., -torch.sqrt(-r), torch.sqrt(r)) 55 | r = (r + 1.) / 2. 56 | return (upper - lower) * r + lower -------------------------------------------------------------------------------- /humanoidverse/utils/motion_lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/utils/motion_lib/__init__.py -------------------------------------------------------------------------------- /humanoidverse/utils/motion_lib/motion_lib_robot.py: -------------------------------------------------------------------------------- 1 | from humanoidverse.utils.motion_lib.motion_lib_base import MotionLibBase 2 | from humanoidverse.utils.motion_lib.torch_humanoid_batch import Humanoid_Batch 3 | class MotionLibRobot(MotionLibBase): 4 | def __init__(self, motion_lib_cfg, num_envs, device): 5 | super().__init__(motion_lib_cfg = motion_lib_cfg, num_envs = num_envs, device = device) 6 | self.mesh_parsers = Humanoid_Batch(motion_lib_cfg) 7 | return -------------------------------------------------------------------------------- /humanoidverse/utils/motion_lib/motion_utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/humanoidverse/utils/motion_lib/motion_utils/__init__.py -------------------------------------------------------------------------------- /humanoidverse/utils/motion_lib/motion_utils/flags.py: -------------------------------------------------------------------------------- 1 | __all__ = ['flags', 'summation'] 2 | 3 | class Flags(object): 4 | def __init__(self, items): 5 | for key, val in items.items(): 6 | setattr(self,key,val) 7 | 8 | flags = Flags({ 9 | 'test': False, 10 | 'debug': False, 11 | "real_traj": False, 12 | "im_eval": False, 13 | }) 14 | -------------------------------------------------------------------------------- /humanoidverse/utils/terrain.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from numpy.random import choice 3 | from scipy import interpolate 4 | 5 | from isaacgym import terrain_utils 6 | from legged_gym.envs.base.legged_robot_config import LeggedRobotCfg 7 | 8 | class Terrain: 9 | def __init__(self, cfg: LeggedRobotCfg.terrain, num_robots) -> None: 10 | 11 | self.cfg = cfg 12 | self.num_robots = num_robots 13 | self.type = cfg.mesh_type 14 | if self.type in ["none", 'plane']: 15 | return 16 | self.env_length = cfg.terrain_length 17 | self.env_width = cfg.terrain_width 18 | self.proportions = [np.sum(cfg.terrain_proportions[:i+1]) for i in range(len(cfg.terrain_proportions))] 19 | 20 | self.cfg.num_sub_terrains = cfg.num_rows * cfg.num_cols 21 | self.env_origins = np.zeros((cfg.num_rows, cfg.num_cols, 3)) 22 | 23 | self.width_per_env_pixels = int(self.env_width / cfg.horizontal_scale) 24 | self.length_per_env_pixels = int(self.env_length / cfg.horizontal_scale) 25 | 26 | self.border = int(cfg.border_size/self.cfg.horizontal_scale) 27 | self.tot_cols = int(cfg.num_cols * self.width_per_env_pixels) + 2 * self.border 28 | self.tot_rows = int(cfg.num_rows * self.length_per_env_pixels) + 2 * self.border 29 | 30 | self.height_field_raw = np.zeros((self.tot_rows , self.tot_cols), dtype=np.int16) 31 | if cfg.curriculum: 32 | self.curiculum() 33 | elif cfg.selected: 34 | self.selected_terrain() 35 | else: 36 | self.randomized_terrain() 37 | 38 | self.heightsamples = self.height_field_raw 39 | if self.type=="trimesh": 40 | self.vertices, self.triangles = terrain_utils.convert_heightfield_to_trimesh( self.height_field_raw, 41 | self.cfg.horizontal_scale, 42 | self.cfg.vertical_scale, 43 | self.cfg.slope_treshold) 44 | 45 | def randomized_terrain(self): 46 | for k in range(self.cfg.num_sub_terrains): 47 | # Env coordinates in the world 48 | (i, j) = np.unravel_index(k, (self.cfg.num_rows, self.cfg.num_cols)) 49 | 50 | choice = np.random.uniform(0, 1) 51 | difficulty = np.random.choice([0.5, 0.75, 0.9]) 52 | terrain = self.make_terrain(choice, difficulty) 53 | self.add_terrain_to_map(terrain, i, j) 54 | 55 | def curiculum(self): 56 | for j in range(self.cfg.num_cols): 57 | for i in range(self.cfg.num_rows): 58 | difficulty = i / self.cfg.num_rows 59 | choice = j / self.cfg.num_cols + 0.001 60 | 61 | terrain = self.make_terrain(choice, difficulty) 62 | self.add_terrain_to_map(terrain, i, j) 63 | 64 | def selected_terrain(self): 65 | terrain_type = self.cfg.terrain_kwargs.pop('type') 66 | for k in range(self.cfg.num_sub_terrains): 67 | # Env coordinates in the world 68 | (i, j) = np.unravel_index(k, (self.cfg.num_rows, self.cfg.num_cols)) 69 | 70 | terrain = terrain_utils.SubTerrain("terrain", 71 | width=self.width_per_env_pixels, 72 | length=self.width_per_env_pixels, 73 | vertical_scale=self.vertical_scale, 74 | horizontal_scale=self.horizontal_scale) 75 | 76 | eval(terrain_type)(terrain, **self.cfg.terrain_kwargs.terrain_kwargs) 77 | self.add_terrain_to_map(terrain, i, j) 78 | 79 | def make_terrain(self, choice, difficulty): 80 | terrain = terrain_utils.SubTerrain( "terrain", 81 | width=self.width_per_env_pixels, 82 | length=self.width_per_env_pixels, 83 | vertical_scale=self.cfg.vertical_scale, 84 | horizontal_scale=self.cfg.horizontal_scale) 85 | slope = difficulty * 0.4 86 | step_height = 0.05 + 0.18 * difficulty 87 | discrete_obstacles_height = 0.05 + difficulty * 0.2 88 | stepping_stones_size = 1.5 * (1.05 - difficulty) 89 | stone_distance = 0.05 if difficulty==0 else 0.1 90 | gap_size = 1. * difficulty 91 | pit_depth = 1. * difficulty 92 | if choice < self.proportions[0]: 93 | if choice < self.proportions[0]/ 2: 94 | slope *= -1 95 | terrain_utils.pyramid_sloped_terrain(terrain, slope=slope, platform_size=3.) 96 | elif choice < self.proportions[1]: 97 | terrain_utils.pyramid_sloped_terrain(terrain, slope=slope, platform_size=3.) 98 | terrain_utils.random_uniform_terrain(terrain, min_height=-0.05, max_height=0.05, step=0.005, downsampled_scale=0.2) 99 | elif choice < self.proportions[3]: 100 | if choice Tensor 148 | a = torch.tensor(a, device=b.device, dtype=torch.float).repeat(b.shape[0]) 149 | return torch.abs(a) * torch.sign(b) 150 | 151 | 152 | @torch.jit.script 153 | def get_euler_xyz(q): 154 | qx, qy, qz, qw = 0, 1, 2, 3 155 | # roll (x-axis rotation) 156 | sinr_cosp = 2.0 * (q[:, qw] * q[:, qx] + q[:, qy] * q[:, qz]) 157 | cosr_cosp = q[:, qw] * q[:, qw] - q[:, qx] * \ 158 | q[:, qx] - q[:, qy] * q[:, qy] + q[:, qz] * q[:, qz] 159 | roll = torch.atan2(sinr_cosp, cosr_cosp) 160 | 161 | # pitch (y-axis rotation) 162 | sinp = 2.0 * (q[:, qw] * q[:, qy] - q[:, qz] * q[:, qx]) 163 | pitch = torch.where(torch.abs(sinp) >= 1, copysign( 164 | np.pi / 2.0, sinp), torch.asin(sinp)) 165 | 166 | # yaw (z-axis rotation) 167 | siny_cosp = 2.0 * (q[:, qw] * q[:, qz] + q[:, qx] * q[:, qy]) 168 | cosy_cosp = q[:, qw] * q[:, qw] + q[:, qx] * \ 169 | q[:, qx] - q[:, qy] * q[:, qy] - q[:, qz] * q[:, qz] 170 | yaw = torch.atan2(siny_cosp, cosy_cosp) 171 | 172 | return roll % (2*np.pi), pitch % (2*np.pi), yaw % (2*np.pi) 173 | 174 | 175 | @torch.jit.script 176 | def quat_from_euler_xyz(roll, pitch, yaw): 177 | cy = torch.cos(yaw * 0.5) 178 | sy = torch.sin(yaw * 0.5) 179 | cr = torch.cos(roll * 0.5) 180 | sr = torch.sin(roll * 0.5) 181 | cp = torch.cos(pitch * 0.5) 182 | sp = torch.sin(pitch * 0.5) 183 | 184 | qw = cy * cr * cp + sy * sr * sp 185 | qx = cy * sr * cp - sy * cr * sp 186 | qy = cy * cr * sp + sy * sr * cp 187 | qz = sy * cr * cp - cy * sr * sp 188 | 189 | return torch.stack([qx, qy, qz, qw], dim=-1) 190 | 191 | 192 | @torch.jit.script 193 | def torch_rand_float(lower, upper, shape, device): 194 | # type: (float, float, Tuple[int, int], str) -> Tensor 195 | return (upper - lower) * torch.rand(*shape, device=device) + lower 196 | 197 | 198 | @torch.jit.script 199 | def torch_random_dir_2(shape, device): 200 | # type: (Tuple[int, int], str) -> Tensor 201 | angle = torch_rand_float(-np.pi, np.pi, shape, device).squeeze(-1) 202 | return torch.stack([torch.cos(angle), torch.sin(angle)], dim=-1) 203 | 204 | 205 | @torch.jit.script 206 | def tensor_clamp(t, min_t, max_t): 207 | return torch.max(torch.min(t, max_t), min_t) 208 | 209 | 210 | @torch.jit.script 211 | def scale(x, lower, upper): 212 | return (0.5 * (x + 1.0) * (upper - lower) + lower) 213 | 214 | 215 | @torch.jit.script 216 | def unscale(x, lower, upper): 217 | return (2.0 * x - upper - lower) / (upper - lower) 218 | 219 | 220 | def unscale_np(x, lower, upper): 221 | return (2.0 * x - upper - lower) / (upper - lower) 222 | -------------------------------------------------------------------------------- /imgs/CMU-NV-logo-crop-png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/imgs/CMU-NV-logo-crop-png.png -------------------------------------------------------------------------------- /imgs/motion_tracking_5800.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/imgs/motion_tracking_5800.gif -------------------------------------------------------------------------------- /isaac_utils/isaac_utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeCAR-Lab/ASAP/dc671beb62d0cff99f528528ac323ea45f1fbf74/isaac_utils/isaac_utils/__init__.py -------------------------------------------------------------------------------- /isaac_utils/isaac_utils/maths.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import numpy as np 3 | import random 4 | import os 5 | 6 | @torch.jit.script 7 | def normalize(x, eps: float = 1e-9): 8 | return x / x.norm(p=2, dim=-1).clamp(min=eps, max=None).unsqueeze(-1) 9 | 10 | @torch.jit.script 11 | def torch_rand_float(lower, upper, shape, device): 12 | # type: (float, float, Tuple[int, int], str) -> Tensor 13 | return (upper - lower) * torch.rand(*shape, device=device) + lower 14 | 15 | @torch.jit.script 16 | def copysign(a, b): 17 | # type: (float, Tensor) -> Tensor 18 | a = torch.tensor(a, device=b.device, dtype=torch.float).repeat(b.shape[0]) 19 | return torch.abs(a) * torch.sign(b) 20 | 21 | 22 | 23 | def set_seed(seed, torch_deterministic=False): 24 | """ set seed across modules """ 25 | if seed == -1 and torch_deterministic: 26 | seed = 42 27 | elif seed == -1: 28 | seed = np.random.randint(0, 10000) 29 | print("Setting seed: {}".format(seed)) 30 | 31 | random.seed(seed) 32 | np.random.seed(seed) 33 | torch.manual_seed(seed) 34 | os.environ["PYTHONHASHSEED"] = str(seed) 35 | torch.cuda.manual_seed(seed) 36 | torch.cuda.manual_seed_all(seed) 37 | 38 | if torch_deterministic: 39 | # refer to https://docs.nvidia.com/cuda/cublas/index.html#cublasApi_reproducibility 40 | os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" 41 | torch.backends.cudnn.benchmark = False 42 | torch.backends.cudnn.deterministic = True 43 | torch.use_deterministic_algorithms(True) 44 | else: 45 | torch.backends.cudnn.benchmark = True 46 | torch.backends.cudnn.deterministic = False 47 | 48 | return seed 49 | 50 | -------------------------------------------------------------------------------- /isaac_utils/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name="isaac_utils", 5 | packages=["isaac_utils"], 6 | version="0.0.1", 7 | description="Unified torch env_utils for IsaacGym and IsaacSim", 8 | author="", 9 | classifiers=[], 10 | ) -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | setup( 4 | name='asap', 5 | version='0.0.1', 6 | license="BSD-3-Clause", 7 | packages=find_packages(), 8 | description='ASAP: ligning Simulation and Real-World Physics for Learning Agile Humanoid Whole-Body Skills', 9 | url="https://github.com/LeCAR-Lab/ASAP", # Update this with your actual repository URL 10 | python_requires=">=3.8", 11 | install_requires=[ 12 | "hydra-core>=1.2.0", 13 | "numpy==1.23.5", 14 | "rich", 15 | "ipdb", 16 | "matplotlib", 17 | "termcolor", 18 | "wandb", 19 | "plotly", 20 | "tqdm", 21 | "loguru", 22 | "meshcat", 23 | "pynput", 24 | "scipy", 25 | "tensorboard", 26 | "onnx", 27 | "onnxruntime", 28 | "opencv-python", 29 | "joblib", 30 | "easydict", 31 | "lxml", 32 | "numpy-stl", 33 | "open3d" 34 | ] 35 | ) --------------------------------------------------------------------------------