├── README.md ├── legged_gym ├── .gitattributes ├── .github │ └── ISSUE_TEMPLATE │ │ └── bug_report.md ├── .gitignore ├── LICENSE ├── README.md ├── legged_gym │ ├── __init__.py │ ├── envs │ │ ├── __init__.py │ │ ├── a1 │ │ │ └── a1_config.py │ │ ├── anymal_b │ │ │ └── anymal_b_config.py │ │ ├── anymal_c │ │ │ ├── anymal.py │ │ │ ├── flat │ │ │ │ └── anymal_c_flat_config.py │ │ │ └── mixed_terrains │ │ │ │ └── anymal_c_rough_config.py │ │ ├── base │ │ │ ├── base_config.py │ │ │ ├── base_task.py │ │ │ ├── legged_robot.py │ │ │ └── legged_robot_config.py │ │ ├── cassie │ │ │ ├── cassie.py │ │ │ └── cassie_config.py │ │ └── legged │ │ │ ├── a1 │ │ │ └── a1v2_config.py │ │ │ ├── base_config.py │ │ │ ├── base_task.py │ │ │ ├── legged_v2.py │ │ │ └── legged_v2_config.py │ ├── scripts │ │ ├── distill_v2_rsl.py │ │ ├── play.py │ │ ├── play_v2.py │ │ ├── play_v2_student.py │ │ ├── test_terrain.py │ │ ├── test_v2.py │ │ ├── train.py │ │ └── train_v2_rsl.py │ ├── sensors │ │ ├── floating_camera_sensor.py │ │ └── sensorbase.py │ ├── tests │ │ ├── data │ │ │ ├── contact.csv │ │ │ ├── contact_218.csv │ │ │ ├── gait_bad.csv │ │ │ ├── gait_good.csv │ │ │ └── gait_vel.csv │ │ ├── extract_frame.py │ │ ├── plot1.py │ │ ├── plot2.py │ │ ├── plot_Histogram.py │ │ ├── plot_RewardAblation copy.py │ │ ├── plot_gait.py │ │ └── test_env.py │ └── utils │ │ ├── __init__.py │ │ ├── barrier_track.py │ │ ├── console.py │ │ ├── gamepad_reader.py │ │ ├── helpers.py │ │ ├── logger.py │ │ ├── math.py │ │ ├── o3dviewer.py │ │ ├── perlin.py │ │ ├── task_registry.py │ │ ├── terrain.py │ │ ├── terrain_vls.py │ │ ├── trimesh.py │ │ ├── webviewer.html │ │ └── webviewer.py ├── licenses │ ├── assets │ │ ├── ANYmal_b_license.txt │ │ ├── ANYmal_c_license.txt │ │ ├── a1_license.txt │ │ └── cassie_license.txt │ └── dependencies │ │ └── matplotlib_license.txt ├── resources │ ├── actuator_nets │ │ └── anydrive_v3_lstm.pt │ ├── objects │ │ └── ball.urdf │ └── robots │ │ ├── a1 │ │ ├── a1_license.txt │ │ ├── meshes │ │ │ ├── calf.dae │ │ │ ├── hip.dae │ │ │ ├── thigh.dae │ │ │ ├── thigh_mirror.dae │ │ │ ├── trunk.dae │ │ │ └── trunk_A1.png │ │ └── urdf │ │ │ ├── a1.urdf │ │ │ └── a1cam.urdf │ │ ├── anymal_b │ │ ├── ANYmal_b_license.txt │ │ ├── meshes │ │ │ ├── anymal_base.dae │ │ │ ├── anymal_foot.dae │ │ │ ├── anymal_hip_l.dae │ │ │ ├── anymal_hip_r.dae │ │ │ ├── anymal_shank_l.dae │ │ │ ├── anymal_shank_r.dae │ │ │ ├── anymal_thigh_l.dae │ │ │ ├── anymal_thigh_r.dae │ │ │ ├── base_uv_texture.jpg │ │ │ └── carbon_uv_texture.jpg │ │ └── urdf │ │ │ └── anymal_b.urdf │ │ ├── anymal_c │ │ ├── ANYmal_c_license.txt │ │ ├── meshes │ │ │ ├── base.dae │ │ │ ├── base.jpg │ │ │ ├── battery.dae │ │ │ ├── battery.jpg │ │ │ ├── bottom_shell.dae │ │ │ ├── bottom_shell.jpg │ │ │ ├── depth_camera.dae │ │ │ ├── depth_camera.jpg │ │ │ ├── drive.dae │ │ │ ├── drive.jpg │ │ │ ├── face.dae │ │ │ ├── face.jpg │ │ │ ├── foot.dae │ │ │ ├── foot.jpg │ │ │ ├── handle.dae │ │ │ ├── handle.jpg │ │ │ ├── hatch.dae │ │ │ ├── hatch.jpg │ │ │ ├── hip.jpg │ │ │ ├── hip_l.dae │ │ │ ├── hip_r.dae │ │ │ ├── lidar.dae │ │ │ ├── lidar.jpg │ │ │ ├── lidar_cage.dae │ │ │ ├── lidar_cage.jpg │ │ │ ├── remote.dae │ │ │ ├── remote.jpg │ │ │ ├── shank.jpg │ │ │ ├── shank_l.dae │ │ │ ├── shank_r.dae │ │ │ ├── thigh.dae │ │ │ ├── thigh.jpg │ │ │ ├── top_shell.dae │ │ │ ├── top_shell.jpg │ │ │ ├── wide_angle_camera.dae │ │ │ └── wide_angle_camera.jpg │ │ └── urdf │ │ │ └── anymal_c.urdf │ │ └── cassie │ │ ├── cassie_license.txt │ │ ├── meshes │ │ ├── abduction.stl │ │ ├── abduction_mirror.stl │ │ ├── achilles-rod.stl │ │ ├── hip.stl │ │ ├── hip_mirror.stl │ │ ├── knee-output.stl │ │ ├── knee-output_mirror.stl │ │ ├── pelvis.stl │ │ ├── plantar-rod.stl │ │ ├── shin-bone.stl │ │ ├── shin-bone_mirror.stl │ │ ├── tarsus.stl │ │ ├── tarsus_mirror.stl │ │ ├── thigh.stl │ │ ├── thigh_mirror.stl │ │ ├── toe-output-crank.stl │ │ ├── toe.stl │ │ ├── toe_mirror.stl │ │ ├── torso.stl │ │ ├── yaw.stl │ │ └── yaw_mirror.stl │ │ └── urdf │ │ └── cassie.urdf └── setup.py ├── requirements.txt └── rsl_rl ├── .gitignore ├── LICENSE ├── README.md ├── licenses └── dependencies │ ├── numpy_license.txt │ └── torch_license.txt ├── rsl_rl ├── __init__.py ├── algorithms │ ├── __init__.py │ ├── ppo.py │ ├── ppo_rma.py │ ├── ppo_rma_blind.py │ └── ppo_rma_depth.py ├── env │ ├── __init__.py │ └── vec_env.py ├── modules │ ├── __init__.py │ ├── actor_critic.py │ ├── actor_critic_recurrent.py │ ├── actor_critic_rma.py │ ├── actor_critic_rma_blind.py │ ├── actor_critic_transformer.py │ └── depth_backbone.py ├── runners │ ├── __init__.py │ ├── on_policy_runner.py │ ├── on_policy_runner_depth.py │ └── on_policy_runner_wandb.py ├── storage │ ├── __init__.py │ └── rollout_storage.py └── utils │ ├── __init__.py │ └── utils.py └── setup.py /README.md: -------------------------------------------------------------------------------- 1 | # LEEPS: Learning End-to-End Legged Perceptive Parkour Skills on Challenging Terrains 2 | Website: https://sites.google.com/view/leeps
3 | Paper: Coming Soon
4 | 5 | ## Dependency 6 | [Isaac Gym](https://developer.nvidia.com/isaac-gym)
7 | [legged_gym](https://github.com/leggedrobotics/legged_gym)
8 | [rsl_rl](https://github.com/leggedrobotics/rsl_rl)
9 | 10 | ## Installation 11 | 1. Create a new python virtual env with python 3.6, 3.7 or 3.8 (3.8 recommended). i.e. with conda: 12 | - `conda create -n LEEPS python==3.8` 13 | - `conda activate LEEPS` 14 | 2. Install required packages: 15 | - `git clone https://github.com/P1terQ/LEEPS.git & cd LEEPS` 16 | - `pip install -r requirements.txt` 17 | 3. Install Isaac Gym 18 | - Download and install Isaac Gym Preview 3 (Preview 2 will not work!) from https://developer.nvidia.com/isaac-gym 19 | - `cd isaacgym/python && pip install -e .` 20 | - Try running an example `cd examples && python 1080_balls_of_solitude.py` 21 | - For troubleshooting check docs `isaacgym/docs/index.html` 22 | 4. Install rsl_rl (PPO implementation) 23 | - Clone this repository 24 | - `cd AMP_for_hardware/rsl_rl && pip install -e .` 25 | 5. Install legged_gym 26 | - `cd ../ && pip install -e .` 27 | 28 | ## Usage 29 | 1. Train teacher policy: 30 | ```python legged_gym/scripts/train_v2_rsl.py --task=a1_v2 --run_name xxx-xx ``` 31 | 1. Train student policy: 32 | ```python legged_gym/scripts/distill_v2_rsl.py --task=a1_v2 --run_name xxx-xx ``` 33 | 1. Play teacher policy: 34 | ```python legged_gym/scripts/play_v2.py --task=a1_v2 --load_run [weight_path] ``` 35 | 1. Play student policy: 36 | ```python legged_gym/scripts/play_v2_student.py --task=a1_v2 --load_run [weight_path] ``` 37 | 38 | ## Arguments 39 | - To run on CPU add the following arguments: `--sim_device=cpu`, `--rl_device=cpu` (sim on CPU and rl on GPU is possible). Default on GPU. 40 | - To run headless (no rendering) add `--headless`. 41 | - To improve performance, once the training starts press `v` to stop the rendering. You can then enable it later to check the progress. 42 | - The trained policy is saved in `LEEPS/weights//_/model_.pt`. Where `` and `` are defined in the train config. 43 | - --task TASK: Task name. 44 | - --resume: Resume training from a checkpoint 45 | - --experiment_name EXPERIMENT_NAME: Name of the experiment to run or load. 46 | - --run_name RUN_NAME: Name of the run. 47 | - --load_run LOAD_RUN: Name of the run to load when resume=True. If -1: will load the last run. 48 | - --checkpoint CHECKPOINT: Saved model checkpoint number. If -1: will load the last checkpoint. 49 | - --num_envs NUM_ENVS: Number of environments to create. 50 | - --seed SEED: Random seed. 51 | - --max_iterations MAX_ITERATIONS: Maximum number of training iterations. 52 | 53 | ## Robot Parkour 54 | https://github.com/P1terQ/LEEPS/assets/90088571/29a084a5-ff1d-4299-b0d9-a243bba4d1ca 55 | 56 | ## Acknowledgement 57 | This work was supported in part by the National Natural Science Foundation of China under Grant U2013601 and 62173314. 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /legged_gym/.gitattributes: -------------------------------------------------------------------------------- 1 | *.dae filter=lfs diff=lfs merge=lfs -text 2 | *.obj filter=lfs diff=lfs merge=lfs -text 3 | *.obj text !filter !merge !diff 4 | *.dae text !filter !merge !diff 5 | -------------------------------------------------------------------------------- /legged_gym/.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: nikitardn 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Execute `./path/script arg1 arg2` 16 | 1. Then ... 17 | 1. See error: ... 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **System (please complete the following information):** 23 | - Commit: [e.g. 8f3b9ca] 24 | - OS: [e.g. Ubuntu 20.04] 25 | - GPU: [e.g. RTX 2060 Super] 26 | - CUDA: [e.g. 11.4] 27 | - GPU Driver: [e.g. 470.82.01] 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /legged_gym/.gitignore: -------------------------------------------------------------------------------- 1 | # These are some examples of commonly ignored file patterns. 2 | # You should customize this list as applicable to your project. 3 | # Learn more about .gitignore: 4 | # https://www.atlassian.com/git/tutorials/saving-changes/gitignore 5 | 6 | # Node artifact files 7 | node_modules/ 8 | dist/ 9 | 10 | # Compiled Java class files 11 | *.class 12 | 13 | # Compiled Python bytecode 14 | *.py[cod] 15 | 16 | # Log files 17 | *.log 18 | 19 | # Package files 20 | *.jar 21 | 22 | # Maven 23 | target/ 24 | dist/ 25 | 26 | # JetBrains IDE 27 | .idea/ 28 | 29 | # Unit test reports 30 | TEST*.xml 31 | 32 | # Generated by MacOS 33 | .DS_Store 34 | 35 | # Generated by Windows 36 | Thumbs.db 37 | 38 | # Applications 39 | *.app 40 | *.exe 41 | *.war 42 | 43 | # Large media files 44 | *.mp4 45 | *.tiff 46 | *.avi 47 | *.flv 48 | *.mov 49 | *.wmv 50 | 51 | # VS Code 52 | .vscode 53 | # logs 54 | logs 55 | runs 56 | 57 | # other 58 | *.egg-info 59 | __pycache__ -------------------------------------------------------------------------------- /legged_gym/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021, ETH Zurich, Nikita Rudin 2 | Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | See licenses/assets for license information for assets included in this repository. 31 | See licenses/dependencies for license information of dependencies of this package. 32 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/__init__.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 os 32 | 33 | LEGGED_GYM_ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 34 | LEGGED_GYM_ENVS_DIR = os.path.join(LEGGED_GYM_ROOT_DIR, 'legged_gym', 'envs') -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/__init__.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 | from legged_gym import LEGGED_GYM_ROOT_DIR, LEGGED_GYM_ENVS_DIR 32 | from legged_gym.envs.a1.a1_config import A1RoughCfg, A1RoughCfgPPO 33 | from .base.legged_robot import LeggedRobot 34 | from .anymal_c.anymal import Anymal 35 | from .anymal_c.mixed_terrains.anymal_c_rough_config import AnymalCRoughCfg, AnymalCRoughCfgPPO 36 | from .anymal_c.flat.anymal_c_flat_config import AnymalCFlatCfg, AnymalCFlatCfgPPO 37 | from .anymal_b.anymal_b_config import AnymalBRoughCfg, AnymalBRoughCfgPPO 38 | from .cassie.cassie import Cassie 39 | from .cassie.cassie_config import CassieRoughCfg, CassieRoughCfgPPO 40 | from .a1.a1_config import A1RoughCfg, A1RoughCfgPPO 41 | 42 | from .legged.a1.a1v2_config import A1V2Cfg, A1V2CfgPPO 43 | from .legged.legged_v2 import LeggedV2 44 | 45 | import os 46 | 47 | from legged_gym.utils.task_registry import task_registry 48 | 49 | task_registry.register( "anymal_c_rough", Anymal, AnymalCRoughCfg(), AnymalCRoughCfgPPO() ) 50 | task_registry.register( "anymal_c_flat", Anymal, AnymalCFlatCfg(), AnymalCFlatCfgPPO() ) 51 | task_registry.register( "anymal_b", Anymal, AnymalBRoughCfg(), AnymalBRoughCfgPPO() ) 52 | task_registry.register( "a1", LeggedRobot, A1RoughCfg(), A1RoughCfgPPO() ) 53 | task_registry.register( "cassie", Cassie, CassieRoughCfg(), CassieRoughCfgPPO() ) 54 | 55 | task_registry.register( "a1_v2", LeggedV2, A1V2Cfg(), A1V2CfgPPO() ) 56 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/a1/a1_config.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 | from legged_gym.envs.base.legged_robot_config import LeggedRobotCfg, LeggedRobotCfgPPO 32 | 33 | class A1RoughCfg( LeggedRobotCfg ): 34 | class init_state( LeggedRobotCfg.init_state ): 35 | pos = [0.0, 0.0, 0.42] # x,y,z [m] 36 | default_joint_angles = { # = target angles [rad] when action = 0.0 37 | 'FL_hip_joint': 0.1, # [rad] 38 | 'RL_hip_joint': 0.1, # [rad] 39 | 'FR_hip_joint': -0.1 , # [rad] 40 | 'RR_hip_joint': -0.1, # [rad] 41 | 42 | 'FL_thigh_joint': 0.8, # [rad] 43 | 'RL_thigh_joint': 1., # [rad] 44 | 'FR_thigh_joint': 0.8, # [rad] 45 | 'RR_thigh_joint': 1., # [rad] 46 | 47 | 'FL_calf_joint': -1.5, # [rad] 48 | 'RL_calf_joint': -1.5, # [rad] 49 | 'FR_calf_joint': -1.5, # [rad] 50 | 'RR_calf_joint': -1.5, # [rad] 51 | } 52 | 53 | class control( LeggedRobotCfg.control ): 54 | # PD Drive parameters: 55 | control_type = 'P' 56 | stiffness = {'joint': 20.} # [N*m/rad] 57 | damping = {'joint': 0.5} # [N*m*s/rad] 58 | # action scale: target angle = actionScale * action + defaultAngle 59 | action_scale = 0.25 60 | # decimation: Number of control action updates @ sim DT per policy DT 61 | decimation = 4 62 | 63 | class asset( LeggedRobotCfg.asset ): 64 | file = '{LEGGED_GYM_ROOT_DIR}/resources/robots/a1/urdf/a1.urdf' 65 | name = "a1" 66 | foot_name = "foot" 67 | penalize_contacts_on = ["thigh", "calf"] 68 | terminate_after_contacts_on = ["base"] 69 | self_collisions = 1 # 1 to disable, 0 to enable...bitwise filter 70 | 71 | class rewards( LeggedRobotCfg.rewards ): 72 | soft_dof_pos_limit = 0.9 73 | base_height_target = 0.25 74 | class scales( LeggedRobotCfg.rewards.scales ): 75 | torques = -0.0002 76 | dof_pos_limits = -10.0 77 | 78 | class A1RoughCfgPPO( LeggedRobotCfgPPO ): 79 | class algorithm( LeggedRobotCfgPPO.algorithm ): 80 | entropy_coef = 0.01 81 | class runner( LeggedRobotCfgPPO.runner ): 82 | run_name = '' 83 | experiment_name = 'rough_a1' 84 | 85 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/anymal_b/anymal_b_config.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 | from legged_gym.envs import AnymalCRoughCfg, AnymalCRoughCfgPPO 32 | 33 | class AnymalBRoughCfg( AnymalCRoughCfg ): 34 | class asset( AnymalCRoughCfg.asset ): 35 | file = '{LEGGED_GYM_ROOT_DIR}/resources/robots/anymal_b/urdf/anymal_b.urdf' 36 | name = "anymal_b" 37 | foot_name = 'FOOT' 38 | class rewards( AnymalCRoughCfg.rewards ): 39 | class scales ( AnymalCRoughCfg.rewards.scales ): 40 | pass 41 | 42 | class AnymalBRoughCfgPPO( AnymalCRoughCfgPPO ): 43 | class runner ( AnymalCRoughCfgPPO.runner): 44 | run_name = '' 45 | experiment_name = 'rough_anymal_b' 46 | load_run = -1 -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/anymal_c/anymal.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 | from time import time 32 | import numpy as np 33 | import os 34 | 35 | from isaacgym.torch_utils import * 36 | from isaacgym import gymtorch, gymapi, gymutil 37 | 38 | import torch 39 | # from torch.tensor import Tensor 40 | from typing import Tuple, Dict 41 | 42 | from legged_gym.envs import LeggedRobot 43 | from legged_gym import LEGGED_GYM_ROOT_DIR 44 | from .mixed_terrains.anymal_c_rough_config import AnymalCRoughCfg 45 | 46 | class Anymal(LeggedRobot): 47 | cfg : AnymalCRoughCfg 48 | def __init__(self, cfg, sim_params, physics_engine, sim_device, headless): 49 | super().__init__(cfg, sim_params, physics_engine, sim_device, headless) 50 | 51 | # load actuator network 52 | if self.cfg.control.use_actuator_network: 53 | actuator_network_path = self.cfg.control.actuator_net_file.format(LEGGED_GYM_ROOT_DIR=LEGGED_GYM_ROOT_DIR) 54 | self.actuator_network = torch.jit.load(actuator_network_path).to(self.device) 55 | 56 | def reset_idx(self, env_ids): 57 | super().reset_idx(env_ids) 58 | # Additionaly empty actuator network hidden states 59 | self.sea_hidden_state_per_env[:, env_ids] = 0. 60 | self.sea_cell_state_per_env[:, env_ids] = 0. 61 | 62 | def _init_buffers(self): 63 | super()._init_buffers() 64 | # Additionally initialize actuator network hidden state tensors 65 | self.sea_input = torch.zeros(self.num_envs*self.num_actions, 1, 2, device=self.device, requires_grad=False) 66 | self.sea_hidden_state = torch.zeros(2, self.num_envs*self.num_actions, 8, device=self.device, requires_grad=False) 67 | self.sea_cell_state = torch.zeros(2, self.num_envs*self.num_actions, 8, device=self.device, requires_grad=False) 68 | self.sea_hidden_state_per_env = self.sea_hidden_state.view(2, self.num_envs, self.num_actions, 8) 69 | self.sea_cell_state_per_env = self.sea_cell_state.view(2, self.num_envs, self.num_actions, 8) 70 | 71 | def _compute_torques(self, actions): 72 | # Choose between pd controller and actuator network 73 | if self.cfg.control.use_actuator_network: 74 | with torch.inference_mode(): 75 | self.sea_input[:, 0, 0] = (actions * self.cfg.control.action_scale + self.default_dof_pos - self.dof_pos).flatten() 76 | self.sea_input[:, 0, 1] = self.dof_vel.flatten() 77 | torques, (self.sea_hidden_state[:], self.sea_cell_state[:]) = self.actuator_network(self.sea_input, (self.sea_hidden_state, self.sea_cell_state)) 78 | return torques 79 | else: 80 | # pd controller 81 | return super()._compute_torques(actions) -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/anymal_c/flat/anymal_c_flat_config.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 | from legged_gym.envs import AnymalCRoughCfg, AnymalCRoughCfgPPO 32 | 33 | class AnymalCFlatCfg( AnymalCRoughCfg ): 34 | class env( AnymalCRoughCfg.env ): 35 | num_observations = 48 36 | 37 | class terrain( AnymalCRoughCfg.terrain ): 38 | mesh_type = 'plane' 39 | measure_heights = False 40 | 41 | class asset( AnymalCRoughCfg.asset ): 42 | self_collisions = 0 # 1 to disable, 0 to enable...bitwise filter 43 | 44 | class rewards( AnymalCRoughCfg.rewards ): 45 | max_contact_force = 350. 46 | class scales ( AnymalCRoughCfg.rewards.scales ): 47 | orientation = -5.0 48 | torques = -0.000025 49 | feet_air_time = 2. 50 | # feet_contact_forces = -0.01 51 | 52 | class commands( AnymalCRoughCfg.commands ): 53 | heading_command = False 54 | resampling_time = 4. 55 | class ranges( AnymalCRoughCfg.commands.ranges ): 56 | ang_vel_yaw = [-1.5, 1.5] 57 | 58 | class domain_rand( AnymalCRoughCfg.domain_rand ): 59 | friction_range = [0., 1.5] # on ground planes the friction combination mode is averaging, i.e total friction = (foot_friction + 1.)/2. 60 | 61 | class AnymalCFlatCfgPPO( AnymalCRoughCfgPPO ): 62 | class policy( AnymalCRoughCfgPPO.policy ): 63 | actor_hidden_dims = [128, 64, 32] 64 | critic_hidden_dims = [128, 64, 32] 65 | activation = 'elu' # can be elu, relu, selu, crelu, lrelu, tanh, sigmoid 66 | 67 | class algorithm( AnymalCRoughCfgPPO.algorithm): 68 | entropy_coef = 0.01 69 | 70 | class runner ( AnymalCRoughCfgPPO.runner): 71 | run_name = '' 72 | experiment_name = 'flat_anymal_c' 73 | load_run = -1 74 | max_iterations = 300 75 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/anymal_c/mixed_terrains/anymal_c_rough_config.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 | from legged_gym.envs.base.legged_robot_config import LeggedRobotCfg, LeggedRobotCfgPPO 32 | 33 | class AnymalCRoughCfg( LeggedRobotCfg ): 34 | class env( LeggedRobotCfg.env ): 35 | num_envs = 4096 36 | num_actions = 12 37 | 38 | class terrain( LeggedRobotCfg.terrain ): 39 | mesh_type = 'trimesh' 40 | 41 | class init_state( LeggedRobotCfg.init_state ): 42 | pos = [0.0, 0.0, 0.6] # x,y,z [m] 43 | default_joint_angles = { # = target angles [rad] when action = 0.0 44 | "LF_HAA": 0.0, 45 | "LH_HAA": 0.0, 46 | "RF_HAA": -0.0, 47 | "RH_HAA": -0.0, 48 | 49 | "LF_HFE": 0.4, 50 | "LH_HFE": -0.4, 51 | "RF_HFE": 0.4, 52 | "RH_HFE": -0.4, 53 | 54 | "LF_KFE": -0.8, 55 | "LH_KFE": 0.8, 56 | "RF_KFE": -0.8, 57 | "RH_KFE": 0.8, 58 | } 59 | 60 | class control( LeggedRobotCfg.control ): 61 | # PD Drive parameters: 62 | stiffness = {'HAA': 80., 'HFE': 80., 'KFE': 80.} # [N*m/rad] 63 | damping = {'HAA': 2., 'HFE': 2., 'KFE': 2.} # [N*m*s/rad] 64 | # action scale: target angle = actionScale * action + defaultAngle 65 | action_scale = 0.5 66 | # decimation: Number of control action updates @ sim DT per policy DT 67 | decimation = 4 68 | use_actuator_network = True 69 | actuator_net_file = "{LEGGED_GYM_ROOT_DIR}/resources/actuator_nets/anydrive_v3_lstm.pt" 70 | 71 | class asset( LeggedRobotCfg.asset ): 72 | file = "{LEGGED_GYM_ROOT_DIR}/resources/robots/anymal_c/urdf/anymal_c.urdf" 73 | name = "anymal_c" 74 | foot_name = "FOOT" 75 | penalize_contacts_on = ["SHANK", "THIGH"] 76 | terminate_after_contacts_on = ["base"] 77 | self_collisions = 1 # 1 to disable, 0 to enable...bitwise filter 78 | 79 | class domain_rand( LeggedRobotCfg.domain_rand): 80 | randomize_base_mass = True 81 | added_mass_range = [-5., 5.] 82 | 83 | class rewards( LeggedRobotCfg.rewards ): 84 | base_height_target = 0.5 85 | max_contact_force = 500. 86 | only_positive_rewards = True 87 | class scales( LeggedRobotCfg.rewards.scales ): 88 | pass 89 | 90 | class AnymalCRoughCfgPPO( LeggedRobotCfgPPO ): 91 | class runner( LeggedRobotCfgPPO.runner ): 92 | run_name = '' 93 | experiment_name = 'rough_anymal_c' 94 | load_run = -1 95 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/base/base_config.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 inspect 32 | 33 | class BaseConfig: 34 | def __init__(self) -> None: 35 | """ Initializes all member classes recursively. Ignores all namse starting with '__' (buit-in methods).""" 36 | self.init_member_classes(self) 37 | 38 | @staticmethod 39 | def init_member_classes(obj): 40 | # iterate over all attributes names 41 | for key in dir(obj): 42 | # disregard builtin attributes 43 | # if key.startswith("__"): 44 | if key=="__class__": 45 | continue 46 | # get the corresponding attribute object 47 | var = getattr(obj, key) 48 | # check if it the attribute is a class 49 | if inspect.isclass(var): 50 | # instantate the class 51 | i_var = var() 52 | # set the attribute to the instance instead of the type 53 | setattr(obj, key, i_var) 54 | # recursively init members of the attribute 55 | BaseConfig.init_member_classes(i_var) -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/cassie/cassie.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 | from time import time 32 | import numpy as np 33 | import os 34 | 35 | from isaacgym.torch_utils import * 36 | from isaacgym import gymtorch, gymapi, gymutil 37 | 38 | import torch 39 | from typing import Tuple, Dict 40 | from legged_gym.envs import LeggedRobot 41 | 42 | class Cassie(LeggedRobot): 43 | def _reward_no_fly(self): 44 | contacts = self.contact_forces[:, self.feet_indices, 2] > 0.1 45 | single_contact = torch.sum(1.*contacts, dim=1)==1 46 | return 1.*single_contact -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/cassie/cassie_config.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 | from legged_gym.envs.base.legged_robot_config import LeggedRobotCfg, LeggedRobotCfgPPO 32 | 33 | class CassieRoughCfg( LeggedRobotCfg ): 34 | class env( LeggedRobotCfg.env): 35 | num_envs = 4096 36 | num_observations = 169 37 | num_actions = 12 38 | 39 | 40 | class terrain( LeggedRobotCfg.terrain): 41 | measured_points_x = [-0.5, -0.4, -0.3, -0.2, -0.1, 0., 0.1, 0.2, 0.3, 0.4, 0.5] # 1mx1m rectangle (without center line) 42 | measured_points_y = [-0.5, -0.4, -0.3, -0.2, -0.1, 0., 0.1, 0.2, 0.3, 0.4, 0.5] 43 | 44 | class init_state( LeggedRobotCfg.init_state ): 45 | pos = [0.0, 0.0, 1.] # x,y,z [m] 46 | default_joint_angles = { # = target angles [rad] when action = 0.0 47 | 'hip_abduction_left': 0.1, 48 | 'hip_rotation_left': 0., 49 | 'hip_flexion_left': 1., 50 | 'thigh_joint_left': -1.8, 51 | 'ankle_joint_left': 1.57, 52 | 'toe_joint_left': -1.57, 53 | 54 | 'hip_abduction_right': -0.1, 55 | 'hip_rotation_right': 0., 56 | 'hip_flexion_right': 1., 57 | 'thigh_joint_right': -1.8, 58 | 'ankle_joint_right': 1.57, 59 | 'toe_joint_right': -1.57 60 | } 61 | 62 | class control( LeggedRobotCfg.control ): 63 | # PD Drive parameters: 64 | stiffness = { 'hip_abduction': 100.0, 'hip_rotation': 100.0, 65 | 'hip_flexion': 200., 'thigh_joint': 200., 'ankle_joint': 200., 66 | 'toe_joint': 40.} # [N*m/rad] 67 | damping = { 'hip_abduction': 3.0, 'hip_rotation': 3.0, 68 | 'hip_flexion': 6., 'thigh_joint': 6., 'ankle_joint': 6., 69 | 'toe_joint': 1.} # [N*m*s/rad] # [N*m*s/rad] 70 | # action scale: target angle = actionScale * action + defaultAngle 71 | action_scale = 0.5 72 | # decimation: Number of control action updates @ sim DT per policy DT 73 | decimation = 4 74 | 75 | class asset( LeggedRobotCfg.asset ): 76 | file = '{LEGGED_GYM_ROOT_DIR}/resources/robots/cassie/urdf/cassie.urdf' 77 | name = "cassie" 78 | foot_name = 'toe' 79 | terminate_after_contacts_on = ['pelvis'] 80 | flip_visual_attachments = False 81 | self_collisions = 1 # 1 to disable, 0 to enable...bitwise filter 82 | 83 | class rewards( LeggedRobotCfg.rewards ): 84 | soft_dof_pos_limit = 0.95 85 | soft_dof_vel_limit = 0.9 86 | soft_torque_limit = 0.9 87 | max_contact_force = 300. 88 | only_positive_rewards = False 89 | class scales( LeggedRobotCfg.rewards.scales ): 90 | termination = -200. 91 | tracking_ang_vel = 1.0 92 | torques = -5.e-6 93 | dof_acc = -2.e-7 94 | lin_vel_z = -0.5 95 | feet_air_time = 5. 96 | dof_pos_limits = -1. 97 | no_fly = 0.25 98 | dof_vel = -0.0 99 | ang_vel_xy = -0.0 100 | feet_contact_forces = -0. 101 | 102 | class CassieRoughCfgPPO( LeggedRobotCfgPPO ): 103 | 104 | class runner( LeggedRobotCfgPPO.runner ): 105 | run_name = '' 106 | experiment_name = 'rough_cassie' 107 | 108 | class algorithm( LeggedRobotCfgPPO.algorithm): 109 | entropy_coef = 0.01 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/legged/a1/a1v2_config.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 | # from legged_gym.envs.terrainprimitive.legged_vls_config import LeggedVLSCfg, LeggedVLSCfgPPO 32 | from legged_gym.envs.legged.legged_v2_config import LeggedV2Cfg, LeggedV2CfgPPO 33 | 34 | class A1V2Cfg( LeggedV2Cfg ): 35 | class init_state( LeggedV2Cfg.init_state ): 36 | pos = [0.0, 0.0, 0.42] # x,y,z [m] 37 | default_joint_angles = { # = target angles [rad] when action = 0.0 38 | 'FL_hip_joint': 0.1, # [rad] 39 | 'RL_hip_joint': 0.1, # [rad] 40 | 'FR_hip_joint': -0.1 , # [rad] 41 | 'RR_hip_joint': -0.1, # [rad] 42 | 43 | 'FL_thigh_joint': 0.8, # [rad] 44 | 'RL_thigh_joint': 1., # [rad] 45 | 'FR_thigh_joint': 0.8, # [rad] 46 | 'RR_thigh_joint': 1., # [rad] 47 | 48 | 'FL_calf_joint': -1.5, # [rad] 49 | 'RL_calf_joint': -1.5, # [rad] 50 | 'FR_calf_joint': -1.5, # [rad] 51 | 'RR_calf_joint': -1.5, # [rad] 52 | } 53 | 54 | class control( LeggedV2Cfg.control ): 55 | control_type = 'P' 56 | stiffness = {'joint': 40.} # [N*m/rad] 57 | damping = {'joint': 1} # [N*m*s/rad] 58 | action_scale = 0.25 59 | decimation = 4 60 | 61 | class asset( LeggedV2Cfg.asset ): 62 | file = '{LEGGED_GYM_ROOT_DIR}/resources/robots/a1/urdf/a1cam.urdf' 63 | foot_name = "foot" 64 | penalize_contacts_on = ["thigh", "calf", "base"] 65 | terminate_after_contacts_on = ["base"]#, "thigh", "calf"] 66 | self_collisions = 1 # 1 to disable, 0 to enable...bitwise filter 67 | 68 | class rewards( LeggedV2Cfg.rewards ): 69 | soft_dof_pos_limit = 0.9 70 | base_height_target = 0.25 71 | 72 | class A1V2CfgPPO( LeggedV2CfgPPO ): 73 | class algorithm( LeggedV2CfgPPO.algorithm ): 74 | entropy_coef = 0.01 75 | class runner( LeggedV2CfgPPO.runner ): 76 | run_name = '' 77 | experiment_name = 'a1_v2' 78 | 79 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/envs/legged/base_config.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 inspect 32 | 33 | class BaseConfig: 34 | def __init__(self) -> None: 35 | """ Initializes all member classes recursively. Ignores all namse starting with '__' (buit-in methods).""" 36 | self.init_member_classes(self) 37 | 38 | @staticmethod 39 | def init_member_classes(obj): 40 | # iterate over all attributes names 41 | for key in dir(obj): 42 | # disregard builtin attributes 43 | # if key.startswith("__"): 44 | if key=="__class__": 45 | continue 46 | # get the corresponding attribute object 47 | var = getattr(obj, key) 48 | # check if it the attribute is a class 49 | if inspect.isclass(var): 50 | # instantate the class 51 | i_var = var() 52 | # set the attribute to the instance instead of the type 53 | setattr(obj, key, i_var) 54 | # recursively init members of the attribute 55 | BaseConfig.init_member_classes(i_var) -------------------------------------------------------------------------------- /legged_gym/legged_gym/scripts/distill_v2_rsl.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from datetime import datetime 4 | 5 | import isaacgym 6 | from legged_gym.envs import * 7 | from legged_gym.utils import get_args, task_registry 8 | # import torch 9 | import wandb 10 | from loguru import logger 11 | 12 | def train(args): 13 | env_cfg, train_cfg = task_registry.get_cfgs(args.task) 14 | 15 | # env_cfg.env.num_envs = 12 16 | # env_cfg.terrain.num_rows = max(2, env_cfg.terrain.max_init_terrain_level+1) 17 | # env_cfg.terrain.num_cols = 2 18 | 19 | current_dir = os.path.dirname(os.path.abspath(__file__)) 20 | root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir))) 21 | log_root = os.path.join(root_dir, 'logs', train_cfg.runner.experiment_name) 22 | log_dir = os.path.join(log_root, datetime.now().strftime('%b%d_%H-%M-%S') + '_' + args.run_name) 23 | os.makedirs(log_dir) 24 | 25 | wandb.init(project=args.task, 26 | name=args.run_name, 27 | entity="p1terq", 28 | group=args.run_name[:3], 29 | mode="online", 30 | dir=log_dir, 31 | config={ 32 | "ENV_CFG": vars(env_cfg), 33 | "TRAIN_CFG": vars(train_cfg) 34 | }) 35 | 36 | 37 | wandb.save("/home/ustc/robot/learning/iros2024/legged_gym/legged_gym/envs/terrainprimitive" + "/legged_vls_config.py", policy="now") 38 | wandb.save("/home/ustc/robot/learning/iros2024/legged_gym/legged_gym/envs/terrainprimitive" + "/legged_vls.py", policy="now") 39 | 40 | env, env_cfg = task_registry.make_env(name=args.task, args=args) 41 | ppo_runner, train_cfg = task_registry.make_alg_runner_rsl(env=env, name=args.task, args=args, log_dir_=log_dir) 42 | ppo_runner.learn(num_learning_iterations=train_cfg.runner.max_iterations, init_at_random_ep_len=True) 43 | 44 | if __name__ == '__main__': 45 | args = get_args() 46 | 47 | # args.headless = True 48 | args.task = 'a1_v2' # task选择任务的文件 49 | 50 | # args.run_name = '000-00' # run_name用来保存权重目录. 前3为表示group,后面为实验编号. 相同代码不同参数的实验为同一group 51 | 52 | args.use_camera = True 53 | args.delay = True 54 | args.resume = True 55 | 56 | # gap 57 | # args.load_run = '/home/ustc/robot/learning/iros2024/logs/a1_v2/Nov24_17-24-59_001-43' 58 | args.load_run = '/home/ustc/robot/learning/iros2024/logs/a1_v2/Dec02_20-28-03_001-78' 59 | 60 | if args.load_run == None: 61 | logger.warning(f'load_run must be specified when training student policy') 62 | raise ValueError('load_run must be specified') 63 | 64 | train(args) 65 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/scripts/play.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 | from legged_gym import LEGGED_GYM_ROOT_DIR 32 | import os 33 | 34 | import isaacgym 35 | from legged_gym.envs import * 36 | from legged_gym.utils import get_args, export_policy_as_jit, task_registry, Logger 37 | 38 | import numpy as np 39 | import torch 40 | 41 | 42 | def play(args): 43 | env_cfg, train_cfg = task_registry.get_cfgs(name=args.task) 44 | # override some parameters for testing 45 | env_cfg.env.num_envs = min(env_cfg.env.num_envs, 50) 46 | env_cfg.terrain.num_rows = 5 47 | env_cfg.terrain.num_cols = 5 48 | env_cfg.terrain.curriculum = False 49 | env_cfg.noise.add_noise = False 50 | env_cfg.domain_rand.randomize_friction = False 51 | env_cfg.domain_rand.push_robots = False 52 | 53 | # prepare environment 54 | env, _ = task_registry.make_env(name=args.task, args=args, env_cfg=env_cfg) 55 | obs = env.get_observations() 56 | # load policy 57 | train_cfg.runner.resume = True 58 | ppo_runner, train_cfg = task_registry.make_alg_runner(env=env, name=args.task, args=args, train_cfg=train_cfg) 59 | policy = ppo_runner.get_inference_policy(device=env.device) 60 | 61 | # export policy as a jit module (used to run it from C++) 62 | if EXPORT_POLICY: 63 | path = os.path.join(LEGGED_GYM_ROOT_DIR, 'logs', train_cfg.runner.experiment_name, 'exported', 'policies') 64 | export_policy_as_jit(ppo_runner.alg.actor_critic, path) 65 | print('Exported policy as jit script to: ', path) 66 | 67 | logger = Logger(env.dt) 68 | robot_index = 0 # which robot is used for logging 69 | joint_index = 1 # which joint is used for logging 70 | stop_state_log = 100 # number of steps before plotting states 71 | stop_rew_log = env.max_episode_length + 1 # number of steps before print average episode rewards 72 | camera_position = np.array(env_cfg.viewer.pos, dtype=np.float64) 73 | camera_vel = np.array([1., 1., 0.]) 74 | camera_direction = np.array(env_cfg.viewer.lookat) - np.array(env_cfg.viewer.pos) 75 | img_idx = 0 76 | 77 | for i in range(10*int(env.max_episode_length)): 78 | actions = policy(obs.detach()) 79 | obs, _, rews, dones, infos = env.step(actions.detach()) 80 | if RECORD_FRAMES: 81 | if i % 2: 82 | filename = os.path.join(LEGGED_GYM_ROOT_DIR, 'logs', train_cfg.runner.experiment_name, 'exported', 'frames', f"{img_idx}.png") 83 | env.gym.write_viewer_image_to_file(env.viewer, filename) 84 | img_idx += 1 85 | if MOVE_CAMERA: 86 | camera_position += camera_vel * env.dt 87 | env.set_camera(camera_position, camera_position + camera_direction) 88 | 89 | if i < stop_state_log: 90 | logger.log_states( 91 | { 92 | 'dof_pos_target': actions[robot_index, joint_index].item() * env.cfg.control.action_scale, 93 | 'dof_pos': env.dof_pos[robot_index, joint_index].item(), 94 | 'dof_vel': env.dof_vel[robot_index, joint_index].item(), 95 | 'dof_torque': env.torques[robot_index, joint_index].item(), 96 | 'command_x': env.commands[robot_index, 0].item(), 97 | 'command_y': env.commands[robot_index, 1].item(), 98 | 'command_yaw': env.commands[robot_index, 2].item(), 99 | 'base_vel_x': env.base_lin_vel[robot_index, 0].item(), 100 | 'base_vel_y': env.base_lin_vel[robot_index, 1].item(), 101 | 'base_vel_z': env.base_lin_vel[robot_index, 2].item(), 102 | 'base_vel_yaw': env.base_ang_vel[robot_index, 2].item(), 103 | 'contact_forces_z': env.contact_forces[robot_index, env.feet_indices, 2].cpu().numpy() 104 | } 105 | ) 106 | elif i==stop_state_log: 107 | logger.plot_states() 108 | if 0 < i < stop_rew_log: 109 | if infos["episode"]: 110 | num_episodes = torch.sum(env.reset_buf).item() 111 | if num_episodes>0: 112 | logger.log_rewards(infos["episode"], num_episodes) 113 | elif i==stop_rew_log: 114 | logger.print_rewards() 115 | 116 | if __name__ == '__main__': 117 | EXPORT_POLICY = True 118 | RECORD_FRAMES = False 119 | MOVE_CAMERA = False 120 | args = get_args() 121 | play(args) 122 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/scripts/play_v2.py: -------------------------------------------------------------------------------- 1 | from legged_gym import LEGGED_GYM_ROOT_DIR 2 | import os 3 | 4 | import isaacgym 5 | from legged_gym.envs import * 6 | from legged_gym.utils import get_args, export_policy_as_jit, task_registry, Logger 7 | 8 | import numpy as np 9 | import torch 10 | from legged_gym.utils import webviewer 11 | 12 | 13 | def play(args): 14 | 15 | if args.web: 16 | web_viewer = webviewer.WebViewer() 17 | 18 | 19 | env_cfg, train_cfg = task_registry.get_cfgs(name=args.task) 20 | 21 | # env_cfg.env.num_envs = 10 22 | # env_cfg.terrain.num_rows = 3 23 | # env_cfg.terrain.num_cols = 10 24 | # env_cfg.terrain.terrain_dict = { 25 | # "step": 0.1, # proportions[0] 26 | # "gap": 0.1, # proportions[1] 27 | # "slope": 0.1, 28 | # "stair": 0.1, 29 | # "pillar": 0.1, 30 | # "flat": 0.0, # proportions[5] 31 | # "steppingstones": 0.1, # proportions[6] 32 | # "crawl": 0.1, # proportions[7] 33 | # "log": 0.3, 34 | # "crack": 0.0, 35 | # "pyramid upstair": 0.0, 36 | # "pyramid gap": 0.0, 37 | # "simple_flat": 0.0 38 | # } 39 | env_cfg.env.num_envs = 1 40 | env_cfg.terrain.num_rows = 10 41 | env_cfg.terrain.num_cols = 1 42 | env_cfg.terrain.terrain_dict = { 43 | "step": 0.0, # proportions[0] 44 | "gap": 0.0, # proportions[1] 45 | "slope": 0.0, 46 | "stair": 0.0, 47 | "discrete": 0.0, 48 | "flat": 0.0, # proportions[5] 49 | "steppingstones": 1.0, # proportions[6] 50 | "crawl": 0.0, # proportions[7] 51 | "log": 0.0, 52 | "crack": 0.0, 53 | "dual": 0.0, 54 | "parkour": 0.0 55 | } 56 | env_cfg.terrain.curriculum = True 57 | 58 | # env_cfg.depth.camera_num_envs = 1 59 | # env_cfg.depth.camera_terrain_num_rows = 10 60 | # env_cfg.depth.camera_terrain_num_cols = 1 61 | 62 | #! 难度random,也可以在terrain中设置 63 | # env_cfg.terrain.num_rows = 1 64 | # env_cfg.terrain.num_cols = 1 65 | # env_cfg.env.num_envs = 1 66 | # env_cfg.terrain.border_size = 0.0 67 | # env_cfg.terrain.terrain_dict = { 68 | # "step": 0.0, # proportions[0] 69 | # "gap": 0.0, # proportions[1] 70 | # "slope": 0.0, 71 | # "stair": 0.0, 72 | # "pillar": 0.0, 73 | # "flat": 0.0, # proportions[5] 74 | # "steppingstones": 0.0, # proportions[6] 75 | # "crawl": 0.0, # proportions[7] 76 | # "log": 1.0, 77 | # "crack": 0.0, 78 | # "pyramid upstair": 0.0, 79 | # } 80 | # env_cfg.terrain.curriculum = False 81 | 82 | 83 | env_cfg.terrain.terrain_proportions = list(env_cfg.terrain.terrain_dict.values()) 84 | 85 | # prepare environment 86 | env, _ = task_registry.make_env(name=args.task, args=args, env_cfg=env_cfg) 87 | obs = env.get_observations() 88 | 89 | if args.web: 90 | web_viewer.setup(env) 91 | 92 | # load policy 93 | train_cfg.runner.resume = True 94 | ppo_runner, train_cfg = task_registry.make_alg_runner_rsl(env=env, name=args.task, args=args, train_cfg=train_cfg) 95 | policy = ppo_runner.get_inference_policy(device=env.device) 96 | 97 | 98 | for i in range(50*int(env.max_episode_length)): 99 | actions = policy(obs.detach()) 100 | obs, _, rews, dones, infos = env.step(actions.detach()) 101 | 102 | if args.web: 103 | web_viewer.render(fetch_results=True, 104 | step_graphics=True, 105 | render_all_camera_sensors=True, 106 | wait_for_page_load=True) 107 | 108 | 109 | if __name__ == '__main__': 110 | 111 | args = get_args() 112 | 113 | args.task = 'a1_v2' 114 | 115 | # args.debug_viz = True 116 | # args.remote = True 117 | # args.use_camera = True 118 | 119 | # args.load_run = '/home/ustc/robot/projects/legged_locomotion/iros2024/weights/a1_v2/Nov28_10-39-59_001-69' 120 | 121 | play(args) 122 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/scripts/play_v2_student.py: -------------------------------------------------------------------------------- 1 | from legged_gym import LEGGED_GYM_ROOT_DIR 2 | import os 3 | 4 | import isaacgym 5 | from legged_gym.envs import * 6 | from legged_gym.utils import get_args, export_policy_as_jit, task_registry, Logger 7 | 8 | import numpy as np 9 | import torch 10 | from loguru import logger 11 | 12 | import time 13 | 14 | 15 | def play(args): 16 | env_cfg, train_cfg = task_registry.get_cfgs(name=args.task) 17 | 18 | env_cfg.depth.camera_num_envs = 1 19 | env_cfg.depth.camera_terrain_num_rows = 10 20 | env_cfg.depth.camera_terrain_num_cols = 1 21 | env_cfg.terrain.terrain_dict = { 22 | "step": 0.0, # proportions[0] 23 | "gap": 0.0, # proportions[1] 24 | "slope": 0.0, 25 | "stair": 0.0, 26 | "pillar": 0.0, 27 | "flat": 0.0, # proportions[5] 28 | "steppingstones": 1.0, # proportions[6] 29 | "crawl": 0.0, # proportions[7] 30 | "log": 0.0, 31 | "crack": 0.0, 32 | "pyramid upstair": 0.0, 33 | "pyramid gap": 0.0, 34 | "simple_flat": 0.0 35 | } 36 | env_cfg.terrain.curriculum = True 37 | env_cfg.terrain.max_init_terrain_level = 1 38 | env_cfg.terrain.simplify_grid = False 39 | # env_cfg.terrain.curriculum = False 40 | 41 | env_cfg.terrain.terrain_proportions = list(env_cfg.terrain.terrain_dict.values()) 42 | # env_cfg.terrain.simplify_grid = False 43 | 44 | 45 | 46 | # prepare environment 47 | env: LeggedV2 48 | env, _ = task_registry.make_env(name=args.task, args=args, env_cfg=env_cfg) 49 | obs = env.get_observations() 50 | 51 | # load policy 52 | train_cfg.runner.resume = True 53 | ppo_runner, train_cfg = task_registry.make_alg_runner_rsl(env=env, name=args.task, args=args, train_cfg=train_cfg) 54 | # policy = ppo_runner.get_inference_policy(device=env.device) 55 | 56 | estimator = ppo_runner.get_estimator_inference_policy() 57 | 58 | terrain_depth_encoder = ppo_runner.get_terrain_depth_encoder_inference_policy() 59 | ceiling_depth_encoder = ppo_runner.get_ceiling_depth_encoder_inference_policy() 60 | 61 | infos = {} 62 | infos["depth"] = env.depth_buffer.clone().to(ppo_runner.device)[:, -1] if ppo_runner.if_depth else None # [1, 58, 87] 63 | 64 | 65 | for i in range(50*int(env.max_episode_length)): 66 | 67 | time1= time.time() 68 | # print("time1: ", time1) 69 | 70 | if infos["depth"] is not None: 71 | obs_student = obs[:, :env.cfg.env.n_proprio].clone() 72 | 73 | terrain_depth_latent_estimated = terrain_depth_encoder(infos["depth"], obs_student) 74 | ceiling_depth_latent_estimated = ceiling_depth_encoder(infos["depth"], obs_student) 75 | # else: 76 | # raise ValueError('depth is None') 77 | 78 | time2= time.time() 79 | # print("time2: ", time2) 80 | 81 | priv_selfstates_estimated = estimator(obs_student) 82 | obs[:, env.cfg.env.n_proprio+env.cfg.env.n_scan_terrain+env.cfg.env.n_scan_ceiling:env.cfg.env.n_proprio+env.cfg.env.n_scan_terrain+env.cfg.env.n_scan_ceiling+env.cfg.env.n_priv] = priv_selfstates_estimated 83 | 84 | if hasattr(ppo_runner.alg, "depth_actor"): 85 | actions = ppo_runner.alg.depth_actor(obs.detach(), 86 | use_historyestimate=True, 87 | terrain_scandots_latent=terrain_depth_latent_estimated, 88 | ceiling_scandots_latent=ceiling_depth_latent_estimated) 89 | else: 90 | raise ValueError('ppo_runner.alg.depth_actor is None') 91 | 92 | # time3= time.time() 93 | # print("time3: ", time3) 94 | # print("duration: ", time3-time1) 95 | 96 | # actions = policy(obs.detach()) 97 | obs, _, rews, dones, infos = env.step(actions.detach()) 98 | 99 | 100 | if __name__ == '__main__': 101 | EXPORT_POLICY = False 102 | RECORD_FRAMES = False 103 | MOVE_CAMERA = False 104 | args = get_args() 105 | 106 | args.task = 'a1_v2' 107 | args.debug_viz = True 108 | args.use_camera = True 109 | args.delay = True 110 | args.resume = True 111 | 112 | # args.remote = True 113 | 114 | # args.load_run = '/home/ustc/robot/projects/legged_locomotion/iros2024/weights/a1_v2/Dec05_10-35-14_002-09' 115 | 116 | if args.load_run == None: 117 | logger.warning(f'load_run must be specified when training student policy') 118 | raise ValueError('load_run must be specified') 119 | 120 | play(args) 121 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/scripts/test_terrain.py: -------------------------------------------------------------------------------- 1 | 2 | from isaacgym import gymapi, gymutil 3 | from legged_gym.utils.barrier_track import BarrierTrack 4 | from legged_gym.envs.a1.a1_config import A1RoughCfg 5 | import numpy as np 6 | 7 | class terrain(A1RoughCfg.terrain): 8 | mesh_type = "trimesh" # Don't change 9 | num_rows = 1 10 | num_cols = 1 11 | 12 | selected = "BarrierTrack" # "BarrierTrack" or "TerrainPerlin", "TerrainPerlin" can be used for training a walk policy. 13 | 14 | max_init_terrain_level = 0 15 | border_size = 0 16 | slope_treshold = 20. 17 | 18 | curriculum = False # for walk 19 | 20 | horizontal_scale = 0.025 # [m] 21 | # vertical_scale = 1. # [m] does not change the value in hightfield 22 | pad_unavailable_info = True 23 | 24 | #! track的参数 25 | BarrierTrack_kwargs = dict( 26 | options= [ 27 | "climb", 28 | "stairs", 29 | "stairs_down", 30 | "slope", 31 | "slope_down", 32 | "crawl", 33 | "tilt", 34 | "leap", 35 | "steppingstone", 36 | "flat" 37 | ], # each race track will permute all the options 38 | 39 | #! 一般都是true如果randomize_obstacle_order=False.最好只生成一个环境。里边包含所有的obstacle 40 | randomize_obstacle_order = False, 41 | n_obstacles_per_track = 10 + 1, # +1是start track 42 | 43 | track_width= 1.6, 44 | track_block_length= 2., # the x-axis distance from the env origin point 45 | 46 | # 每个cols之间的wall 47 | wall_thickness= (0.04, 0.2), # [m] 48 | wall_height= -0.05, 49 | # wall_thickness= 1.0, 50 | # wall_height= 1, 51 | 52 | climb= dict( 53 | height= (0.2, 0.6), 54 | depth= (0.1, 0.8), # size along the forward axis 55 | fake_offset= 0.0, # [m] an offset that make the robot easier to get into the obstacle 56 | climb_down_prob= 0.0, 57 | ), 58 | 59 | crawl= dict( 60 | height= (0.25, 0.5), 61 | depth= (0.1, 0.6), # size along the forward axis 62 | wall_height= 0.6, 63 | no_perlin_at_obstacle= False, 64 | ), 65 | 66 | tilt= dict( 67 | width= (0.24, 0.32), 68 | depth= (0.4, 1.), # size along the forward axis 69 | opening_angle= 0.0, # [rad] an opening that make the robot easier to get into the obstacle 70 | wall_height= 0.5, 71 | ), 72 | 73 | leap= dict( 74 | length= (0.2, 1.0), 75 | depth= (0.4, 0.8), 76 | height= 0.2, 77 | ), 78 | 79 | slope = dict( 80 | gradient = (0.2, 0.4), 81 | ), 82 | 83 | slope_down = dict( 84 | gradient = (-0.4, -0.2), 85 | ), 86 | 87 | stairs = dict( 88 | step_width = (0.3, 0.5), 89 | step_height = (0.1, 0.2) 90 | ), 91 | 92 | stairs_down = dict( 93 | step_width = (0.3, 0.5), 94 | step_height = (-0.2, -0.1) 95 | ), 96 | 97 | steppingstone = dict( 98 | stone_size = (0.2, 0.3), 99 | stone_distance = (0.1, 0.2), 100 | max_height = (0.05, 0.1), 101 | ), 102 | 103 | add_perlin_noise= True, #! add noise 104 | # add_perlin_noise= False, 105 | 106 | border_perlin_noise= True, 107 | 108 | border_height= 0., 109 | virtual_terrain= False, 110 | draw_virtual_terrain= True, 111 | engaging_next_threshold= 1.2, 112 | curriculum_perlin= False, 113 | no_perlin_threshold= 0.0, 114 | ) 115 | 116 | TerrainPerlin_kwargs = dict( 117 | zScale= [0.05, 0.1], 118 | # zScale= 0.1, # Use a constant zScale for training a walk policy 119 | frequency= 10, 120 | ) 121 | 122 | 123 | if __name__ == '__main__': 124 | gym = gymapi.acquire_gym() 125 | args = gymutil.parse_arguments() 126 | 127 | sim_params = gymapi.SimParams() 128 | sim_params.up_axis = gymapi.UpAxis.UP_AXIS_Z 129 | sim_params.gravity = gymapi.Vec3(0.0, 0.0, -9.81) 130 | 131 | args.physics_engine = gymapi.SIM_PHYSX 132 | sim_params.substeps = 2 133 | sim_params.physx.solver_type = 1 134 | sim_params.physx.num_position_iterations = 4 135 | sim_params.physx.num_velocity_iterations = 0 136 | sim_params.physx.num_threads = args.num_threads 137 | sim_params.physx.use_gpu = args.use_gpu 138 | 139 | sim = gym.create_sim(args.compute_device_id, args.graphics_device_id, args.physics_engine, sim_params) 140 | 141 | 142 | terrain_cfg = terrain() 143 | 144 | terrain_ = BarrierTrack(terrain_cfg, num_envs=0) 145 | 146 | terrain_.add_terrain_to_sim(gym, sim, device= "cpu") 147 | 148 | viewer = gym.create_viewer(sim, gymapi.CameraProperties()) 149 | 150 | cam_initpos = gymapi.Vec3(0, -2, 2.5) 151 | cam_inittarget = gymapi.Vec3(0, 0, 1) 152 | cam_direction = np.array(cam_inittarget) - np.array(cam_initpos) 153 | 154 | gym.viewer_camera_look_at(viewer, None, cam_initpos, cam_inittarget) 155 | 156 | dt = sim_params.dt 157 | cam_vel = np.array([1., 0., 0.]) 158 | cam_dpos = np.array([0. ,0. ,0. ]) 159 | 160 | while not gym.query_viewer_has_closed(viewer): 161 | # cam_dpos += cam_vel * dt 162 | # cam_pos = gymapi.Vec3(0+cam_dpos[0], -2+cam_dpos[1], 2.5+cam_dpos[2]) 163 | # cam_target = gymapi.Vec3(0+cam_dpos[0], 0+cam_dpos[1], 1+cam_dpos[2]) 164 | # gym.viewer_camera_look_at(viewer, None, cam_pos, cam_target) 165 | 166 | # step the physics 167 | gym.simulate(sim) 168 | gym.fetch_results(sim, True) 169 | 170 | # update the viewer 171 | gym.step_graphics(sim) 172 | gym.draw_viewer(viewer, sim, True) 173 | 174 | # Wait for dt to elapse in real time. 175 | # This synchronizes the physics simulation with the rendering rate. 176 | gym.sync_frame_time(sim) 177 | 178 | gym.destroy_viewer(viewer) 179 | gym.destroy_sim(sim) 180 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/scripts/test_v2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from datetime import datetime 4 | 5 | import isaacgym 6 | from legged_gym.envs import * 7 | from legged_gym.utils import get_args, export_policy_as_jit, task_registry, Logger 8 | 9 | import torch 10 | 11 | def test_env(args): 12 | env_cfg, train_cfg = task_registry.get_cfgs(name=args.task) 13 | 14 | # env_cfg.terrain.num_rows = max(2, env_cfg.terrain.max_init_terrain_level+1) #! 15 | # env_cfg.terrain.num_rows = 10 16 | # env_cfg.terrain.num_cols = 10 17 | env_cfg.terrain.num_rows = 10 #! 18 | env_cfg.terrain.num_cols = 1 19 | # env_cfg.env.num_envs = env_cfg.terrain.num_rpillar_xows * env_cfg.terrain.num_cols 20 | env_cfg.env.num_envs = 3 21 | env_cfg.terrain.max_init_terrain_level = 3 22 | 23 | env_cfg.terrain.border_size = 0.0 24 | env_cfg.terrain.terrain_dict = { 25 | "step": 0.0, # proportions[0] 26 | "gap": 0.0, # proportions[1] 27 | "slope": 0.0, 28 | "stair": 0.0, 29 | "discrete": 1.0, 30 | "flat": 0.0, # proportions[5] 31 | "steppingstones": 0.0, # proportions[6] 32 | "crawl": 0.0, # proportions[7] 33 | "log": 0.0, 34 | "crack": 0.0, 35 | "dual": 0.0, 36 | "parkour": 0.0 37 | } 38 | env_cfg.terrain.terrain_proportions = list(env_cfg.terrain.terrain_dict.values()) 39 | env_cfg.terrain.curriculum = True 40 | 41 | # prepare environment 42 | env, _ = task_registry.make_env(name=args.task, args=args, env_cfg=env_cfg) 43 | for i in range(int(1000*env.max_episode_length)): 44 | actions = 0.*torch.ones(env.num_envs, env.num_actions, device=env.device) 45 | obs, _, rew, done, info = env.step(actions) 46 | print("Done") 47 | 48 | if __name__ == '__main__': 49 | args = get_args() 50 | 51 | # choose task 52 | args.task = 'a1_v2' 53 | args.debug_viz = True 54 | 55 | test_env(args) 56 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/scripts/train.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 numpy as np 32 | import os 33 | from datetime import datetime 34 | 35 | import isaacgym 36 | from legged_gym.envs import * 37 | from legged_gym.utils import get_args, task_registry 38 | import torch 39 | 40 | def train(args): 41 | env, env_cfg = task_registry.make_env(name=args.task, args=args) 42 | ppo_runner, train_cfg = task_registry.make_alg_runner(env=env, name=args.task, args=args) 43 | ppo_runner.learn(num_learning_iterations=train_cfg.runner.max_iterations, init_at_random_ep_len=True) 44 | 45 | if __name__ == '__main__': 46 | args = get_args() 47 | train(args) 48 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/scripts/train_v2_rsl.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from datetime import datetime 4 | 5 | import isaacgym 6 | from legged_gym.envs import * 7 | from legged_gym.utils import get_args, task_registry 8 | # import torch 9 | import wandb 10 | 11 | def train(args): 12 | env_cfg, train_cfg = task_registry.get_cfgs(args.task) 13 | 14 | #! test 15 | # env_cfg.env.debug_viz = True 16 | # env_cfg.env.num_envs = 1 17 | # env_cfg.terrain.num_rows = max(2, env_cfg.terrain.max_init_terrain_level+1) 18 | # env_cfg.terrain.num_cols = 2 19 | # env_cfg.terrain.max_init_terrain_level = 9 20 | 21 | current_dir = os.path.dirname(os.path.abspath(__file__)) 22 | root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir))) 23 | log_root = os.path.join(root_dir, 'weights', train_cfg.runner.experiment_name) 24 | log_dir = os.path.join(log_root, datetime.now().strftime('%b%d_%H-%M-%S') + '_' + args.run_name) 25 | os.makedirs(log_dir) 26 | 27 | wandb.init(project=args.task, 28 | name=args.run_name, 29 | entity="p1terq", 30 | group=args.run_name[:3], 31 | mode="online", 32 | dir=log_dir, 33 | config={ 34 | "ENV_CFG": vars(env_cfg), 35 | "TRAIN_CFG": vars(train_cfg) 36 | }) 37 | 38 | 39 | wandb.save("/home/ustc/robot/learning/iros2024/legged_gym/legged_gym/envs/legged" + "/legged_v2_config.py", policy="now") 40 | wandb.save("/home/ustc/robot/learning/iros2024/legged_gym/legged_gym/envs/legged" + "/legged_v2.py", policy="now") 41 | 42 | env, env_cfg = task_registry.make_env(name=args.task, args=args) 43 | ppo_runner, train_cfg = task_registry.make_alg_runner_rsl(env=env, name=args.task, args=args, log_dir_=log_dir) 44 | ppo_runner.learn(num_learning_iterations=train_cfg.runner.max_iterations, init_at_random_ep_len=True) 45 | 46 | if __name__ == '__main__': 47 | args = get_args() 48 | 49 | # args.headless = True 50 | args.task = 'a1_v2' # task选择任务的文件 51 | 52 | # args.run_name = '000-00' # run_name用来保存权重目录. 前3为表示group,后面为实验编号. 相同代码不同参数的实验为同一group 53 | 54 | train(args) 55 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/sensors/floating_camera_sensor.py: -------------------------------------------------------------------------------- 1 | from .sensorbase import SensorBase 2 | from isaacgym import gymapi 3 | 4 | class FloatingCameraSensor(SensorBase): 5 | def __init__(self, env): 6 | super().__init__(env) 7 | self.env = env 8 | 9 | camera_props = gymapi.CameraProperties() 10 | camera_props.width = 360 11 | camera_props.height = 240 12 | self.recording_camera = self.env.gym.create_camera_sensor(self.env.envs[0], camera_props) 13 | self.env.gym.set_camera_location(self.recording_camera, self.env.envs[0], 14 | gymapi.Vec3(1.5, 1, 3.0), 15 | gymapi.Vec3(0, 0, 0)) 16 | 17 | def set_position(self, target_loc=None, cam_distance=None): 18 | if cam_distance is None: 19 | cam_distance = [0, -1.0, 1.0] 20 | if target_loc is None: 21 | bx, by, bz = self.env.root_states[0, 0], self.env.root_states[0, 1], self.env.root_states[0, 2] 22 | target_loc = [bx, by, bz] 23 | 24 | self.env.gym.set_camera_location(self.recording_camera, self.env.envs[0], gymapi.Vec3(target_loc[0] + cam_distance[0], 25 | target_loc[1] + cam_distance[1], 26 | target_loc[2] + cam_distance[2]), 27 | gymapi.Vec3(target_loc[0], target_loc[1], target_loc[2])) 28 | 29 | def get_observation(self, env_ids = None): 30 | self.env.gym.step_graphics(self.env.sim) 31 | self.env.gym.render_all_camera_sensors(self.env.sim) 32 | img = self.env.gym.get_camera_image(self.env.sim, self.env.envs[0], self.recording_camera, gymapi.IMAGE_COLOR) 33 | w, h = img.shape 34 | return img.reshape([w, h // 4, 4]) -------------------------------------------------------------------------------- /legged_gym/legged_gym/sensors/sensorbase.py: -------------------------------------------------------------------------------- 1 | class SensorBase: 2 | def __init__(self, env): 3 | self.env = env 4 | 5 | def get_observation(self): 6 | raise NotImplementedError 7 | 8 | def get_noise_vec(self): 9 | raise NotImplementedError 10 | 11 | def get_dim(self): 12 | raise NotImplementedError -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/data/gait_bad.csv: -------------------------------------------------------------------------------- 1 | Time,RF,LF,RH,LH 2 | 0.02,0,0,0,0 3 | 0.039999999,0,0,0,0 4 | 0.059999999,0,0,0,0 5 | 0.079999998,0,0,0,0 6 | 0.099999994,0,0,0,0 7 | 0.119999997,0,0,0,0 8 | 0.140000001,1,0,0,0 9 | 0.159999996,1,0,0,1 10 | 0.179999992,1,1,0,0 11 | 0.199999988,1,1,0,0 12 | 0.219999999,1,0,1,0 13 | 0.239999995,1,1,1,0 14 | 0.25999999,1,1,0,0 15 | 0.280000001,1,0,0,0 16 | 0.299999982,1,0,0,0 17 | 0.319999993,1,0,0,0 18 | 0.340000004,0,0,0,0 19 | 0.359999985,0,0,0,0 20 | 0.379999995,0,0,0,0 21 | 0.399999976,0,1,0,0 22 | 0.419999987,0,1,0,0 23 | 0.439999998,1,0,0,1 24 | 0.459999979,1,0,0,1 25 | 0.479999989,1,0,0,1 26 | 0.5,1,0,0,1 27 | 0.519999981,1,0,0,0 28 | 0.539999962,1,0,0,1 29 | 0.560000002,1,0,0,1 30 | 0.579999983,1,0,0,1 31 | 0.599999964,1,0,0,1 32 | 0.620000005,1,0,0,0 33 | 0.639999986,1,0,0,1 34 | 0.659999967,1,0,0,0 35 | 0.680000007,0,0,0,0 36 | 0.699999988,0,0,1,0 37 | 0.719999969,0,0,1,0 38 | 0.74000001,0,0,0,0 39 | 0.75999999,0,0,0,0 40 | 0.779999971,0,0,0,0 41 | 0.799999952,1,0,1,0 42 | 0.819999993,1,0,0,1 43 | 0.839999974,1,0,0,0 44 | 0.859999955,1,0,1,0 45 | 0.879999995,1,0,1,0 46 | 0.899999976,1,0,0,1 47 | 0.919999957,1,0,0,1 48 | 0.939999998,1,0,0,1 49 | 0.959999979,1,1,0,0 50 | 0.979999959,0,0,0,0 51 | 1,0,0,0,0 52 | 1.019999981,0,0,0,0 53 | 1.039999962,1,0,0,0 54 | 1.059999943,1,0,0,0 55 | 1.079999924,1,0,0,0 56 | 1.100000024,1,0,0,0 57 | 1.120000005,1,1,0,0 58 | 1.139999986,0,1,0,0 59 | 1.159999967,1,0,0,0 60 | 1.179999948,1,0,0,0 61 | 1.199999928,1,0,0,0 62 | 1.220000029,1,0,1,0 63 | 1.24000001,1,0,0,0 64 | 1.25999999,0,0,1,1 65 | 1.279999971,0,1,1,0 66 | 1.299999952,0,1,1,0 67 | 1.319999933,1,0,0,0 68 | 1.339999914,1,0,0,0 69 | 1.360000014,1,0,0,0 70 | 1.379999995,1,0,0,0 71 | 1.399999976,0,0,0,0 72 | 1.419999957,0,0,0,1 73 | 1.439999938,0,0,0,1 74 | 1.459999919,0,0,0,1 75 | 1.480000019,1,0,0,0 76 | 1.5,1,0,0,1 77 | 1.519999981,1,0,0,0 78 | 1.539999962,1,0,0,1 79 | 1.559999943,0,0,0,0 80 | 1.579999924,0,0,0,0 81 | 1.599999905,0,0,0,0 82 | 1.620000005,0,0,0,0 83 | 1.639999986,1,1,0,0 84 | 1.659999967,1,0,0,1 85 | 1.679999948,1,0,0,1 86 | 1.699999928,1,0,0,0 87 | 1.719999909,1,0,0,0 88 | 1.74000001,1,0,0,0 89 | 1.75999999,1,0,0,0 90 | 1.779999971,0,0,0,0 91 | 1.799999952,0,0,0,0 92 | 1.819999933,1,1,1,0 93 | 1.839999914,1,1,1,0 94 | 1.860000014,1,1,1,0 95 | 1.879999995,1,0,1,0 96 | 1.899999976,0,0,0,0 97 | 1.919999957,0,0,0,0 98 | 1.939999938,0,0,0,0 99 | 1.959999919,1,0,0,0 100 | 1.9799999,1,0,0,1 101 | 2,1,0,0,0 102 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/data/gait_good.csv: -------------------------------------------------------------------------------- 1 | Time,RF,LF,RH,LH 2 | 0.02,1,0,0,1 3 | 0.039999999,0,0,0,0 4 | 0.059999999,0,0,0,0 5 | 0.079999998,0,0,0,0 6 | 0.099999994,0,0,0,0 7 | 0.119999997,0,0,0,0 8 | 0.140000001,1,0,0,0 9 | 0.159999996,1,1,0,1 10 | 0.179999992,1,1,0,1 11 | 0.199999988,1,1,0,1 12 | 0.219999999,1,1,0,1 13 | 0.239999995,1,1,0,1 14 | 0.25999999,1,1,0,1 15 | 0.280000001,1,1,0,1 16 | 0.299999982,1,1,1,1 17 | 0.319999993,1,1,1,1 18 | 0.340000004,0,1,1,1 19 | 0.359999985,0,1,1,1 20 | 0.379999995,0,1,1,0 21 | 0.399999976,0,1,1,0 22 | 0.419999987,0,1,1,0 23 | 0.439999998,0,1,1,0 24 | 0.459999979,1,1,1,0 25 | 0.479999989,1,1,1,0 26 | 0.5,1,1,1,0 27 | 0.519999981,1,1,1,0 28 | 0.539999962,1,1,0,0 29 | 0.560000002,1,0,0,1 30 | 0.579999983,1,0,0,1 31 | 0.599999964,1,0,0,1 32 | 0.620000005,1,0,0,1 33 | 0.639999986,1,0,0,1 34 | 0.659999967,1,0,0,1 35 | 0.680000007,1,0,0,1 36 | 0.699999988,1,1,0,1 37 | 0.719999969,1,1,0,1 38 | 0.74000001,1,1,0,1 39 | 0.75999999,1,1,0,1 40 | 0.779999971,1,1,1,1 41 | 0.799999952,0,1,1,1 42 | 0.819999993,0,1,1,1 43 | 0.839999974,0,1,1,1 44 | 0.859999955,0,1,1,1 45 | 0.879999995,0,1,1,0 46 | 0.899999976,0,1,1,0 47 | 0.919999957,0,1,1,0 48 | 0.939999998,1,1,1,0 49 | 0.959999979,1,1,1,0 50 | 0.979999959,1,1,1,0 51 | 1,1,1,1,0 52 | 1.019999981,1,1,1,0 53 | 1.039999962,1,1,1,0 54 | 1.059999943,1,1,1,0 55 | 1.079999924,1,1,0,0 56 | 1.100000024,1,0,0,1 57 | 1.120000005,1,0,0,1 58 | 1.139999986,1,0,0,1 59 | 1.159999967,1,0,0,1 60 | 1.179999948,1,0,0,1 61 | 1.199999928,1,0,0,1 62 | 1.220000029,1,0,0,1 63 | 1.24000001,1,1,0,1 64 | 1.25999999,1,1,0,1 65 | 1.279999971,1,1,0,1 66 | 1.299999952,1,1,1,1 67 | 1.319999933,0,1,1,1 68 | 1.339999914,0,1,1,1 69 | 1.360000014,0,1,1,1 70 | 1.379999995,0,1,1,1 71 | 1.399999976,0,1,1,0 72 | 1.419999957,0,1,1,0 73 | 1.439999938,0,1,1,0 74 | 1.459999919,0,1,1,0 75 | 1.480000019,1,1,1,0 76 | 1.5,1,1,1,0 77 | 1.519999981,1,1,1,0 78 | 1.539999962,1,1,1,0 79 | 1.559999943,1,1,1,0 80 | 1.579999924,1,1,1,0 81 | 1.599999905,1,1,1,0 82 | 1.620000005,1,1,0,0 83 | 1.639999986,1,0,0,1 84 | 1.659999967,1,0,0,1 85 | 1.679999948,1,0,0,1 86 | 1.699999928,1,0,0,1 87 | 1.719999909,1,0,0,1 88 | 1.74000001,1,0,0,1 89 | 1.75999999,1,0,0,1 90 | 1.779999971,1,1,0,1 91 | 1.799999952,1,1,0,1 92 | 1.819999933,1,1,0,1 93 | 1.839999914,1,1,0,1 94 | 1.860000014,0,1,1,1 95 | 1.879999995,0,1,1,1 96 | 1.899999976,0,1,1,1 97 | 1.919999957,0,1,1,1 98 | 1.939999938,0,1,1,0 99 | 1.959999919,0,1,1,0 100 | 1.9799999,0,1,1,0 101 | 2,0,1,1,0 102 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/data/gait_vel.csv: -------------------------------------------------------------------------------- 1 | Time,RF,LF,RH,LH 2 | 0.02,0,0,0,0 3 | 0.039999999,0,0,0,0 4 | 0.059999999,0,0,0,0 5 | 0.079999998,0,0,0,0 6 | 0.099999994,0,0,0,0 7 | 0.119999997,0,0,0,0 8 | 0.140000001,1,1,0,0 9 | 0.159999996,1,1,0,0 10 | 0.179999992,0,1,1,1 11 | 0.199999988,0,1,1,0 12 | 0.219999999,0,1,1,0 13 | 0.239999995,0,1,1,0 14 | 0.25999999,0,1,1,0 15 | 0.280000001,0,1,1,0 16 | 0.299999982,0,1,1,0 17 | 0.319999993,0,1,1,0 18 | 0.340000004,0,1,1,0 19 | 0.359999985,0,1,1,0 20 | 0.379999995,0,1,1,0 21 | 0.399999976,0,1,1,0 22 | 0.419999987,0,1,1,0 23 | 0.439999998,0,1,1,0 24 | 0.459999979,0,1,1,0 25 | 0.479999989,0,1,1,0 26 | 0.5,0,1,1,0 27 | 0.519999981,0,1,1,1 28 | 0.539999962,1,1,1,1 29 | 0.560000002,1,1,1,1 30 | 0.579999983,1,1,0,1 31 | 0.599999964,1,1,0,1 32 | 0.620000005,1,0,0,1 33 | 0.639999986,1,0,0,1 34 | 0.659999967,1,0,0,1 35 | 0.680000007,1,0,0,1 36 | 0.699999988,1,0,0,1 37 | 0.719999969,1,0,0,1 38 | 0.74000001,1,0,0,1 39 | 0.75999999,1,0,0,1 40 | 0.779999971,1,1,1,0 41 | 0.799999952,0,1,1,0 42 | 0.819999993,0,1,1,0 43 | 0.839999974,0,1,1,0 44 | 0.859999955,0,1,1,0 45 | 0.879999995,0,1,1,0 46 | 0.899999976,0,1,1,0 47 | 0.919999957,0,1,1,0 48 | 0.939999998,0,1,1,0 49 | 0.959999979,0,1,1,0 50 | 0.979999959,0,1,1,0 51 | 1,0,1,1,0 52 | 1.019999981,0,1,1,0 53 | 1.039999962,0,1,1,0 54 | 1.059999943,1,1,1,0 55 | 1.079999924,1,1,0,1 56 | 1.100000024,1,0,0,1 57 | 1.120000005,1,0,0,1 58 | 1.139999986,1,0,0,1 59 | 1.159999967,1,0,0,1 60 | 1.179999948,1,0,0,1 61 | 1.199999928,1,0,0,1 62 | 1.220000029,1,0,0,1 63 | 1.24000001,1,0,0,1 64 | 1.25999999,1,0,0,1 65 | 1.279999971,1,0,1,1 66 | 1.299999952,1,1,1,0 67 | 1.319999933,0,1,1,0 68 | 1.339999914,0,1,1,0 69 | 1.360000014,0,1,1,0 70 | 1.379999995,0,1,1,0 71 | 1.399999976,0,1,1,0 72 | 1.419999957,0,1,1,0 73 | 1.439999938,0,1,1,0 74 | 1.459999919,0,1,1,0 75 | 1.480000019,0,1,1,0 76 | 1.5,0,1,1,0 77 | 1.519999981,0,1,1,0 78 | 1.539999962,0,1,1,0 79 | 1.559999943,1,1,1,0 80 | 1.579999924,1,1,0,1 81 | 1.599999905,1,0,0,1 82 | 1.620000005,1,0,0,1 83 | 1.639999986,1,0,0,1 84 | 1.659999967,1,0,0,1 85 | 1.679999948,1,0,0,1 86 | 1.699999928,1,0,0,1 87 | 1.719999909,1,0,0,1 88 | 1.74000001,1,0,0,1 89 | 1.75999999,1,0,0,1 90 | 1.779999971,1,0,0,1 91 | 1.799999952,1,1,1,0 92 | 1.819999933,1,1,1,0 93 | 1.839999914,0,1,1,0 94 | 1.860000014,0,1,1,0 95 | 1.879999995,0,1,1,0 96 | 1.899999976,0,1,1,0 97 | 1.919999957,0,1,1,0 98 | 1.939999938,0,1,1,0 99 | 1.959999919,0,1,1,0 100 | 1.9799999,0,1,1,0 101 | 2,0,1,1,0 102 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/extract_frame.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | # 替换为实际的视频文件路径 4 | video_path = '/home/ustc/Videos/1-29parkour.mp4' 5 | 6 | # 指定开始和结束时间(以秒为单位) 7 | start_time = 17 # 从视频的第10秒开始 8 | end_time = 26 # 到视频的第60秒结束 9 | 10 | # 打开视频文件 11 | cap = cv2.VideoCapture(video_path) 12 | 13 | # 检查视频是否成功打开 14 | if not cap.isOpened(): 15 | print("错误:无法打开视频。") 16 | exit() 17 | 18 | # 获取视频的帧率和总帧数 19 | fps = cap.get(cv2.CAP_PROP_FPS) 20 | total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) 21 | 22 | # 计算开始和结束时间对应的帧编号 23 | start_frame = int(fps * start_time) 24 | end_frame = int(fps * end_time) 25 | end_frame = min(end_frame, total_frames) # 防止结束帧超出视频总帧数 26 | 27 | # 计算每0.5秒的帧数间隔 28 | frame_interval = int(fps * 0.1) 29 | 30 | # 初始化帧计数器 31 | frame_counter = 0 32 | 33 | # 初始化输出帧的列表 34 | saved_frames = [] 35 | 36 | # 逐帧读取视频 37 | while True: 38 | ret, frame = cap.read() 39 | 40 | # 如果没有更多帧,则退出循环 41 | if not ret: 42 | break 43 | 44 | # 只处理位于指定时间范围内的帧 45 | if start_frame <= frame_counter <= end_frame: 46 | # 每0.5秒保存一帧 47 | if frame_counter % frame_interval == 0: 48 | # 构造图片文件名 49 | frame_filename = f'/home/ustc/Videos/pic/1-29parkour_big/frame_{frame_counter//frame_interval}.png' 50 | # 保存当前帧为图片 51 | cv2.imwrite(frame_filename, frame) 52 | saved_frames.append(frame_filename) 53 | print(f"保存:{frame_filename}") 54 | 55 | # 帧计数器增加 56 | frame_counter += 1 57 | 58 | # 释放视频捕获对象 59 | cap.release() 60 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/plot1.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | # Define the data - using binary values as an example 5 | # You can replace these with your actual data 6 | data1 = np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1], [0, 1, 0]]) 7 | data2 = np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0], [1, 0, 1]]) 8 | data3 = np.array([[1, 1, 0], [0, 1, 1], [1, 0, 1], [1, 1, 0]]) 9 | 10 | # Define the labels for y-axis 11 | labels = ['RH', 'RF', 'LH', 'LF'] 12 | 13 | # Create a figure with 3 subplots in a row 14 | fig, axs = plt.subplots(1, 3, figsize=(9, 3)) 15 | 16 | # A function to create a single subplot 17 | def create_subplot(ax, data, title, c_map): 18 | ax.imshow(data, cmap=c_map, aspect='auto') 19 | ax.set_yticks(np.arange(len(labels))) 20 | ax.set_yticklabels(labels) 21 | ax.set_xlabel('Time [s]') 22 | ax.set_title(title) 23 | 24 | # Create each subplot with the corresponding data and color map 25 | create_subplot(axs[0], data1, 'Data 1', 'Blues') 26 | create_subplot(axs[1], data2, 'Data 2', 'Oranges') 27 | create_subplot(axs[2], data3, 'Data 3', 'Greens') 28 | 29 | # Adjust layout for better spacing 30 | plt.tight_layout() 31 | 32 | # Show the plot 33 | plt.show() 34 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/plot2.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | # Sample data: Replace these with your actual data points 5 | environments = ['2k steps in Log Bridge', '6k steps in Log Bridge', '2k steps in Tunnel', '6k steps in Tunnel'] 6 | VelocityTracking_scores = [0.8, 0.9, 0.7, 0.6] 7 | ExtremeParkour_scores = [0.9, 0.8, 0.8, 0.7] 8 | Oracle_scores = [0.7, 0.8, 0.6, 0.5] 9 | LEEPS_scores = [0.6, 0.7, 0.5, 0.4] 10 | 11 | # Set the positions and width for the bars 12 | positions = np.arange(len(environments)) 13 | width = 0.2 # the width of the bars 14 | 15 | # Plot the bars 16 | fig, ax = plt.subplots() 17 | rects1 = ax.bar(positions - width*1.5, VelocityTracking_scores, width, label='Velocity Tracking') 18 | rects2 = ax.bar(positions - width/2, ExtremeParkour_scores, width, label='Extreme Parkour') 19 | rects3 = ax.bar(positions + width/2, Oracle_scores, width, label='LEEPS Oracle') 20 | rects4 = ax.bar(positions + width*1.5, LEEPS_scores, width, label='LEEPS') 21 | 22 | # Add some text for labels, title and custom x-axis tick labels, etc. 23 | ax.set_ylabel('Average Terrain Level') 24 | ax.set_title('Scores by environment') 25 | ax.set_xticks(positions) 26 | ax.set_xticklabels(environments) 27 | ax.legend() 28 | 29 | # Function to add labels on top of the bars 30 | def add_labels(rects): 31 | """Attach a text label above each bar in *rects*, displaying its height.""" 32 | for rect in rects: 33 | height = rect.get_height() 34 | ax.annotate('{}'.format(height), 35 | xy=(rect.get_x() + rect.get_width() / 2, height), 36 | xytext=(0, 3), # 3 points vertical offset 37 | textcoords="offset points", 38 | ha='center', va='bottom') 39 | 40 | # Call the function to add labels 41 | add_labels(rects1) 42 | add_labels(rects2) 43 | add_labels(rects3) 44 | add_labels(rects4) 45 | 46 | # Display the plot 47 | plt.tight_layout() 48 | plt.show() 49 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/plot_Histogram.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import matplotlib.font_manager as mfm 3 | from matplotlib import style 4 | import numpy as np 5 | import seaborn as sns 6 | style.use('ggplot') # 加载'ggplot'风格 7 | import matplotlib 8 | matplotlib.rcParams['pdf.fonttype'] = 42 9 | matplotlib.rcParams['ps.fonttype'] = 42 10 | 11 | # 加载中文字体 12 | # font_path = "/System/Library/Fonts/STHeiti Light.ttc" # 本地字体链接 13 | # prop = mfm.FontProperties(fname=font_path) 14 | 15 | A = [[0.4, 0.6, 0.02, 0.9], 16 | [0.6, 0.8, 1.0, 0.02], 17 | [1.0, 1.0, 1.0, 1.0], 18 | [1.0, 1.0, 0.95, 0.9]] 19 | 20 | x_labels = ['0.5m barrier', '0.8m gap', '0.2m log', '0.2m tunnel'] 21 | 22 | x = np.arange(4) 23 | # 生成多柱图 24 | # lgd = plt.figure(figsize=(10,3)) 25 | 26 | fig, ax = plt.subplots(figsize=(12.5,3.5)) 27 | color1 = sns.color_palette('deep') 28 | color2 = sns.color_palette('muted') 29 | color3=[color2[0],color2[1],color2[4],color2[3],color1[2]] 30 | sns.set_style('white') 31 | bar_width = 0.2 32 | ax.bar(x + 0.0, A[0], color=color3[4], width=bar_width, label='Robot Parkour Learning') 33 | ax.bar(x + 0.2, A[1], color=color3[0], width=bar_width, label='Extreme Legged Parkour') 34 | ax.bar(x + 0.4, A[2], color=color3[2], width=bar_width, label='LEEPS$_\mathrm{Oracle}$') 35 | ax.bar(x + 0.6, A[3], color=color3[3], width=bar_width, label='LEEPS') 36 | 37 | plt.xticks(x + 0.30, x_labels, fontsize=13, color='black') 38 | plt.xlabel('Environments',fontsize=16,color='black') 39 | plt.ylim( -0.05 ,1.19) 40 | plt.yticks(fontsize=12,color='black') 41 | plt.ylabel('Success Rate', fontsize=14,color='black') 42 | # lgd.grid(False) 43 | ax.spines['top'].set_visible(False) 44 | ax.spines['right'].set_visible(False) 45 | ax.spines['bottom'].set_visible(True) 46 | ax.spines['left'].set_visible(True) 47 | 48 | # 生成图片 49 | plt.legend(fontsize=15, 50 | loc='upper center', 51 | borderaxespad=0.2, 52 | frameon=False, 53 | # loc="upper right", 54 | ncol=4) 55 | 56 | plt.tight_layout() 57 | plt.savefig("TerrainLevel.png", dpi=700) 58 | plt.savefig('TerrainLevel.pdf', 59 | format='pdf', 60 | bbox_extra_artists=(fig,), 61 | bbox_inches='tight', 62 | ) 63 | plt.show() -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/plot_gait.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import pandas as pd 3 | import numpy as np 4 | 5 | # Define file paths 6 | csv_file_paths = [ 7 | '/home/ustc/robot/projects/legged_locomotion/iros2024/legged_gym/legged_gym/tests/data/gait_vel.csv', 8 | '/home/ustc/robot/projects/legged_locomotion/iros2024/legged_gym/legged_gym/tests/data/gait_bad.csv', 9 | '/home/ustc/robot/projects/legged_locomotion/iros2024/legged_gym/legged_gym/tests/data/gait_good.csv' 10 | ] 11 | 12 | # Create a figure with 3 subplots 13 | fig, axs = plt.subplots(1, 3, figsize=(10.5, 2.8)) # Adjust the size as needed 14 | colors = ['C0', 'C2', 'C1'] 15 | titles = ['Velocity tracking', 'LEEPS w/o gait-shaping', 'LEEPS'] 16 | 17 | title_fontsize = 20 18 | label_fontsize = 18 19 | padding = 0.6 20 | 21 | pic_num = 0 22 | 23 | #! 1st subplot 24 | ax = axs[pic_num] 25 | df = pd.read_csv(csv_file_paths[pic_num]) 26 | 27 | # Plot each contact state 28 | for i, limb in enumerate(['RH', 'RF', 'LH', 'LF']): 29 | # Extract the times where contact is made 30 | contact_times = df['Time'][df[limb] == 1] 31 | for time in contact_times: 32 | # ax.plot([time, time + 0.02], [i, i], color=colors[pic_num], lw=20) # Adjust line width as needed 33 | ax.plot([time, time + 0.002], [i, i], color=colors[pic_num], lw=20) 34 | 35 | # Set the y-axis labels to the limbs names 36 | ax.set_yticks([0, 1, 2, 3]) 37 | ax.set_yticklabels(['LF', 'LH', 'RF', 'RH'], fontsize=label_fontsize) 38 | ax.set_ylim([-padding, 4 - 1 + padding]) 39 | # ax.invert_yaxis() # Invert y-axis so that LF is at the bottom as in the example image 40 | 41 | # Set the x-axis label and limits 42 | ax.set_xlabel('Time [s]', fontsize=label_fontsize) 43 | ax.set_xlim([0, max(df['Time'])]) 44 | # ax.set_xlim([df['Time'].min() - padding, df['Time'].max() + padding]) 45 | ax.set_title(titles[pic_num], fontsize=title_fontsize) 46 | pic_num += 1 47 | 48 | for spine in ax.spines.values(): 49 | spine.set_linewidth(1.5) 50 | ax.tick_params(axis='both', which='major', labelsize=label_fontsize, width=1.5) 51 | 52 | #! 2ed subplot 53 | ax = axs[pic_num] 54 | df = pd.read_csv(csv_file_paths[pic_num]) 55 | 56 | # Plot each contact state 57 | for i, limb in enumerate(['RH', 'RF', 'LH', 'LF']): 58 | # Extract the times where contact is made 59 | contact_times = df['Time'][df[limb] == 1] 60 | for time in contact_times: 61 | # ax.plot([time, time + 0.02], [i, i], color=colors[pic_num], lw=20) # Adjust line width as needed 62 | ax.plot([time, time + 0.003], [i, i], color=colors[pic_num], lw=20) 63 | 64 | # Set the y-axis labels to the limbs names 65 | ax.set_yticks([0, 1, 2, 3]) 66 | ax.set_yticklabels(['LF', 'LH', 'RF', 'RH'], fontsize=label_fontsize) 67 | ax.set_ylim([-padding, 4 - 1 + padding]) 68 | # ax.invert_yaxis() # Invert y-axis so that LF is at the bottom as in the example image 69 | 70 | # Set the x-axis label and limits 71 | ax.set_xlabel('Time [s]', fontsize=label_fontsize) 72 | ax.set_xlim([0, max(df['Time'])]) 73 | ax.set_title(titles[pic_num], fontsize=title_fontsize) 74 | pic_num += 1 75 | 76 | for spine in ax.spines.values(): 77 | spine.set_linewidth(1.5) 78 | ax.tick_params(axis='both', which='major', labelsize=label_fontsize, width=1.5) 79 | 80 | #! 3rd subplot 81 | ax = axs[pic_num] 82 | df = pd.read_csv(csv_file_paths[pic_num]) 83 | 84 | # Plot each contact state 85 | for i, limb in enumerate(['RH', 'RF', 'LH', 'LF']): 86 | # Extract the times where contact is made 87 | contact_times = df['Time'][df[limb] == 1] 88 | for time in contact_times: 89 | # ax.plot([time, time + 0.02], [i, i], color=colors[pic_num], lw=20) # Adjust line width as needed 90 | ax.plot([time, time + 0.0015], [i, i], color=colors[pic_num], lw=20) 91 | 92 | # Set the y-axis labels to the limbs names 93 | ax.set_yticks([0, 1, 2, 3]) 94 | ax.set_yticklabels(['LF', 'LH', 'RF', 'RH'], fontsize=label_fontsize) 95 | ax.set_ylim([-padding, 4 - 1 + padding]) 96 | 97 | # ax.set_xticks([0, 1, 2], [0, 1.0, 2.0]) 98 | # ax.invert_yaxis() # Invert y-axis so that LF is at the bottom as in the example image 99 | 100 | # Set the x-axis label and limits 101 | ax.set_xlabel('Time [s]', fontsize=label_fontsize) 102 | ax.set_xlim([0, max(df['Time'])]) 103 | ax.set_title(titles[pic_num], fontsize=title_fontsize) 104 | pic_num += 1 105 | 106 | # Remove all spines 107 | # for spine in ax.spines.values(): 108 | # spine.set_visible(False) 109 | 110 | # Hide the top and right ticks and tick labels 111 | # ax.xaxis.tick_bottom() 112 | # ax.yaxis.tick_left() 113 | 114 | for spine in ax.spines.values(): 115 | spine.set_linewidth(1.5) 116 | ax.tick_params(axis='both', which='major', labelsize=label_fontsize, width=1.5) 117 | 118 | 119 | # Adjust layout for better spacing 120 | plt.tight_layout() 121 | 122 | plt.savefig('gait_phase.png', format='png', dpi=500) # Save as PNG with specified DPI 123 | plt.savefig('gait_phase.pdf', format='pdf') # Save as PDF 124 | 125 | # Show the plot 126 | plt.show() 127 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/tests/test_env.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 numpy as np 32 | import os 33 | from datetime import datetime 34 | 35 | import isaacgym 36 | from legged_gym.envs import * 37 | from legged_gym.utils import get_args, export_policy_as_jit, task_registry, Logger 38 | 39 | import torch 40 | 41 | 42 | def test_env(args): 43 | env_cfg, train_cfg = task_registry.get_cfgs(name=args.task) 44 | # override some parameters for testing 45 | env_cfg.env.num_envs = min(env_cfg.env.num_envs, 10) 46 | 47 | # prepare environment 48 | env, _ = task_registry.make_env(name=args.task, args=args, env_cfg=env_cfg) 49 | for i in range(int(10*env.max_episode_length)): 50 | actions = 0.*torch.ones(env.num_envs, env.num_actions, device=env.device) 51 | obs, _, rew, done, info = env.step(actions) 52 | print("Done") 53 | 54 | if __name__ == '__main__': 55 | args = get_args() 56 | 57 | args.task = 'pc_a1' 58 | test_env(args) 59 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/utils/__init__.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 | from .helpers import class_to_dict, get_load_path, get_args, export_policy_as_jit, set_seed, update_class_from_dict 32 | from .task_registry import task_registry 33 | from .logger import Logger 34 | from .math import * 35 | from .terrain import Terrain -------------------------------------------------------------------------------- /legged_gym/legged_gym/utils/gamepad_reader.py: -------------------------------------------------------------------------------- 1 | from absl import app 2 | from absl import flags 3 | from inputs import get_gamepad 4 | import threading 5 | import time 6 | import numpy as np 7 | 8 | FLAGS = flags.FLAGS 9 | MAX_ABS_RX = 32768 # 最大键盘值 10 | MAX_ABS_RY = 32768 11 | 12 | 13 | def _interpolate(raw_reading, max_raw_reading, new_scale): 14 | #! 用于将键盘值转化为-1到1之间的值 * new_scale 15 | return raw_reading / max_raw_reading * new_scale 16 | 17 | # class Gamepad: 18 | # def __init__(self, vel_scale_x=-1.0, vel_scale_y=-1.0, vel_scale_rot=1.0): 19 | 20 | # # keys and flags 21 | # self._vel_scale_x = vel_scale_x 22 | # self._vel_scale_y = vel_scale_y 23 | # self._vel_scale_rot = vel_scale_rot 24 | 25 | # self._lb_pressed = False 26 | # self._rb_pressed = False 27 | 28 | # # control values 29 | # self.vx, self.vy, self.wz = 0., 0., 0. 30 | # self.estop_flag = False 31 | # self.is_running = True 32 | 33 | # self.read_thread = threading.Thread(target=self.read_loop) 34 | # self.read_thread.start() 35 | 36 | 37 | # def read_loop(self): 38 | # while self.is_running and not self.estop_flag: 39 | # events = get_gamepad() 40 | 41 | # for event in events: 42 | # if event.ev_type == 'Absolute' and event.code == 'ABS_Y': 43 | # self.vx = _interpolate(event.state, MAX_ABS_RY, self._vel_scale_x) 44 | # elif event.ev_type == 'Absolute' and event.code == 'ABS_X': 45 | # self.vy = _interpolate(event.state, MAX_ABS_RX, self._vel_scale_y) 46 | # elif event.ev_type == 'Absolute' and event.code == 'ABS_RX': 47 | # self.wz = _interpolate(event.state, MAX_ABS_RX, self._vel_scale_rot) 48 | 49 | # elif event.ev_type == 'Key' and event.code == 'BTN_TL': 50 | # self._lb_pressed = event.state == 1 51 | # elif event.ev_type == 'Key' and event.code == 'BTN_TR': 52 | # self._rb_pressed = event.state == 1 53 | 54 | # if self._lb_pressed and self._rb_pressed: 55 | # self.estop_flag = True 56 | # self.vx, self.vy, self.wz = 0., 0., 0. 57 | 58 | # def get_command(self): 59 | # # del time_since_reset # unused 60 | # return (1.0 * self.vx, 0.5 * self.vy, 0), -1.5 * self.wz, self.estop_flag 61 | 62 | # def gamepad_stop(self): 63 | # self.is_running = False 64 | 65 | class Gamepad: 66 | def __init__(self, goal_delta_scale_x=-4.0, goal_delta_scale_y=-1.0): 67 | 68 | # keys and flags 69 | self._goal_delta_scale_x = goal_delta_scale_x 70 | self._goal_delta_scale_y = goal_delta_scale_y 71 | 72 | self._lb_pressed = False 73 | self._rb_pressed = False 74 | 75 | # control values 76 | self.delta_x, self.delta_y = 0., 0. 77 | self.episode_length_s = 0. 78 | self.episode_param = 0.7 79 | 80 | self.estop_flag = False 81 | self.is_running = True 82 | 83 | self.read_thread = threading.Thread(target=self.read_loop) 84 | self.read_thread.start() 85 | 86 | 87 | def read_loop(self): 88 | while self.is_running and not self.estop_flag: 89 | events = get_gamepad() 90 | 91 | 92 | 93 | for event in events: 94 | 95 | # print("event.ev_type: ", event.ev_type) 96 | # print("event.code: ", event.code) 97 | # print("event.state: ", event.state) 98 | 99 | if event.ev_type == 'Absolute' and event.code == 'ABS_Y': 100 | self.delta_x = _interpolate(event.state, MAX_ABS_RY, self._goal_delta_scale_x) 101 | elif event.ev_type == 'Absolute' and event.code == 'ABS_X': 102 | self.delta_y = _interpolate(event.state, MAX_ABS_RX, self._goal_delta_scale_y) 103 | 104 | elif event.ev_type == 'Absolute' and event.code == 'ABS_HAT0Y': 105 | if event.state == -1: 106 | self.episode_param += 0.05 107 | elif event.state == 1: 108 | self.episode_param -= 0.05 109 | self.episode_param = np.clip(self.episode_param, 0.6, 1.0) 110 | 111 | elif event.ev_type == 'Key' and event.code == 'BTN_TL': 112 | self._lb_pressed = event.state == 1 113 | elif event.ev_type == 'Key' and event.code == 'BTN_TR': 114 | self._rb_pressed = event.state == 1 115 | 116 | # print("delta_x: ", self.delta_x) 117 | episode_percentage = _interpolate(np.square(self.delta_x) + np.square(self.delta_y), 118 | np.square(self._goal_delta_scale_x)+np.square(self._goal_delta_scale_y),1.0) 119 | # print("episode_percentage: ", episode_percentage) 120 | self.episode_length_s = 1 + episode_percentage * 5.0 121 | 122 | 123 | if self._lb_pressed and self._rb_pressed: 124 | self.estop_flag = True 125 | self.delta_x, self.delta_y = 0., 0. 126 | 127 | def get_command(self): 128 | # del time_since_reset # unused 129 | return 1.0 * self.delta_x, 1.0 * self.delta_y, self.episode_param * self.episode_length_s, self.estop_flag 130 | 131 | def gamepad_stop(self): 132 | self.is_running = False 133 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/utils/logger.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 matplotlib.pyplot as plt 32 | import numpy as np 33 | from collections import defaultdict 34 | from multiprocessing import Process, Value 35 | 36 | class Logger: 37 | def __init__(self, dt): 38 | self.state_log = defaultdict(list) 39 | self.rew_log = defaultdict(list) 40 | self.dt = dt 41 | self.num_episodes = 0 42 | self.plot_process = None 43 | 44 | def log_state(self, key, value): 45 | self.state_log[key].append(value) 46 | 47 | def log_states(self, dict): 48 | for key, value in dict.items(): 49 | self.log_state(key, value) 50 | 51 | def log_rewards(self, dict, num_episodes): 52 | for key, value in dict.items(): 53 | if 'rew' in key: 54 | self.rew_log[key].append(value.item() * num_episodes) 55 | self.num_episodes += num_episodes 56 | 57 | def reset(self): 58 | self.state_log.clear() 59 | self.rew_log.clear() 60 | 61 | def plot_states(self): 62 | self.plot_process = Process(target=self._plot) 63 | self.plot_process.start() 64 | 65 | def _plot(self): 66 | nb_rows = 3 67 | nb_cols = 3 68 | fig, axs = plt.subplots(nb_rows, nb_cols) 69 | for key, value in self.state_log.items(): 70 | time = np.linspace(0, len(value)*self.dt, len(value)) 71 | break 72 | log= self.state_log 73 | # plot joint targets and measured positions 74 | a = axs[1, 0] 75 | if log["dof_pos"]: a.plot(time, log["dof_pos"], label='measured') 76 | if log["dof_pos_target"]: a.plot(time, log["dof_pos_target"], label='target') 77 | a.set(xlabel='time [s]', ylabel='Position [rad]', title='DOF Position') 78 | a.legend() 79 | # plot joint velocity 80 | a = axs[1, 1] 81 | if log["dof_vel"]: a.plot(time, log["dof_vel"], label='measured') 82 | if log["dof_vel_target"]: a.plot(time, log["dof_vel_target"], label='target') 83 | a.set(xlabel='time [s]', ylabel='Velocity [rad/s]', title='Joint Velocity') 84 | a.legend() 85 | # plot base vel x 86 | a = axs[0, 0] 87 | if log["base_vel_x"]: a.plot(time, log["base_vel_x"], label='measured') 88 | if log["command_x"]: a.plot(time, log["command_x"], label='commanded') 89 | a.set(xlabel='time [s]', ylabel='base lin vel [m/s]', title='Base velocity x') 90 | a.legend() 91 | # plot base vel y 92 | a = axs[0, 1] 93 | if log["base_vel_y"]: a.plot(time, log["base_vel_y"], label='measured') 94 | if log["command_y"]: a.plot(time, log["command_y"], label='commanded') 95 | a.set(xlabel='time [s]', ylabel='base lin vel [m/s]', title='Base velocity y') 96 | a.legend() 97 | # plot base vel yaw 98 | a = axs[0, 2] 99 | if log["base_vel_yaw"]: a.plot(time, log["base_vel_yaw"], label='measured') 100 | if log["command_yaw"]: a.plot(time, log["command_yaw"], label='commanded') 101 | a.set(xlabel='time [s]', ylabel='base ang vel [rad/s]', title='Base velocity yaw') 102 | a.legend() 103 | # plot base vel z 104 | a = axs[1, 2] 105 | if log["base_vel_z"]: a.plot(time, log["base_vel_z"], label='measured') 106 | a.set(xlabel='time [s]', ylabel='base lin vel [m/s]', title='Base velocity z') 107 | a.legend() 108 | # plot contact forces 109 | a = axs[2, 0] 110 | if log["contact_forces_z"]: 111 | forces = np.array(log["contact_forces_z"]) 112 | for i in range(forces.shape[1]): 113 | a.plot(time, forces[:, i], label=f'force {i}') 114 | a.set(xlabel='time [s]', ylabel='Forces z [N]', title='Vertical Contact forces') 115 | a.legend() 116 | # plot torque/vel curves 117 | a = axs[2, 1] 118 | if log["dof_vel"]!=[] and log["dof_torque"]!=[]: a.plot(log["dof_vel"], log["dof_torque"], 'x', label='measured') 119 | a.set(xlabel='Joint vel [rad/s]', ylabel='Joint Torque [Nm]', title='Torque/velocity curves') 120 | a.legend() 121 | # plot torques 122 | a = axs[2, 2] 123 | if log["dof_torque"]!=[]: a.plot(time, log["dof_torque"], label='measured') 124 | a.set(xlabel='time [s]', ylabel='Joint Torque [Nm]', title='Torque') 125 | a.legend() 126 | plt.show() 127 | 128 | def print_rewards(self): 129 | print("Average rewards per second:") 130 | for key, values in self.rew_log.items(): 131 | mean = np.sum(np.array(values)) / self.num_episodes 132 | print(f" - {key}: {mean}") 133 | print(f"Total number of episodes: {self.num_episodes}") 134 | 135 | def __del__(self): 136 | if self.plot_process is not None: 137 | self.plot_process.kill() -------------------------------------------------------------------------------- /legged_gym/legged_gym/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 isaacgym.torch_utils import quat_apply, normalize 35 | from typing import Tuple 36 | from isaacgym.torch_utils import * 37 | from isaacgym import gymtorch, gymapi, gymutil 38 | from PIL import Image as Im 39 | 40 | 41 | # @ torch.jit.script 42 | def quat_apply_yaw(quat, vec): 43 | quat_yaw = quat.clone().view(-1, 4) 44 | quat_yaw[:, :2] = 0. 45 | quat_yaw = normalize(quat_yaw) 46 | return quat_apply(quat_yaw, vec) 47 | 48 | 49 | def quat_apply_np(a, b): 50 | shape = b.shape 51 | a = a.reshape((-1, 4)) 52 | b = b.reshape((-1, 3)) 53 | xyz = a[:, :3] 54 | t = np.cross(xyz, b, axis=-1) * 2 55 | result = (b + a[:, 3:] * t + np.cross(xyz, t, axis=-1)).reshape(shape) 56 | return result 57 | 58 | 59 | def quat_rotate_inverse_np(q, v): 60 | shape = q.shape 61 | q_w = q[:, -1] 62 | q_vec = q[:, :3] 63 | a = v * (2.0 * q_w ** 2 - 1.0).reshape((-1, 1)) 64 | b = np.cross(q_vec, v, axis=-1) * q_w.reshape((-1, 1)) * 2.0 65 | c = q_vec * np.matmul(q_vec.reshape(shape[0], 1, 3), v.reshape(shape[0], 3, 1)).squeeze(-1) * 2.0 66 | return a - b + c 67 | 68 | 69 | # @ torch.jit.script 70 | def wrap_to_pi(angles): 71 | angles %= 2*np.pi 72 | angles -= 2*np.pi * (angles > np.pi) 73 | return angles 74 | 75 | # @ torch.jit.script 76 | def torch_rand_sqrt_float(lower, upper, shape, device): 77 | # type: (float, float, Tuple[int, int], str) -> Tensor 78 | r = 2*torch.rand(*shape, device=device) - 1 79 | r = torch.where(r<0., -torch.sqrt(-r), torch.sqrt(r)) 80 | r = (r + 1.) / 2. 81 | return (upper - lower) * r + lower 82 | 83 | # @torch.jit.script 84 | def depth_image_to_point_cloud_GPU(camera_tensor, camera_view_matrix_inv, camera_proj_matrix, u, v, width:float, height:float, depth_bar:float, device:torch.device): 85 | # time1 = time.time() 86 | depth_buffer = camera_tensor.to(device) 87 | 88 | # Get the camera view matrix and invert it to transform points from camera to world space 89 | vinv = camera_view_matrix_inv 90 | 91 | # Get the camera projection matrix and get the necessary scaling 92 | # coefficients for deprojection 93 | 94 | proj = camera_proj_matrix 95 | fu = 2/proj[0, 0] 96 | fv = 2/proj[1, 1] 97 | 98 | centerU = width/2 99 | centerV = height/2 100 | 101 | Z = depth_buffer 102 | X = -(u-centerU)/width * Z * fu 103 | Y = (v-centerV)/height * Z * fv 104 | 105 | Z = Z.view(-1) 106 | valid = Z > -depth_bar 107 | X = X.view(-1) 108 | Y = Y.view(-1) 109 | 110 | position = torch.vstack((X, Y, Z, torch.ones(len(X), device=device)))[:, valid] 111 | position = position.permute(1, 0) 112 | position = position@vinv 113 | 114 | points = position[:, 0:3] 115 | 116 | return points 117 | 118 | def euler_from_quaternion(quat_angle): 119 | """ 120 | Convert a quaternion into euler angles (roll, pitch, yaw) 121 | roll is rotation around x in radians (counterclockwise) 122 | pitch is rotation around y in radians (counterclockwise) 123 | yaw is rotation around z in radians (counterclockwise) 124 | """ 125 | x = quat_angle[:,0]; y = quat_angle[:,1]; z = quat_angle[:,2]; w = quat_angle[:,3] 126 | t0 = +2.0 * (w * x + y * z) 127 | t1 = +1.0 - 2.0 * (x * x + y * y) 128 | roll_x = torch.atan2(t0, t1) 129 | 130 | t2 = +2.0 * (w * y - z * x) 131 | t2 = torch.clip(t2, -1, 1) 132 | pitch_y = torch.asin(t2) 133 | 134 | t3 = +2.0 * (w * z + x * y) 135 | t4 = +1.0 - 2.0 * (y * y + z * z) 136 | yaw_z = torch.atan2(t3, t4) 137 | 138 | return roll_x, pitch_y, yaw_z # in radians 139 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/utils/o3dviewer.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import open3d as o3d 3 | 4 | class PointcloudVisualizer() : 5 | 6 | def __init__(self) -> None: 7 | self.vis = o3d.visualization.VisualizerWithKeyCallback() 8 | self.vis.create_window() 9 | # self.vis.register_key_callback(key, your_update_function) 10 | 11 | def add_geometry(self, cloud) : 12 | self.vis.add_geometry(cloud) 13 | 14 | def update(self, cloud): 15 | #Your update routine 16 | self.vis.update_geometry(cloud) 17 | self.vis.update_renderer() 18 | self.vis.poll_events() 19 | 20 | if __name__ == "__main__" : 21 | 22 | visualizer = PointcloudVisualizer() 23 | cloud = o3d.io.read_point_cloud("../../../assets/dataset/one_door_cabinet/46145_link_0/point_sample/full_PC.ply") 24 | visualizer.add_geometry(cloud) 25 | while True : 26 | print("update") 27 | visualizer.update(cloud) 28 | xyz = np.asarray(cloud.points) 29 | xyz *= 1.001 -------------------------------------------------------------------------------- /legged_gym/legged_gym/utils/perlin.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from numpy.random import choice 3 | from scipy import interpolate 4 | 5 | from isaacgym import terrain_utils, gymapi 6 | 7 | import matplotlib.pyplot as plt 8 | 9 | class TerrainPerlin: 10 | def __init__(self, cfg, num_envs): 11 | self.cfg = cfg 12 | self.env_length = cfg.terrain_length 13 | self.env_width = cfg.terrain_width 14 | self.xSize = cfg.terrain_length * cfg.num_rows # int(cfg.horizontal_scale * cfg.tot_cols) 15 | self.ySize = cfg.terrain_width * cfg.num_cols # int(cfg.horizontal_scale * cfg.tot_rows) 16 | self.tot_cols = int(self.xSize / cfg.horizontal_scale) 17 | self.tot_rows = int(self.ySize / cfg.horizontal_scale) 18 | assert(self.xSize == cfg.horizontal_scale * self.tot_rows and self.ySize == cfg.horizontal_scale * self.tot_cols) 19 | self.heightsamples_float = self.generate_fractal_noise_2d(self.xSize, self.ySize, self.tot_rows, self.tot_cols, **cfg.TerrainPerlin_kwargs) 20 | # self.heightsamples_float[self.tot_cols//2 - 100:, :] += 100000 21 | # self.heightsamples_float[self.tot_cols//2 - 40: self.tot_cols//2 + 40, :] = np.mean(self.heightsamples_float) 22 | self.heightsamples = (self.heightsamples_float * (1 / cfg.vertical_scale)).astype(np.int16) 23 | 24 | 25 | print("Terrain heightsamples shape: ", self.heightsamples.shape) 26 | print("Terrain heightsamples stat: ", *(np.array([np.min(self.heightsamples), np.max(self.heightsamples), np.mean(self.heightsamples), np.std(self.heightsamples), np.median(self.heightsamples)]) * cfg.vertical_scale)) 27 | # self.heightsamples = np.zeros((800, 800)).astype(np.int16) 28 | self.vertices, self.triangles = terrain_utils.convert_heightfield_to_trimesh( self.heightsamples, 29 | cfg.horizontal_scale, 30 | cfg.vertical_scale, 31 | cfg.slope_treshold) 32 | 33 | @staticmethod 34 | def generate_perlin_noise_2d(shape, res): 35 | def f(t): 36 | return 6*t**5 - 15*t**4 + 10*t**3 37 | 38 | delta = (res[0] / shape[0], res[1] / shape[1]) 39 | d = (shape[0] // res[0], shape[1] // res[1]) 40 | grid = np.mgrid[0:res[0]:delta[0],0:res[1]:delta[1]].transpose(1, 2, 0) % 1 41 | # Gradients 42 | angles = 2*np.pi*np.random.rand(res[0]+1, res[1]+1) 43 | gradients = np.dstack((np.cos(angles), np.sin(angles))) 44 | g00 = gradients[0:-1,0:-1].repeat(d[0], 0).repeat(d[1], 1) 45 | g10 = gradients[1:,0:-1].repeat(d[0], 0).repeat(d[1], 1) 46 | g01 = gradients[0:-1,1:].repeat(d[0], 0).repeat(d[1], 1) 47 | g11 = gradients[1:,1:].repeat(d[0], 0).repeat(d[1], 1) 48 | # Ramps 49 | #! --task a1_climb --load_run leap的情况下: grid[640,464,2] g00[640,464,2] res[160,116] 50 | #! --task a1_climb --load_run climb的情况下: grid[593,464,2] g00[592,464,2] res[148,116] 51 | n00 = np.sum(grid * g00, 2) 52 | n10 = np.sum(np.dstack((grid[:,:,0]-1, grid[:,:,1])) * g10, 2) 53 | n01 = np.sum(np.dstack((grid[:,:,0], grid[:,:,1]-1)) * g01, 2) 54 | n11 = np.sum(np.dstack((grid[:,:,0]-1, grid[:,:,1]-1)) * g11, 2) 55 | # Interpolation 56 | t = f(grid) 57 | n0 = n00*(1-t[:,:,0]) + t[:,:,0]*n10 58 | n1 = n01*(1-t[:,:,0]) + t[:,:,0]*n11 59 | return np.sqrt(2)*((1-t[:,:,1])*n0 + t[:,:,1]*n1) * 0.5 + 0.5 60 | 61 | @staticmethod 62 | def generate_fractal_noise_2d(xSize=20, ySize=20, xSamples=1600, ySamples=1600, \ 63 | frequency=10, fractalOctaves=2, fractalLacunarity = 2.0, fractalGain=0.25, zScale = 0.23): 64 | xScale = int(frequency * xSize) #! --load_run leap的情况下: xSize=16 65 | yScale = int(frequency * ySize) 66 | amplitude = 1 67 | shape = (xSamples, ySamples) 68 | noise = np.zeros(shape) 69 | for _ in range(fractalOctaves): 70 | noise += amplitude * TerrainPerlin.generate_perlin_noise_2d((xSamples, ySamples), (xScale, yScale)) * zScale 71 | amplitude *= fractalGain 72 | xScale, yScale = int(fractalLacunarity * xScale), int(fractalLacunarity * yScale) 73 | 74 | return noise 75 | 76 | def add_trimesh_to_sim(self, trimesh, trimesh_origin): 77 | tm_params = gymapi.TriangleMeshParams() 78 | tm_params.nb_vertices = trimesh[0].shape[0] 79 | tm_params.nb_triangles = trimesh[1].shape[0] 80 | tm_params.transform.p.x = trimesh_origin[0] 81 | tm_params.transform.p.y = trimesh_origin[1] 82 | tm_params.transform.p.z = 0. 83 | tm_params.static_friction = self.cfg.static_friction 84 | tm_params.dynamic_friction = self.cfg.dynamic_friction 85 | tm_params.restitution = self.cfg.restitution 86 | self.gym.add_triangle_mesh( 87 | self.sim, 88 | trimesh[0].flatten(order= "C"), 89 | trimesh[1].flatten(order= "C"), 90 | tm_params, 91 | ) 92 | 93 | def add_terrain_to_sim(self, gym, sim, device= "cpu"): 94 | """ deploy the terrain mesh to the simulator 95 | """ 96 | self.gym = gym 97 | self.sim = sim 98 | self.device = device 99 | self.add_trimesh_to_sim( 100 | (self.vertices, self.triangles), 101 | np.zeros(3,), 102 | ) 103 | self.env_origins = np.zeros((self.cfg.num_rows, self.cfg.num_cols, 3)) 104 | for row_idx in range(self.cfg.num_rows): 105 | for col_idx in range(self.cfg.num_cols): 106 | origin_x = (row_idx + 0.5) * self.env_length 107 | origin_y = (col_idx + 0.5) * self.env_width 108 | self.env_origins[row_idx, col_idx] = [ 109 | origin_x, 110 | origin_y, 111 | self.heightsamples[ 112 | int(origin_x / self.cfg.horizontal_scale), 113 | int(origin_y / self.cfg.horizontal_scale), 114 | ] * self.cfg.vertical_scale, 115 | ] 116 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/utils/trimesh.py: -------------------------------------------------------------------------------- 1 | """ This file defines a mesh as a tuple of (vertices, triangles) 2 | All operations are based on numpy ndarray 3 | - vertices: np ndarray of shape (n, 3) np.float32 4 | - triangles: np ndarray of shape (n_, 3) np.uint32 5 | """ 6 | import numpy as np 7 | 8 | def box_trimesh( 9 | size, # float [3] for x, y, z axis length (in meter) under box frame 10 | center_position, # float [3] position (in meter) in world frame 11 | rpy= np.zeros(3), # euler angle (in rad) not implemented yet. 12 | ): 13 | if not (rpy == 0).all(): 14 | raise NotImplementedError("Only axis-aligned box triangle mesh is implemented") 15 | 16 | vertices = np.empty((8, 3), dtype= np.float32) 17 | vertices[:] = center_position 18 | vertices[[0, 4, 2, 6], 0] -= size[0] / 2 19 | vertices[[1, 5, 3, 7], 0] += size[0] / 2 20 | vertices[[0, 1, 2, 3], 1] -= size[1] / 2 21 | vertices[[4, 5, 6, 7], 1] += size[1] / 2 22 | vertices[[2, 3, 6, 7], 2] -= size[2] / 2 23 | vertices[[0, 1, 4, 5], 2] += size[2] / 2 24 | 25 | triangles = -np.ones((12, 3), dtype= np.uint32) 26 | triangles[0] = [0, 2, 1] # 27 | triangles[1] = [1, 2, 3] 28 | triangles[2] = [0, 4, 2] # 29 | triangles[3] = [2, 4, 6] 30 | triangles[4] = [4, 5, 6] # 31 | triangles[5] = [5, 7, 6] 32 | triangles[6] = [1, 3, 5] # 33 | triangles[7] = [3, 7, 5] 34 | triangles[8] = [0, 1, 4] # 35 | triangles[9] = [1, 5, 4] 36 | triangles[10]= [2, 6, 3] # 37 | triangles[11]= [3, 6, 7] 38 | 39 | return vertices, triangles 40 | 41 | def combine_trimeshes(*trimeshes): 42 | if len(trimeshes) > 2: 43 | return combine_trimeshes( 44 | trimeshes[0], 45 | combine_trimeshes(trimeshes[1:]) 46 | ) 47 | 48 | # only two trimesh to combine 49 | trimesh_0, trimesh_1 = trimeshes 50 | if trimesh_0[1].shape[0] < trimesh_1[1].shape[0]: 51 | trimesh_0, trimesh_1 = trimesh_1, trimesh_0 52 | 53 | trimesh_1 = (trimesh_1[0], trimesh_1[1] + trimesh_0[0].shape[0]) 54 | vertices = np.concatenate((trimesh_0[0], trimesh_1[0]), axis= 0) 55 | triangles = np.concatenate((trimesh_0[1], trimesh_1[1]), axis= 0) 56 | 57 | return vertices, triangles 58 | 59 | def move_trimesh(trimesh, move: np.ndarray): 60 | """ inplace operation """ 61 | trimesh[0] += move 62 | -------------------------------------------------------------------------------- /legged_gym/legged_gym/utils/webviewer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 | 14 | 15 |
16 | 17 |
18 | 19 | 79 | 80 | -------------------------------------------------------------------------------- /legged_gym/licenses/assets/ANYmal_b_license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019 ANYbotics, https://www.anybotics.com 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | 13 | 3. The name of ANYbotics and ANYmal may not be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 20 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /legged_gym/licenses/assets/ANYmal_c_license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2020, ANYbotics AG. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /legged_gym/licenses/assets/cassie_license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jenna Reher, jreher@caltech.edu 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. -------------------------------------------------------------------------------- /legged_gym/licenses/dependencies/matplotlib_license.txt: -------------------------------------------------------------------------------- 1 | 1. This LICENSE AGREEMENT is between the Matplotlib Development Team ("MDT"), and the Individual or Organization ("Licensee") accessing and otherwise using matplotlib software in source or binary form and its associated documentation. 2 | 3 | 2. Subject to the terms and conditions of this License Agreement, MDT hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use matplotlib 3.4.3 alone or in any derivative version, provided, however, that MDT's License Agreement and MDT's notice of copyright, i.e., "Copyright (c) 2012-2013 Matplotlib Development Team; All Rights Reserved" are retained in matplotlib 3.4.3 alone or in any derivative version prepared by Licensee. 4 | 5 | 3. In the event Licensee prepares a derivative work that is based on or incorporates matplotlib 3.4.3 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to matplotlib 3.4.3. 6 | 7 | 4. MDT is making matplotlib 3.4.3 available to Licensee on an "AS IS" basis. MDT MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, MDT MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB 3.4.3 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 8 | 9 | 5. MDT SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB 3.4.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING MATPLOTLIB 3.4.3, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 10 | 11 | 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 12 | 13 | 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between MDT and Licensee. This License Agreement does not grant permission to use MDT trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 14 | 15 | 8. By copying, installing or otherwise using matplotlib 3.4.3, Licensee agrees to be bound by the terms and conditions of this License Agreement. -------------------------------------------------------------------------------- /legged_gym/resources/actuator_nets/anydrive_v3_lstm.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/actuator_nets/anydrive_v3_lstm.pt -------------------------------------------------------------------------------- /legged_gym/resources/objects/ball.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /legged_gym/resources/robots/a1/meshes/trunk_A1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/a1/meshes/trunk_A1.png -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_b/ANYmal_b_license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019 ANYbotics, https://www.anybotics.com 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | 13 | 3. The name of ANYbotics and ANYmal may not be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 20 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_b/meshes/base_uv_texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_b/meshes/base_uv_texture.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_b/meshes/carbon_uv_texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_b/meshes/carbon_uv_texture.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/ANYmal_c_license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2020, ANYbotics AG. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/base.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/base.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/battery.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Blender User 6 | Blender 2.81.16 commit date:2019-11-20, commit time:14:27, hash:26bd5ebd42e3 7 | 8 | 2020-01-07T14:47:32 9 | 2020-01-07T14:47:32 10 | 11 | Z_UP 12 | 13 | 14 | 15 | 16 | 17 | 18 | battery 19 | 20 | 21 | 22 | 23 | battery-surface 24 | 25 | 26 | 27 | 28 | 29 | 0 0 0 1 30 | 31 | 32 | 33 | 34 | 35 | 1.45 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | battery.jpg 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -0.225881 -0.06249898 -0.03684729 -0.225881 -0.06249898 0.03725165 -0.225881 0.06249898 -0.03684729 -0.225881 0.06249898 0.03725165 0.232213 -0.06249898 -0.03684729 0.232213 -0.06249898 0.03725165 0.232213 0.06249898 -0.03684729 0.232213 0.06249898 0.03725165 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -1 0 0 0 1 0 1 0 0 0 -1 0 0 0 -1 0 0 1 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 0.8431081 0.2728654 1 0 1 0.2728654 0.6862162 1 0.8431079 0 0.8431081 1 0.8431081 0.5457308 1 0.2728654 1 0.5457308 0.6862159 0 0.5293241 1 0.5293239 0 0.264662 0 0.5293239 0.9999999 0.2646622 0.9999999 0.264662 0.9999999 0 0 0.2646618 0 0.8431081 0.2728654 0.8431081 0 1 0 0.6862162 1 0.6862161 0 0.8431079 0 0.8431081 0.5457308 0.8431081 0.2728654 1 0.2728654 0.6862159 0 0.6862161 1 0.5293241 1 0.264662 0 0.5293238 0 0.5293239 0.9999999 0.264662 0.9999999 1.73529e-7 0.9999999 0 0 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |

1 0 0 2 0 1 0 0 2 3 1 3 6 1 4 2 1 5 7 2 6 4 2 7 6 2 8 5 3 9 0 3 10 4 3 11 6 4 12 0 4 13 2 4 14 3 5 15 5 5 16 7 5 17 1 0 18 3 0 19 2 0 20 3 1 21 7 1 22 6 1 23 7 2 24 5 2 25 4 2 26 5 3 27 1 3 28 0 3 29 6 4 30 4 4 31 0 4 32 3 5 33 1 5 34 5 5 35

92 |
93 |
94 |
95 |
96 | 97 | 98 | 99 | 1 0 0 0 0 1 0 0 0 0 1 -0.03329167 0 0 0 1 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 |
-------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/battery.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/battery.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/bottom_shell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/bottom_shell.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/depth_camera.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Blender User 6 | Blender 2.82.7 commit date:2020-02-12, commit time:16:20, hash:77d23b0bd76f 7 | 8 | 2020-02-20T10:55:16 9 | 2020-02-20T10:55:16 10 | 11 | Z_UP 12 | 13 | 14 | 15 | 16 | 17 | 18 | depth_camera 19 | 20 | 21 | 22 | 23 | depth_camera-surface 24 | 25 | 26 | 27 | 28 | 29 | 0 0 0 1 30 | 31 | 32 | 33 | 34 | 35 | 1.45 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | depth_camera.jpg 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 0 -0.04699999 -0.01968461 0 -0.04699999 0.01951932 0 0.04699999 -0.01968461 0 0.04699999 0.01951932 0.03039997 -0.04699999 -0.01968461 0.03039997 -0.04699999 0.01951932 0.03039997 0.04699999 -0.01968461 0.03039997 0.04699999 0.01951932 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -1 0 0 1 0 0 0 0 1 0 -1 0 0 1 0 0 0 -1 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 0.2816218 0.7056847 0.5632433 0 0.5632433 0.7056847 1.60564e-7 0.7056847 0.2816215 0 0.2816217 0.7056847 0.7816217 0.7056846 1 0 1 0.7056846 0.5632433 0.7056847 0.344865 1 0.344865 0.7056847 0.7816216 0.7056847 0.5632434 1 0.5632433 0.7056847 0.7816217 0 0.5632433 0.7056846 0.5632434 0 0.2816218 0.7056847 0.2816217 0 0.5632433 0 1.60564e-7 0.7056847 0 0 0.2816215 0 0.7816217 0.7056846 0.7816217 0 1 0 0.5632433 0.7056847 0.5632433 1 0.344865 1 0.7816216 0.7056847 0.7816218 1 0.5632434 1 0.7816217 0 0.7816216 0.7056846 0.5632433 0.7056846 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |

1 0 0 2 0 1 0 0 2 7 1 3 4 1 4 6 1 5 3 2 6 5 2 7 7 2 8 1 3 9 4 3 10 5 3 11 7 4 12 2 4 13 3 4 14 6 5 15 0 5 16 2 5 17 1 0 18 3 0 19 2 0 20 7 1 21 5 1 22 4 1 23 3 2 24 1 2 25 5 2 26 1 3 27 0 3 28 4 3 29 7 4 30 6 4 31 2 4 32 6 5 33 4 5 34 0 5 35

92 |
93 |
94 |
95 |
96 | 97 | 98 | 99 | 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 |
-------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/depth_camera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/depth_camera.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/drive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/drive.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/face.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/face.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/foot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/foot.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/handle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/handle.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/hatch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/hatch.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/hip.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/hip.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/lidar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/lidar.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/lidar_cage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/lidar_cage.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/remote.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/remote.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/shank.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/shank.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/thigh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/thigh.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/top_shell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/top_shell.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/anymal_c/meshes/wide_angle_camera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/anymal_c/meshes/wide_angle_camera.jpg -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/cassie_license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jenna Reher, jreher@caltech.edu 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. -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/abduction.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/abduction.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/abduction_mirror.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/abduction_mirror.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/achilles-rod.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/achilles-rod.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/hip.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/hip.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/hip_mirror.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/hip_mirror.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/knee-output.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/knee-output.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/knee-output_mirror.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/knee-output_mirror.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/pelvis.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/pelvis.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/plantar-rod.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/plantar-rod.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/shin-bone.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/shin-bone.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/shin-bone_mirror.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/shin-bone_mirror.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/tarsus.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/tarsus.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/tarsus_mirror.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/tarsus_mirror.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/thigh.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/thigh.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/thigh_mirror.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/thigh_mirror.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/toe-output-crank.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/toe-output-crank.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/toe.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/toe.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/toe_mirror.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/toe_mirror.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/torso.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/torso.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/yaw.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/yaw.stl -------------------------------------------------------------------------------- /legged_gym/resources/robots/cassie/meshes/yaw_mirror.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P1terQ/LEEPS/f570ddabd1f47251839e3daefb93f5e72d707684/legged_gym/resources/robots/cassie/meshes/yaw_mirror.stl -------------------------------------------------------------------------------- /legged_gym/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages 2 | from distutils.core import setup 3 | 4 | setup( 5 | name='legged_gym', 6 | version='1.0.0', 7 | author='Nikita Rudin', 8 | license="BSD-3-Clause", 9 | packages=find_packages(), 10 | author_email='rudinn@ethz.ch', 11 | description='Isaac Gym environments for Legged Robots', 12 | install_requires=['isaacgym', 13 | 'rsl-rl', 14 | 'matplotlib'] 15 | ) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # This file may be used to create an environment using: 2 | # $ conda create --name --file 3 | # platform: linux-64 4 | _libgcc_mutex=0.1=main 5 | _openmp_mutex=5.1=1_gnu 6 | absl-py=2.0.0=pypi_0 7 | addict=2.4.0=pypi_0 8 | ansi2html=1.9.1=pypi_0 9 | appdirs=1.4.4=pypi_0 10 | asttokens=2.4.1=pypi_0 11 | attrs=23.1.0=pypi_0 12 | backcall=0.2.0=pypi_0 13 | blinker=1.7.0=pypi_0 14 | ca-certificates=2023.08.22=h06a4308_0 15 | certifi=2023.11.17=pypi_0 16 | charset-normalizer=3.3.2=pypi_0 17 | click=8.1.7=pypi_0 18 | comm=0.2.0=pypi_0 19 | configargparse=1.7=pypi_0 20 | contourpy=1.1.1=pypi_0 21 | cycler=0.12.1=pypi_0 22 | dash=2.14.2=pypi_0 23 | dash-core-components=2.0.0=pypi_0 24 | dash-html-components=2.0.0=pypi_0 25 | dash-table=5.0.0=pypi_0 26 | decorator=4.4.2=pypi_0 27 | docker-pycreds=0.4.0=pypi_0 28 | executing=2.0.1=pypi_0 29 | fastjsonschema=2.19.0=pypi_0 30 | flask=3.0.0=pypi_0 31 | fonttools=4.46.0=pypi_0 32 | gitdb=4.0.11=pypi_0 33 | gitpython=3.1.40=pypi_0 34 | idna=3.6=pypi_0 35 | imageio=2.33.1=pypi_0 36 | imageio-ffmpeg=0.4.9=pypi_0 37 | importlib-metadata=7.0.0=pypi_0 38 | importlib-resources=6.1.1=pypi_0 39 | inputs=0.5=pypi_0 40 | ipython=8.12.3=pypi_0 41 | ipywidgets=8.1.1=pypi_0 42 | isaacgym=1.0rc4=dev_0 43 | itsdangerous=2.1.2=pypi_0 44 | jedi=0.19.1=pypi_0 45 | jinja2=3.1.2=pypi_0 46 | joblib=1.3.2=pypi_0 47 | jsonschema=4.20.0=pypi_0 48 | jsonschema-specifications=2023.11.2=pypi_0 49 | jupyter-core=5.5.0=pypi_0 50 | jupyterlab-widgets=3.0.9=pypi_0 51 | kiwisolver=1.4.5=pypi_0 52 | ld_impl_linux-64=2.38=h1181459_1 53 | legged-gym=1.0.0=dev_0 54 | libffi=3.4.4=h6a678d5_0 55 | libgcc-ng=11.2.0=h1234567_1 56 | libgomp=11.2.0=h1234567_1 57 | libstdcxx-ng=11.2.0=h1234567_1 58 | loguru=0.7.2=pypi_0 59 | markupsafe=2.1.3=pypi_0 60 | matplotlib=3.7.4=pypi_0 61 | matplotlib-inline=0.1.6=pypi_0 62 | moviepy=1.0.3=pypi_0 63 | nbformat=5.7.0=pypi_0 64 | ncurses=6.4=h6a678d5_0 65 | nest-asyncio=1.5.8=pypi_0 66 | ninja=1.11.1.1=pypi_0 67 | numpy=1.20.3=pypi_0 68 | open3d=0.17.0=pypi_0 69 | opencv-python=4.8.1.78=pypi_0 70 | openssl=3.0.12=h7f8727e_0 71 | packaging=23.2=pypi_0 72 | pandas=2.0.3=pypi_0 73 | parso=0.8.3=pypi_0 74 | pexpect=4.9.0=pypi_0 75 | pickleshare=0.7.5=pypi_0 76 | pillow=10.1.0=pypi_0 77 | pip=23.3.1=py38h06a4308_0 78 | pkgutil-resolve-name=1.3.10=pypi_0 79 | platformdirs=4.1.0=pypi_0 80 | plotly=5.18.0=pypi_0 81 | proglog=0.1.10=pypi_0 82 | prompt-toolkit=3.0.41=pypi_0 83 | protobuf=4.25.1=pypi_0 84 | psutil=5.9.6=pypi_0 85 | ptyprocess=0.7.0=pypi_0 86 | pure-eval=0.2.2=pypi_0 87 | pyfqmr=0.2.0=pypi_0 88 | pygments=2.17.2=pypi_0 89 | pyparsing=3.1.1=pypi_0 90 | pyquaternion=0.9.9=pypi_0 91 | python=3.8.18=h955ad1f_0 92 | python-dateutil=2.8.2=pypi_0 93 | pytz=2023.3.post1=pypi_0 94 | pyyaml=6.0.1=pypi_0 95 | readline=8.2=h5eee18b_0 96 | referencing=0.32.0=pypi_0 97 | requests=2.31.0=pypi_0 98 | retrying=1.3.4=pypi_0 99 | rpds-py=0.13.2=pypi_0 100 | rsl-rl=1.0.2=dev_0 101 | scikit-learn=1.3.2=pypi_0 102 | scipy=1.10.1=pypi_0 103 | seaborn=0.13.1=pypi_0 104 | sentry-sdk=1.38.0=pypi_0 105 | setproctitle=1.3.3=pypi_0 106 | setuptools=68.0.0=py38h06a4308_0 107 | six=1.16.0=pypi_0 108 | smmap=5.0.1=pypi_0 109 | sqlite=3.41.2=h5eee18b_0 110 | stack-data=0.6.3=pypi_0 111 | tenacity=8.2.3=pypi_0 112 | threadpoolctl=3.2.0=pypi_0 113 | tk=8.6.12=h1ccaba5_0 114 | torch=1.10.0+cu113=pypi_0 115 | torchaudio=0.10.0+cu113=pypi_0 116 | torchvision=0.11.1+cu113=pypi_0 117 | tqdm=4.66.1=pypi_0 118 | traitlets=5.14.0=pypi_0 119 | typing-extensions=4.9.0=pypi_0 120 | tzdata=2023.3=pypi_0 121 | urllib3=2.1.0=pypi_0 122 | wandb=0.16.1=pypi_0 123 | wcwidth=0.2.12=pypi_0 124 | werkzeug=3.0.1=pypi_0 125 | wheel=0.41.2=py38h06a4308_0 126 | widgetsnbextension=4.0.9=pypi_0 127 | xz=5.4.5=h5eee18b_0 128 | zipp=3.17.0=pypi_0 129 | zlib=1.2.13=h5eee18b_0 130 | -------------------------------------------------------------------------------- /rsl_rl/.gitignore: -------------------------------------------------------------------------------- 1 | # IDEs 2 | .idea 3 | 4 | # builds 5 | *.egg-info 6 | 7 | # cache 8 | __pycache__ 9 | .pytest_cache 10 | 11 | # vs code 12 | .vscode -------------------------------------------------------------------------------- /rsl_rl/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021, ETH Zurich, Nikita Rudin 2 | Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | See licenses/dependencies for license information of dependencies of this package. -------------------------------------------------------------------------------- /rsl_rl/README.md: -------------------------------------------------------------------------------- 1 | # RSL RL 2 | Fast and simple implementation of RL algorithms, designed to run fully on GPU. 3 | This code is an evolution of `rl-pytorch` provided with NVIDIA's Isaac GYM. 4 | 5 | Only PPO is implemented for now. More algorithms will be added later. 6 | Contributions are welcome. 7 | 8 | ## Setup 9 | 10 | ``` 11 | git clone https://github.com/leggedrobotics/rsl_rl 12 | cd rsl_rl 13 | pip install -e . 14 | ``` 15 | 16 | ### Useful Links ### 17 | Example use case: https://github.com/leggedrobotics/legged_gym 18 | Project website: https://leggedrobotics.github.io/legged_gym/ 19 | Paper: https://arxiv.org/abs/2109.11978 20 | 21 | **Maintainer**: Nikita Rudin 22 | **Affiliation**: Robotic Systems Lab, ETH Zurich & NVIDIA 23 | **Contact**: rudinn@ethz.ch 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /rsl_rl/licenses/dependencies/numpy_license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2005-2021, NumPy Developers. 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 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of the NumPy Developers nor the names of any 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /rsl_rl/licenses/dependencies/torch_license.txt: -------------------------------------------------------------------------------- 1 | From PyTorch: 2 | 3 | Copyright (c) 2016- Facebook, Inc (Adam Paszke) 4 | Copyright (c) 2014- Facebook, Inc (Soumith Chintala) 5 | Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) 6 | Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) 7 | Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) 8 | Copyright (c) 2011-2013 NYU (Clement Farabet) 9 | Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) 10 | Copyright (c) 2006 Idiap Research Institute (Samy Bengio) 11 | Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) 12 | 13 | From Caffe2: 14 | 15 | Copyright (c) 2016-present, Facebook Inc. All rights reserved. 16 | 17 | All contributions by Facebook: 18 | Copyright (c) 2016 Facebook Inc. 19 | 20 | All contributions by Google: 21 | Copyright (c) 2015 Google Inc. 22 | All rights reserved. 23 | 24 | All contributions by Yangqing Jia: 25 | Copyright (c) 2015 Yangqing Jia 26 | All rights reserved. 27 | 28 | All contributions by Kakao Brain: 29 | Copyright 2019-2020 Kakao Brain 30 | 31 | All contributions from Caffe: 32 | Copyright(c) 2013, 2014, 2015, the respective contributors 33 | All rights reserved. 34 | 35 | All other contributions: 36 | Copyright(c) 2015, 2016 the respective contributors 37 | All rights reserved. 38 | 39 | Caffe2 uses a copyright model similar to Caffe: each contributor holds 40 | copyright over their contributions to Caffe2. The project versioning records 41 | all such contribution and copyright details. If a contributor wants to further 42 | mark their specific copyright on a particular contribution, they should 43 | indicate their copyright solely in the commit message of the change when it is 44 | committed. 45 | 46 | All rights reserved. 47 | 48 | Redistribution and use in source and binary forms, with or without 49 | modification, are permitted provided that the following conditions are met: 50 | 51 | 1. Redistributions of source code must retain the above copyright 52 | notice, this list of conditions and the following disclaimer. 53 | 54 | 2. Redistributions in binary form must reproduce the above copyright 55 | notice, this list of conditions and the following disclaimer in the 56 | documentation and/or other materials provided with the distribution. 57 | 58 | 3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America 59 | and IDIAP Research Institute nor the names of its contributors may be 60 | used to endorse or promote products derived from this software without 61 | specific prior written permission. 62 | 63 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 64 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 67 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 68 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 69 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 70 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 71 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 72 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 73 | POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/__init__.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 -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/algorithms/__init__.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 | from .ppo import PPO 32 | from .ppo_rma import PPORMA 33 | from .ppo_rma_blind import PPORMA_Blind 34 | from .ppo_rma_depth import PPORMADepth 35 | -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/env/__init__.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 | from .vec_env import VecEnv -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/env/vec_env.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 | from abc import ABC, abstractmethod 32 | import torch 33 | from typing import Tuple, Union 34 | 35 | # minimal interface of the environment 36 | class VecEnv(ABC): 37 | num_envs: int 38 | num_obs: int 39 | num_privileged_obs: int 40 | num_actions: int 41 | max_episode_length: int 42 | privileged_obs_buf: torch.Tensor 43 | obs_buf: torch.Tensor 44 | rew_buf: torch.Tensor 45 | reset_buf: torch.Tensor 46 | episode_length_buf: torch.Tensor # current episode duration 47 | extras: dict 48 | device: torch.device 49 | @abstractmethod 50 | def step(self, actions: torch.Tensor) -> Tuple[torch.Tensor, Union[torch.Tensor, None], torch.Tensor, torch.Tensor, dict]: 51 | pass 52 | @abstractmethod 53 | def reset(self, env_ids: Union[list, torch.Tensor]): 54 | pass 55 | @abstractmethod 56 | def get_observations(self) -> torch.Tensor: 57 | pass 58 | @abstractmethod 59 | def get_privileged_observations(self) -> Union[torch.Tensor, None]: 60 | pass -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/modules/__init__.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 | from .actor_critic import ActorCritic 32 | from .actor_critic_recurrent import ActorCriticRecurrent 33 | from .actor_critic_rma import ActorCriticRMA, Estimator 34 | from .actor_critic_rma_blind import ActorCriticRMA_Blind, Estimator_Blind 35 | from .depth_backbone import * 36 | 37 | -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/modules/actor_critic.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 numpy as np 32 | 33 | import torch 34 | import torch.nn as nn 35 | from torch.distributions import Normal 36 | from torch.nn.modules import rnn 37 | 38 | class ActorCritic(nn.Module): 39 | is_recurrent = False 40 | def __init__(self, num_actor_obs, 41 | num_critic_obs, 42 | num_actions, 43 | actor_hidden_dims=[256, 256, 256], 44 | critic_hidden_dims=[256, 256, 256], 45 | activation='elu', 46 | init_noise_std=1.0, 47 | **kwargs): 48 | if kwargs: 49 | print("ActorCritic.__init__ got unexpected arguments, which will be ignored: " + str([key for key in kwargs.keys()])) 50 | super(ActorCritic, self).__init__() 51 | 52 | activation = get_activation(activation) 53 | 54 | mlp_input_dim_a = num_actor_obs 55 | mlp_input_dim_c = num_critic_obs 56 | 57 | # Policy 58 | actor_layers = [] 59 | actor_layers.append(nn.Linear(mlp_input_dim_a, actor_hidden_dims[0])) 60 | actor_layers.append(activation) 61 | for l in range(len(actor_hidden_dims)): 62 | if l == len(actor_hidden_dims) - 1: 63 | actor_layers.append(nn.Linear(actor_hidden_dims[l], num_actions)) 64 | else: 65 | actor_layers.append(nn.Linear(actor_hidden_dims[l], actor_hidden_dims[l + 1])) 66 | actor_layers.append(activation) 67 | self.actor = nn.Sequential(*actor_layers) 68 | 69 | # Value function 70 | critic_layers = [] 71 | critic_layers.append(nn.Linear(mlp_input_dim_c, critic_hidden_dims[0])) 72 | critic_layers.append(activation) 73 | for l in range(len(critic_hidden_dims)): 74 | if l == len(critic_hidden_dims) - 1: 75 | critic_layers.append(nn.Linear(critic_hidden_dims[l], 1)) 76 | else: 77 | critic_layers.append(nn.Linear(critic_hidden_dims[l], critic_hidden_dims[l + 1])) 78 | critic_layers.append(activation) 79 | self.critic = nn.Sequential(*critic_layers) 80 | 81 | print(f"Actor MLP: {self.actor}") 82 | print(f"Critic MLP: {self.critic}") 83 | 84 | # Action noise 85 | self.std = nn.Parameter(init_noise_std * torch.ones(num_actions)) 86 | self.distribution = None 87 | # disable args validation for speedup 88 | Normal.set_default_validate_args = False 89 | 90 | # seems that we get better performance without init 91 | # self.init_memory_weights(self.memory_a, 0.001, 0.) 92 | # self.init_memory_weights(self.memory_c, 0.001, 0.) 93 | 94 | @staticmethod 95 | # not used at the moment 96 | def init_weights(sequential, scales): 97 | [torch.nn.init.orthogonal_(module.weight, gain=scales[idx]) for idx, module in 98 | enumerate(mod for mod in sequential if isinstance(mod, nn.Linear))] 99 | 100 | 101 | def reset(self, dones=None): 102 | pass 103 | 104 | def forward(self): 105 | raise NotImplementedError 106 | 107 | @property 108 | def action_mean(self): 109 | return self.distribution.mean 110 | 111 | @property 112 | def action_std(self): 113 | return self.distribution.stddev 114 | 115 | @property 116 | def entropy(self): 117 | return self.distribution.entropy().sum(dim=-1) 118 | 119 | def update_distribution(self, observations): 120 | mean = self.actor(observations) 121 | self.distribution = Normal(mean, mean*0. + self.std) 122 | 123 | def act(self, observations, **kwargs): 124 | self.update_distribution(observations) 125 | return self.distribution.sample() 126 | 127 | def get_actions_log_prob(self, actions): 128 | return self.distribution.log_prob(actions).sum(dim=-1) 129 | 130 | def act_inference(self, observations): 131 | actions_mean = self.actor(observations) 132 | return actions_mean 133 | 134 | def evaluate(self, critic_observations, **kwargs): 135 | value = self.critic(critic_observations) 136 | return value 137 | 138 | def get_activation(act_name): 139 | if act_name == "elu": 140 | return nn.ELU() 141 | elif act_name == "selu": 142 | return nn.SELU() 143 | elif act_name == "relu": 144 | return nn.ReLU() 145 | elif act_name == "crelu": 146 | return nn.ReLU() 147 | elif act_name == "lrelu": 148 | return nn.LeakyReLU() 149 | elif act_name == "tanh": 150 | return nn.Tanh() 151 | elif act_name == "sigmoid": 152 | return nn.Sigmoid() 153 | else: 154 | print("invalid activation function!") 155 | return None 156 | -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/modules/actor_critic_recurrent.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 numpy as np 32 | 33 | import torch 34 | import torch.nn as nn 35 | from torch.distributions import Normal 36 | from torch.nn.modules import rnn 37 | from .actor_critic import ActorCritic, get_activation 38 | from rsl_rl.utils import unpad_trajectories 39 | 40 | class ActorCriticRecurrent(ActorCritic): 41 | is_recurrent = True 42 | def __init__(self, num_actor_obs, 43 | num_critic_obs, 44 | num_actions, 45 | actor_hidden_dims=[256, 256, 256], 46 | critic_hidden_dims=[256, 256, 256], 47 | activation='elu', 48 | rnn_type='lstm', 49 | rnn_hidden_size=256, 50 | rnn_num_layers=1, 51 | init_noise_std=1.0, 52 | **kwargs): 53 | if kwargs: 54 | print("ActorCriticRecurrent.__init__ got unexpected arguments, which will be ignored: " + str(kwargs.keys()),) 55 | 56 | super().__init__(num_actor_obs=rnn_hidden_size, 57 | num_critic_obs=rnn_hidden_size, 58 | num_actions=num_actions, 59 | actor_hidden_dims=actor_hidden_dims, 60 | critic_hidden_dims=critic_hidden_dims, 61 | activation=activation, 62 | init_noise_std=init_noise_std) 63 | 64 | activation = get_activation(activation) 65 | 66 | self.memory_a = Memory(num_actor_obs, type=rnn_type, num_layers=rnn_num_layers, hidden_size=rnn_hidden_size) 67 | self.memory_c = Memory(num_critic_obs, type=rnn_type, num_layers=rnn_num_layers, hidden_size=rnn_hidden_size) 68 | 69 | print(f"Actor RNN: {self.memory_a}") 70 | print(f"Critic RNN: {self.memory_c}") 71 | 72 | def reset(self, dones=None): 73 | self.memory_a.reset(dones) 74 | self.memory_c.reset(dones) 75 | 76 | def act(self, observations, masks=None, hidden_states=None): 77 | input_a = self.memory_a(observations, masks, hidden_states) 78 | return super().act(input_a.squeeze(0)) 79 | 80 | def act_inference(self, observations): 81 | input_a = self.memory_a(observations) 82 | return super().act_inference(input_a.squeeze(0)) 83 | 84 | def evaluate(self, critic_observations, masks=None, hidden_states=None): 85 | input_c = self.memory_c(critic_observations, masks, hidden_states) 86 | return super().evaluate(input_c.squeeze(0)) 87 | 88 | def get_hidden_states(self): 89 | return self.memory_a.hidden_states, self.memory_c.hidden_states 90 | 91 | 92 | class Memory(torch.nn.Module): 93 | def __init__(self, input_size, type='lstm', num_layers=1, hidden_size=256): 94 | super().__init__() 95 | # RNN 96 | rnn_cls = nn.GRU if type.lower() == 'gru' else nn.LSTM 97 | self.rnn = rnn_cls(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers) 98 | self.hidden_states = None 99 | 100 | def forward(self, input, masks=None, hidden_states=None): 101 | batch_mode = masks is not None 102 | if batch_mode: 103 | # batch mode (policy update): need saved hidden states 104 | if hidden_states is None: 105 | raise ValueError("Hidden states not passed to memory module during policy update") 106 | out, _ = self.rnn(input, hidden_states) 107 | out = unpad_trajectories(out, masks) 108 | else: 109 | # inference mode (collection): use hidden states of last step 110 | out, self.hidden_states = self.rnn(input.unsqueeze(0), self.hidden_states) 111 | return out 112 | 113 | def reset(self, dones=None): 114 | # When the RNN is an LSTM, self.hidden_states_a is a list with hidden_state and cell_state 115 | for hidden_state in self.hidden_states: 116 | hidden_state[..., dones, :] = 0.0 -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/modules/depth_backbone.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | class DepthBackbone58x87(nn.Module): 5 | def __init__(self, scan_output_dim, num_frames=1): 6 | super().__init__() 7 | 8 | # todo 尝试把num_frames改成4试试看 9 | self.num_frames = num_frames 10 | activation_func = nn.ELU() 11 | 12 | self.image_compression = nn.Sequential( 13 | nn.Conv2d(in_channels=num_frames, out_channels=32, kernel_size=5), 14 | nn.MaxPool2d(kernel_size=2, stride=2), 15 | activation_func, 16 | nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3), 17 | activation_func, 18 | nn.Flatten(), 19 | nn.Linear(64*25*39, 128), 20 | activation_func, 21 | nn.Linear(128, scan_output_dim) 22 | ) 23 | self.output_activation = activation_func 24 | 25 | def forward(self, images: torch.Tensor): # [16, 58, 87] 26 | images_compressed = self.image_compression(images.unsqueeze(self.num_frames 27 | )) # [16, 32]. 这里unsqueeze(1)是因为nn.Conv2d的输入是[batch_size, channel, height, width], channel为帧数=1 28 | latent = self.output_activation(images_compressed) 29 | 30 | return latent 31 | 32 | class RecurrentDepthBackbone(nn.Module): 33 | def __init__(self, base_backbone, n_proprio, n_scan_encoder_outputdim) -> None: 34 | super().__init__() 35 | 36 | activation_func = nn.ELU() 37 | last_activation = nn.Tanh() 38 | self.base_backbone = base_backbone 39 | 40 | self.combination_mlp = nn.Sequential( 41 | nn.Linear(n_scan_encoder_outputdim + n_proprio, 128), #! cat depth and proprio 42 | activation_func, 43 | nn.Linear(128, n_scan_encoder_outputdim) 44 | ) 45 | 46 | self.rnn = nn.GRU(input_size=n_scan_encoder_outputdim, hidden_size=512, batch_first=True) 47 | 48 | #! 把输出层维度从34改成32,不输出yaw了 49 | self.output_mlp = nn.Sequential(nn.Linear(512, n_scan_encoder_outputdim), last_activation) 50 | 51 | self.hidden_states = None 52 | 53 | def forward(self, depth_image, proprioception): 54 | depth_conv = self.base_backbone(depth_image) 55 | depth_latent = self.combination_mlp(torch.cat([depth_conv, proprioception], dim=-1)) 56 | depth_latent, self.hidden_states = self.rnn(depth_latent[:, None, :], self.hidden_states) # None是在中间加一个维度 57 | depth_latent = self.output_mlp(depth_latent.squeeze(1)) 58 | 59 | return depth_latent 60 | 61 | def detach_hidden_states(self): 62 | self.hidden_states = self.hidden_states.detach().clone() 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/runners/__init__.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 | from .on_policy_runner import OnPolicyRunner 32 | from .on_policy_runner_depth import OnPolicyRunnerDepth 33 | from .on_policy_runner_wandb import OnPolicyRunnerWandb 34 | -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/storage/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 ETH Zurich, NVIDIA CORPORATION 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | from .rollout_storage import RolloutStorage -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/utils/__init__.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 | from .utils import split_and_pad_trajectories, unpad_trajectories -------------------------------------------------------------------------------- /rsl_rl/rsl_rl/utils/utils.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 | 33 | def split_and_pad_trajectories(tensor, dones): 34 | """ Splits trajectories at done indices. Then concatenates them and padds with zeros up to the length og the longest trajectory. 35 | Returns masks corresponding to valid parts of the trajectories 36 | Example: 37 | Input: [ [a1, a2, a3, a4 | a5, a6], 38 | [b1, b2 | b3, b4, b5 | b6] 39 | ] 40 | 41 | Output:[ [a1, a2, a3, a4], | [ [True, True, True, True], 42 | [a5, a6, 0, 0], | [True, True, False, False], 43 | [b1, b2, 0, 0], | [True, True, False, False], 44 | [b3, b4, b5, 0], | [True, True, True, False], 45 | [b6, 0, 0, 0] | [True, False, False, False], 46 | ] | ] 47 | 48 | Assumes that the inputy has the following dimension order: [time, number of envs, aditional dimensions] 49 | """ 50 | dones = dones.clone() 51 | dones[-1] = 1 52 | # Permute the buffers to have order (num_envs, num_transitions_per_env, ...), for correct reshaping 53 | flat_dones = dones.transpose(1, 0).reshape(-1, 1) 54 | 55 | # Get length of trajectory by counting the number of successive not done elements 56 | done_indices = torch.cat((flat_dones.new_tensor([-1], dtype=torch.int64), flat_dones.nonzero()[:, 0])) 57 | trajectory_lengths = done_indices[1:] - done_indices[:-1] 58 | trajectory_lengths_list = trajectory_lengths.tolist() 59 | # Extract the individual trajectories 60 | trajectories = torch.split(tensor.transpose(1, 0).flatten(0, 1),trajectory_lengths_list) 61 | padded_trajectories = torch.nn.utils.rnn.pad_sequence(trajectories) 62 | 63 | 64 | trajectory_masks = trajectory_lengths > torch.arange(0, tensor.shape[0], device=tensor.device).unsqueeze(1) 65 | return padded_trajectories, trajectory_masks 66 | 67 | def unpad_trajectories(trajectories, masks): 68 | """ Does the inverse operation of split_and_pad_trajectories() 69 | """ 70 | # Need to transpose before and after the masking to have proper reshaping 71 | return trajectories.transpose(1, 0)[masks.transpose(1, 0)].view(-1, trajectories.shape[0], trajectories.shape[-1]).transpose(1, 0) -------------------------------------------------------------------------------- /rsl_rl/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup(name='rsl_rl', 4 | version='1.0.2', 5 | author='Nikita Rudin', 6 | author_email='rudinn@ethz.ch', 7 | license="BSD-3-Clause", 8 | packages=find_packages(), 9 | description='Fast and simple RL algorithms implemented in pytorch', 10 | python_requires='>=3.6', 11 | install_requires=[ 12 | "torch>=1.4.0", 13 | "torchvision>=0.5.0", 14 | "numpy>=1.16.4" 15 | ], 16 | ) 17 | --------------------------------------------------------------------------------