├── .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 | )
--------------------------------------------------------------------------------