├── faive_gym
├── __init__.py
├── cfg
│ ├── train
│ │ ├── FaiveHandP0PPO.yaml
│ │ ├── FaiveHandP0_bookPPO.yaml
│ │ ├── FaiveHandP0_crawlPPO.yaml
│ │ ├── FaiveHandP0_spherePPO.yaml
│ │ ├── FaiveHandP0_privilegedPPO.yaml
│ │ └── RobotHandDefaultPPO.yaml
│ ├── task
│ │ ├── FaiveHandP0_book.yaml
│ │ ├── FaiveHandP0_crawl.yaml
│ │ ├── FaiveHandP0.yaml
│ │ ├── FaiveHandP0_privileged.yaml
│ │ ├── FaiveHandP0_sphere.yaml
│ │ └── RobotHandDefault.yaml
│ └── config.yaml
├── .gitignore
├── scripts
│ ├── export_all_policies.py
│ └── export_policy.py
├── tasks
│ └── crawl.py
└── train.py
├── assets
├── README.md
├── faive_hand_p0
│ ├── mesh
│ │ ├── base.stl
│ │ ├── palm.stl
│ │ ├── ring_dp.stl
│ │ ├── ring_mp.stl
│ │ ├── ring_pp.stl
│ │ ├── index_dp.stl
│ │ ├── index_meta.stl
│ │ ├── index_mp.stl
│ │ ├── index_pp.stl
│ │ ├── middle_dp.stl
│ │ ├── middle_mp.stl
│ │ ├── middle_pp.stl
│ │ ├── pinky_dp.stl
│ │ ├── pinky_meta.stl
│ │ ├── pinky_mp.stl
│ │ ├── pinky_pp.stl
│ │ ├── ring_meta.stl
│ │ ├── thumb_base.stl
│ │ ├── thumb_dp.stl
│ │ ├── thumb_mp.stl
│ │ ├── thumb_pp.stl
│ │ └── middle_meta.stl
│ ├── README.md
│ ├── faive_hand.xml
│ ├── faive_structure.xml
│ └── faive_metadata.xml
├── urdf
│ ├── sphere_checkerboard.png
│ ├── sphere.mtl
│ ├── cube_multicolor.urdf
│ ├── sphere.urdf
│ ├── cube_multicolor.obj
│ └── cube_multicolor.mtl
├── objects_dext_manip
│ ├── pyramid.stl
│ ├── flat_pyr.stl
│ ├── hex_prism.stl
│ ├── octahedron.stl
│ ├── pentaprism.stl
│ ├── trig_prism.stl
│ ├── dodecahedron.stl
│ ├── tetrahedron.stl
│ ├── hex_prism.xml
│ ├── flat_pyr.xml
│ ├── trig_prism.xml
│ ├── octahedron.xml
│ ├── penta_prism.xml
│ ├── tetrahedron.xml
│ ├── dodecahedron.xml
│ ├── pyramid.xml
│ ├── stairs.urdf
│ ├── block_pyr.urdf
│ ├── pentaprism.urdf
│ ├── stell_dodeca.urdf
│ └── stell_dodeca.obj
└── mjcf
│ └── simple_book.xml
├── img
├── isaacgym_preview.gif
└── onnx_export_sample.svg
├── .github
└── pull_request_template.md
├── setup.py
├── LICENSE-NVIDIA
├── .gitignore
├── README.md
└── LICENSE
/faive_gym/__init__.py:
--------------------------------------------------------------------------------
1 | from .robot_hand import RobotHand
--------------------------------------------------------------------------------
/faive_gym/cfg/train/FaiveHandP0PPO.yaml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - RobotHandDefaultPPO
--------------------------------------------------------------------------------
/faive_gym/cfg/train/FaiveHandP0_bookPPO.yaml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - FaiveHandP0PPO
--------------------------------------------------------------------------------
/faive_gym/cfg/train/FaiveHandP0_crawlPPO.yaml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - FaiveHandP0PPO
--------------------------------------------------------------------------------
/assets/README.md:
--------------------------------------------------------------------------------
1 | MJCF and URDF models of robots and objects that are loaded into IsaacGym
--------------------------------------------------------------------------------
/img/isaacgym_preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/img/isaacgym_preview.gif
--------------------------------------------------------------------------------
/faive_gym/.gitignore:
--------------------------------------------------------------------------------
1 | runs/
2 | __pycache__/
3 | videos/
4 | wandb/
5 | exported_policies/
6 | models/
7 | recordings/
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/base.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/base.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/palm.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/palm.stl
--------------------------------------------------------------------------------
/assets/urdf/sphere_checkerboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/urdf/sphere_checkerboard.png
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/ring_dp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/ring_dp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/ring_mp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/ring_mp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/ring_pp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/ring_pp.stl
--------------------------------------------------------------------------------
/assets/objects_dext_manip/pyramid.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/objects_dext_manip/pyramid.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/index_dp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/index_dp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/index_meta.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/index_meta.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/index_mp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/index_mp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/index_pp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/index_pp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/middle_dp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/middle_dp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/middle_mp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/middle_mp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/middle_pp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/middle_pp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/pinky_dp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/pinky_dp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/pinky_meta.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/pinky_meta.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/pinky_mp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/pinky_mp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/pinky_pp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/pinky_pp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/ring_meta.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/ring_meta.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/thumb_base.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/thumb_base.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/thumb_dp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/thumb_dp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/thumb_mp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/thumb_mp.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/thumb_pp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/thumb_pp.stl
--------------------------------------------------------------------------------
/assets/objects_dext_manip/flat_pyr.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/objects_dext_manip/flat_pyr.stl
--------------------------------------------------------------------------------
/assets/objects_dext_manip/hex_prism.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/objects_dext_manip/hex_prism.stl
--------------------------------------------------------------------------------
/assets/objects_dext_manip/octahedron.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/objects_dext_manip/octahedron.stl
--------------------------------------------------------------------------------
/assets/objects_dext_manip/pentaprism.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/objects_dext_manip/pentaprism.stl
--------------------------------------------------------------------------------
/assets/objects_dext_manip/trig_prism.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/objects_dext_manip/trig_prism.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/mesh/middle_meta.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/faive_hand_p0/mesh/middle_meta.stl
--------------------------------------------------------------------------------
/assets/objects_dext_manip/dodecahedron.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/objects_dext_manip/dodecahedron.stl
--------------------------------------------------------------------------------
/assets/objects_dext_manip/tetrahedron.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-ethz/faive_gym_oss/HEAD/assets/objects_dext_manip/tetrahedron.stl
--------------------------------------------------------------------------------
/assets/faive_hand_p0/README.md:
--------------------------------------------------------------------------------
1 | # Faive Hand P0 model
2 | https://faive-robotics.com/
3 |
4 | MJCF model of the Faive Hand Proto 0 using simplified STL meshes which has sensitive features removed, but can still be simulated in MuJoCo and IsaacGym. SRL internal members can find the MJCF model for newer hands in the internal repo, faive-integration/model.
5 |
--------------------------------------------------------------------------------
/assets/urdf/sphere.mtl:
--------------------------------------------------------------------------------
1 | # Blender 3.5.1 MTL File: 'sphere.blend'
2 | # www.blender.org
3 |
4 | newmtl Material.004
5 | Ns 250.000000
6 | Ka 1.000000 1.000000 1.000000
7 | Ks 1.000000 1.000000 1.000000
8 | Kd 1.000000 1.000000 1.000000
9 | Ke 0.000000 0.000000 0.000000
10 | Ni 1.450000
11 | d 1.000000
12 | illum 2
13 | map_Kd sphere_checkerboard.png
14 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/hex_prism.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/flat_pyr.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/trig_prism.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/octahedron.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/penta_prism.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/tetrahedron.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/dodecahedron.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/pyramid.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | overwrite this text to describe your changes here
2 |
3 | ## checklist
4 | PR can be merged after all these are met
5 | - [ ] describe the changes (with screenshots if it helps)
6 | - [ ] If this PR modifies any part of the training, post the W&B results of the following experiments (post screenshot of the consecutive_successes)
7 | ```bash
8 | python train.py task=FaiveHandP0 capture_video=True force_render=False wandb_activate=True wandb_group=srl_ethz wandb_project=faive_hand wandb_name=faivehandp0_check
9 | ```
--------------------------------------------------------------------------------
/assets/urdf/cube_multicolor.urdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 | import os
3 |
4 | root_dir = os.path.dirname(os.path.realpath(__file__))
5 |
6 | INSTALL_REQUIRES = [
7 | "isaacgymenvs",
8 | "wandb<0.13"
9 | ]
10 |
11 | setup(
12 | name="faive_gym",
13 | author="Soft Robotics Lab",
14 | version="0.0.1",
15 | description="IsaacGym environments for the Faive Hand, intended to be used together with IsaacGymEnvs",
16 | python_requires=">=3.8.*",
17 | install_requires=INSTALL_REQUIRES,
18 | packages=find_packages("."),
19 | )
20 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/stairs.urdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/block_pyr.urdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/pentaprism.urdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/stell_dodeca.urdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/faive_gym/cfg/task/FaiveHandP0_book.yaml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - FaiveHandP0
3 | # a simple example of introducing an articulated object
4 | # doesn't learn any actual task, feel free to improve it...
5 |
6 | # if you want to get the joint angle of the articulated object, that can be computed by accessing the corresponding indices in self.dof_state
7 | # e.g. if the object is 1 DoF and was loaded (with create_actor) right after the robot
8 | # the object joint position and velocity can be accessed by self.dof_state.view(self.num_envs, -1, 2)[:, self.num_hand_dofs]
9 | env:
10 | object_type: ["simple_book"]
11 |
--------------------------------------------------------------------------------
/assets/urdf/sphere.urdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/faive_gym/cfg/train/FaiveHandP0_spherePPO.yaml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - FaiveHandP0PPO
3 |
4 | # enable asymmetric observations
5 | params:
6 | config:
7 | central_value_config:
8 | minibatch_size: ${..minibatch_size}
9 | mini_epochs: 5
10 | learning_rate: 5e-4
11 | lr_schedule: adaptive
12 | schedule_type: standard
13 | kl_threshold: 0.016
14 | clip_value: True
15 | normalize_input: True
16 | truncate_grads: True
17 |
18 | network:
19 | name: actor_critic
20 | central_value: True
21 | mlp:
22 | units: [512, 512, 256, 128]
23 | activation: elu
24 | d2rl: False
25 | initializer:
26 | name: default
27 | regularizer:
28 | name: N
--------------------------------------------------------------------------------
/assets/urdf/cube_multicolor.obj:
--------------------------------------------------------------------------------
1 | mtllib cube_multicolor.mtl
2 |
3 | v -0.5 -0.5 -0.5
4 | v -0.5 -0.5 0.5
5 | v -0.5 0.5 -0.5
6 | v -0.5 0.5 0.5
7 | v 0.5 -0.5 -0.5
8 | v 0.5 -0.5 0.5
9 | v 0.5 0.5 -0.5
10 | v 0.5 0.5 0.5
11 |
12 | vn -0.5 -0.5 0.5
13 | vn -0.5 -0.5 -0.5
14 | vn -0.5 0.5 -0.5
15 | vn -0.5 -0.5 -0.5
16 | vn 0.5 -0.5 -0.5
17 | vn -0.5 -0.5 -0.5
18 |
19 | usemtl red
20 | f 1//2 7//2 5//2
21 | f 1//2 3//2 7//2
22 | usemtl green
23 | f 1//6 4//6 3//6
24 | f 1//6 2//6 4//6
25 | usemtl blue
26 | f 3//3 8//3 7//3
27 | f 3//3 4//3 8//3
28 | usemtl yellow
29 | f 5//5 7//5 8//5
30 | f 5//5 8//5 6//5
31 | usemtl cyan
32 | f 1//4 5//4 6//4
33 | f 1//4 6//4 2//4
34 | usemtl white
35 | f 2//1 6//1 8//1
36 | f 2//1 8//1 4//1
37 |
--------------------------------------------------------------------------------
/assets/urdf/cube_multicolor.mtl:
--------------------------------------------------------------------------------
1 | newmtl red
2 | Ns 10.0
3 | Ka 1.0 1.0 1.0
4 | Kd 1.0 0.0 0.0
5 | Ks 0.125 0.125 0.125
6 | Ke 0.0 0.0 0.0
7 | Ni 1.0
8 | d 1.0
9 | illum 2
10 |
11 | newmtl green
12 | Ns 10.0
13 | Ka 1.0 1.0 1.0
14 | Kd 0.0 1.0 0.0
15 | Ks 0.125 0.125 0.125
16 | Ke 0.0 0.0 0.0
17 | Ni 1.0
18 | d 1.0
19 | illum 2
20 |
21 | newmtl blue
22 | Ns 10.0
23 | Ka 1.0 1.0 1.0
24 | Kd 0.0 0.0 1.0
25 | Ks 0.125 0.125 0.125
26 | Ke 0.0 0.0 0.0
27 | Ni 1.0
28 | d 1.0
29 | illum 2
30 |
31 | newmtl yellow
32 | Ns 10.0
33 | Ka 1.0 1.0 1.0
34 | Kd 1.0 1.0 0.0
35 | Ks 0.125 0.125 0.125
36 | Ke 0.0 0.0 0.0
37 | Ni 1.0
38 | d 1.0
39 | illum 2
40 |
41 | newmtl cyan
42 | Ns 10.0
43 | Ka 1.0 1.0 1.0
44 | Kd 0.0 1.0 1.0
45 | Ks 0.125 0.125 0.125
46 | Ke 0.0 0.0 0.0
47 | Ni 1.0
48 | d 1.0
49 | illum 2
50 |
51 | newmtl white
52 | Ns 10.0
53 | Ka 1.0 1.0 1.0
54 | Kd 1.0 1.0 1.0
55 | Ks 0.125 0.125 0.125
56 | Ke 0.0 0.0 0.0
57 | Ni 1.0
58 | d 1.0
59 | illum 2
60 |
--------------------------------------------------------------------------------
/assets/faive_hand_p0/faive_hand.xml:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/faive_gym/cfg/train/FaiveHandP0_privilegedPPO.yaml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - FaiveHandP0PPO
3 |
4 | params:
5 | config:
6 | central_value_config:
7 | # "Central Value Network" rl_games' name for the critic, when it has to receive a separate set of observations from the actor.
8 | # by defining the central_value_config, the central value is enabled, and rl_games reads from the state_buf for the critic observations and obs_buf for the actor observations.
9 | minibatch_size: ${..minibatch_size}
10 | mini_epochs: 5
11 | learning_rate: 5e-4
12 | lr_schedule: adaptive
13 | schedule_type: standard
14 | kl_threshold: 0.016
15 | clip_value: True
16 | normalize_input: True
17 | truncate_grads: True
18 |
19 | network:
20 | name: actor_critic
21 | central_value: True
22 | mlp:
23 | units: [512, 512, 256, 128]
24 | activation: elu
25 | d2rl: False
26 | initializer:
27 | name: default
28 | regularizer:
29 | name: None
--------------------------------------------------------------------------------
/assets/mjcf/simple_book.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/faive_gym/cfg/task/FaiveHandP0_crawl.yaml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - FaiveHandP0
3 | # use the Crawl class defined in tasks/crawl.py
4 | # see crawl.py for how to use
5 | # doesn't actually train, just an example of how to have a free base robot
6 | name: Crawl
7 | env:
8 | hand_fix_base: False
9 | hand_start_p: [0, 0, 0.1]
10 | hand_start_r: [0, 0, 0, 1]
11 |
12 | object_fix_base: True
13 | object_start_offset: [0, 0, 1] # move it to where it won't interfere with hand
14 |
15 | rewards:
16 | scales:
17 | action_penalty: 0.
18 | dof_acc_penalty: 0.
19 | dof_vel_penalty: 0.
20 | dof_trq_penalty: -0.0025
21 | success: 0.
22 | drop_penalty: 0.
23 | simple_hand_flat: 0.0
24 |
25 | reorienttask_obj_dist: 0.
26 | reorienttask_obj_rot: 0.
27 |
28 | crawl_forward_vel: 20.
29 | crawl_penalty_upsidedown: -0.1
30 |
31 | observations:
32 | # change to include more stuff about body
33 | actor_observations: ["dof_position", "dof_speed", "dof_force",
34 | "hand_quat", "hand_vel",
35 | "actions"]
36 |
37 | obs_dims:
38 | hand_quat: 4
39 | hand_vel: 6
--------------------------------------------------------------------------------
/faive_gym/scripts/export_all_policies.py:
--------------------------------------------------------------------------------
1 | '''
2 | Calls export_policy.py in a loop to export all policies that are in the models/ directory (beware: not the default
3 | saving dir to avoid saving all checkpoints) in the .onnx (ONNX) and .pt
4 | (TorchScript module) format. The output filename will be in the _YYYY-MM-DD_HH-mm-ss.pth/.onnx format
5 |
6 | specify task name as argument, e.g.:
7 | python export_all_policies.py FaiveHandP0_sphere
8 | '''
9 |
10 | import subprocess
11 | import glob
12 | import os
13 | import sys
14 | MODEL_FOLDER="../models"
15 |
16 | if len(sys.argv) < 2:
17 | print("Please specify the task name as argument, e.g.:")
18 | print("python export_all_policies.py FaiveHandP0_sphere")
19 | exit()
20 | TASK_NAME=sys.argv[1]
21 |
22 | # iterate through MODEL_FOLDER and export all .pth files as
23 | # .onnx and .pt
24 | for policy_file in glob.glob(os.path.join(MODEL_FOLDER, "*.pth")):
25 | name = os.path.splitext(os.path.basename(policy_file))[0]
26 | print("Found policy file ", policy_file, " exporting with name ", name, "...")
27 | command=f"python export_policy.py task={TASK_NAME} checkpoint={policy_file} wandb_name={name}"
28 | subprocess.run(command, shell=True)
29 | print("Successfully exported ", policy_file)
--------------------------------------------------------------------------------
/faive_gym/cfg/task/FaiveHandP0.yaml:
--------------------------------------------------------------------------------
1 | # load the default environment parameters, and override the ones we want to change
2 | defaults:
3 | - RobotHandDefault
4 |
5 | # The base RobotHand class suffices for the default P0 robot for now
6 | name: RobotHand
7 |
8 | env:
9 | numActions: 11
10 | object_start_offset: [0, -0.15, 0.07]
11 |
12 | asset:
13 | model_file: "faive_hand_p0/faive_hand.xml"
14 | force_sensor_names: ["index_dp", "middle_dp", "ring_dp", "pinky_dp", "thumb_dp"]
15 | pose_sensor_names: ["index_dp", "middle_dp", "ring_dp", "pinky_dp", "thumb_dp"]
16 |
17 | observations:
18 | obs_dims:
19 | dof_position: 11
20 | dof_pos_target: 11
21 | dof_speed: 11
22 | dof_speed_numerical: 11
23 | dof_force: 11
24 | obj_pos: 3
25 | obj_quat: 4
26 | obj_linvel: 3
27 | obj_angvel: 3
28 | obj_linvel_numerical: 3
29 | obj_angvel_numerical: 3
30 | goal_pos: 3
31 | goal_quat: 4
32 | goal_quat_diff: 4
33 | pose_sensor_pos: 15 # 3 * 5
34 | pose_sensor_quat: 20 # 4 * 5
35 | pose_sensor_linvel: 15 # 3 * 5
36 | pose_sensor_angvel: 15 # 3 * 5
37 | force_sensor_force: 30 # 6 * 5
38 | actions: 11
39 | obj_pose_history: 35 # 7 dof pose * 5 history length
40 | dof_pos_history: 55 # 11 dof joint * 5 history length
41 |
42 |
--------------------------------------------------------------------------------
/LICENSE-NVIDIA:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2018-2023, NVIDIA Corporation
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (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.
--------------------------------------------------------------------------------
/faive_gym/cfg/config.yaml:
--------------------------------------------------------------------------------
1 | # Task name - used to pick the class to load
2 | task_name: ${task.name}
3 | # experiment name. defaults to name of training config
4 | experiment: ''
5 |
6 | # if set to positive integer, overrides the default number of environments
7 | num_envs: ''
8 |
9 | # seed - set to -1 to choose random seed
10 | seed: 42
11 | # set to True for deterministic performance
12 | torch_deterministic: False
13 |
14 | # set the maximum number of learning iterations to train for. overrides default per-environment setting
15 | max_iterations: ''
16 |
17 |
18 | ## Device config
19 | # 'physx' or 'flex'
20 | physics_engine: 'physx'
21 | # whether to use cpu or gpu pipeline
22 | pipeline: 'gpu'
23 | # device for running physics simulation
24 | sim_device: 'cuda:0'
25 | # device to run RL
26 | rl_device: 'cuda:0'
27 | graphics_device_id: 0
28 |
29 | ## PhysX arguments
30 | num_threads: 4 # Number of worker threads per scene used by PhysX - for CPU PhysX only.
31 | solver_type: 1 # 0: pgs, 1: tgs
32 | num_subscenes: 4 # Splits the simulation into N physics scenes and runs each one in a separate thread
33 |
34 | # RLGames Arguments
35 | # test - if set, run policy in inference mode (requires setting checkpoint to load)
36 | test: False
37 | # used to set checkpoint path
38 | checkpoint: ''
39 | # custom to genetic_hand: if set, always start from epoch 0 no matter what epoch is in the checkpoint, useful for transfer learning from trained policy
40 | always_start_from_epoch0: False
41 | # set to True to use multi-gpu horovod training
42 | multi_gpu: False
43 |
44 | wandb_activate: False
45 | wandb_group: 'srl_ethz'
46 | wandb_name: ${train.params.config.name}
47 | wandb_entity: ''
48 | wandb_project: ''
49 | capture_video: False
50 | capture_video_freq: 2000
51 | capture_video_len: 100
52 | force_render: True
53 |
54 | # disables rendering
55 | headless: False
56 |
57 | # set default task and default training config based on task
58 | defaults:
59 | - task: FaiveHandP0
60 | - train: ${task}PPO
61 | - hydra/job_logging: disabled
62 |
63 | # set the directory where the output files get saved
64 | hydra:
65 | output_subdir: null
66 | run:
67 | dir: .
--------------------------------------------------------------------------------
/faive_gym/tasks/crawl.py:
--------------------------------------------------------------------------------
1 | from faive_gym.robot_hand import RobotHand
2 | from isaacgymenvs.utils.torch_jit_utils import (
3 | quat_rotate_inverse,
4 | quat_conjugate,
5 | quat_mul,
6 | quat_to_angle_axis,
7 | )
8 | import torch
9 |
10 | """
11 | not a serious task, just intended as an example of
12 | - how to make a custom task that is derived from the RobotHand class
13 | - how to create environments where the robot hand doesn't have a fixed base
14 |
15 | The robot hand learns to crawl on the floor like a horror film - except it doesn't even learn to crawl right now, see if you can make it work...
16 | """
17 |
18 | class Crawl(RobotHand):
19 |
20 | def check_termination(self):
21 | # override the function defined in RobotHand
22 |
23 | # check if hand is upside down (z axis is facing up)
24 | # do a bit hacky but easy to implement check
25 | hand_rot = self.hand_pose[:, 3:]
26 | angle, axis = quat_to_angle_axis(hand_rot)
27 | self.upside_down_buf = (torch.norm(axis[:, :2], dim=1) > 0.9) & (angle > 0.8 * 3.14)
28 |
29 | timeout_buf = self.progress_buf > self.max_episode_length - 1
30 |
31 | self.reset_goal_buf[:] = 0
32 | self.reset_buf[:] = self.upside_down_buf | timeout_buf
33 |
34 |
35 | def _init_buffers(self):
36 | super()._init_buffers()
37 | # move forward (in the direction of the fingertip, which is the y axis) 10 cm/s
38 | self.target_vel = torch.tensor([0., 0.07, -0.07], dtype=torch.float32, device=self.device)
39 |
40 | def _reward_crawl_penalty_upsidedown(self):
41 | return self.upside_down_buf
42 |
43 | def _reward_crawl_forward_vel(self):
44 | quat = self.hand_pose[:, 3:]
45 | lin_vel = self.hand_vel[:, :3]
46 | local_vel = quat_rotate_inverse(quat, lin_vel)
47 | vel_error = torch.sum(torch.square(self.target_vel - local_vel), dim=1)
48 | return torch.exp(-vel_error/0.05)
49 |
50 | def _observation_hand_quat(self):
51 | return self.hand_pose[:, 3:]
52 |
53 | def _observation_hand_vel(self):
54 | return self.hand_vel
55 |
56 |
--------------------------------------------------------------------------------
/faive_gym/cfg/train/RobotHandDefaultPPO.yaml:
--------------------------------------------------------------------------------
1 | # Define the default training configuration for the RobotHand task.
2 | # configurations for other robotic hands can be defined by first inheriting from this config (see FaiveHandP0PPO.yaml for an example)
3 |
4 | params:
5 | seed: ${...seed}
6 |
7 | algo:
8 | name: a2c_continuous
9 |
10 | model:
11 | name: continuous_a2c_logstd
12 |
13 | network:
14 | name: actor_critic
15 | separate: False
16 |
17 | space:
18 | continuous:
19 | mu_activation: None
20 | sigma_activation: None
21 | mu_init:
22 | name: default
23 | sigma_init:
24 | name: const_initializer
25 | val: 0
26 | fixed_sigma: True
27 |
28 | mlp:
29 | units: [512, 512, 256, 128]
30 | activation: elu
31 | d2rl: False
32 |
33 | initializer:
34 | name: default
35 | regularizer:
36 | name: None
37 |
38 | load_checkpoint: ${if:${...checkpoint},True,False} # flag which sets whether to load the checkpoint
39 | load_path: ${...checkpoint} # path to the checkpoint to load
40 |
41 | config:
42 | name: ${resolve_default:FaiveHand,${....experiment}}
43 | full_experiment_name: ${.name}
44 | env_name: rlgpu
45 | multi_gpu: ${....multi_gpu}
46 | ppo: True
47 | mixed_precision: False
48 | normalize_input: True
49 | normalize_value: True
50 | value_bootstrap: True
51 | num_actors: ${....task.env.numEnvs}
52 | normalize_advantage: True
53 | gamma: 0.99
54 | tau: 0.95
55 | learning_rate: 5e-4
56 | lr_schedule: adaptive
57 | schedule_type: standard
58 | kl_threshold: 0.016
59 | score_to_win: 100000
60 | max_epochs: ${resolve_default:5000,${....max_iterations}}
61 | save_best_after: 100
62 | save_frequency: 200
63 | print_stats: True
64 | grad_norm: 1.0
65 | entropy_coef: 0.0
66 | truncate_grads: True
67 | e_clip: 0.2
68 | horizon_length: 8
69 | minibatch_size: ${....task.env.numEnvs}
70 | mini_epochs: 5
71 | critic_coef: 4
72 | clip_value: True
73 | seq_len: 4
74 | bounds_loss_coef: 0.0001
75 | reward_shaper:
76 | scale_value: 1
77 |
78 | player:
79 | #render: True
80 | deterministic: True
81 | games_num: 100000
82 | print_stats: True
83 |
84 | # custom to faive-isaac, parameters for training the student policy
85 | student:
86 | learning_rate: 1e-5
87 | # how many hiddent units the student policy has before it gets sent to the layers copied from the teacher
88 | custom_layers_units: [512, 256, 128]
89 | # how many layers to copy from the end of the teacher policy to the end of the student policy
90 | num_layers_to_copy_from_teacher: 2
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # poetry
98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102 | #poetry.lock
103 |
104 | # pdm
105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106 | #pdm.lock
107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108 | # in version control.
109 | # https://pdm.fming.dev/#use-with-ide
110 | .pdm.toml
111 |
112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113 | __pypackages__/
114 |
115 | # Celery stuff
116 | celerybeat-schedule
117 | celerybeat.pid
118 |
119 | # SageMath parsed files
120 | *.sage.py
121 |
122 | # Environments
123 | .env
124 | .venv
125 | env/
126 | venv/
127 | ENV/
128 | env.bak/
129 | venv.bak/
130 |
131 | # Spyder project settings
132 | .spyderproject
133 | .spyproject
134 |
135 | # Rope project settings
136 | .ropeproject
137 |
138 | # mkdocs documentation
139 | /site
140 |
141 | # mypy
142 | .mypy_cache/
143 | .dmypy.json
144 | dmypy.json
145 |
146 | # Pyre type checker
147 | .pyre/
148 |
149 | # pytype static type analyzer
150 | .pytype/
151 |
152 | # Cython debug symbols
153 | cython_debug/
154 |
155 | # PyCharm
156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158 | # and can be added to the global gitignore or merged into this file. For a more nuclear
159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160 | #.idea/
161 |
--------------------------------------------------------------------------------
/faive_gym/cfg/task/FaiveHandP0_privileged.yaml:
--------------------------------------------------------------------------------
1 | # sample which sends different observations to the actor and critic
2 | # since the critic can use privileged information only available to the simulator
3 | defaults:
4 | - FaiveHandP0
5 | env:
6 | controlFrequencyInv: 3
7 |
8 | observations:
9 | asymmetric_observations: True
10 | # actor uses "history" rather than velocity, to hopefully make policy more robust to noise
11 | # also it does not use force observations, which are not available to the real robot (yet)
12 | actor_observations: ["dof_position", "dof_speed", "dof_pos_target",
13 | "obj_quat", "obj_angvel_numerical",
14 | "goal_pos", "goal_quat", "goal_quat_diff",
15 | "actions"]
16 |
17 | critic_observations: ["dof_position", "dof_speed", "dof_force", "dof_pos_target",
18 | "obj_pos", "obj_quat", "obj_linvel", "obj_angvel_numerical",
19 | "goal_pos", "goal_quat", "goal_quat_diff",
20 | "pose_sensor_pos", "pose_sensor_quat", "pose_sensor_linvel", "pose_sensor_angvel", "force_sensor_force",
21 | "actions"]
22 |
23 | task:
24 | randomize: True
25 | randomization_params:
26 | # most params are just copied from the ShadowHandOpenAI_FF.yaml
27 | frequency: 2048 # Define how many simulation steps between generating new randomizations
28 | observations:
29 | range: [0, .08] # sampled every step, regardless of "frequency". mean and variance, if distribution is "gaussian"
30 | range_correlated: [0, .05] # updated every "frequency" steps, can simulate bias
31 | operation: "additive"
32 | distribution: "gaussian"
33 | actions:
34 | range: [0., .05]
35 | range_correlated: [0, .05]
36 | operation: "additive"
37 | distribution: "gaussian"
38 | actor_params:
39 | hand: # this must match the name defined in create_actor
40 | color: True
41 | tendon_properties:
42 | damping:
43 | range: [0.75, 1.5]
44 | operation: "scaling"
45 | distribution: "loguniform"
46 | stiffness:
47 | range: [0.75, 1.5]
48 | operation: "scaling"
49 | distribution: "loguniform"
50 | dof_properties:
51 | damping:
52 | range: [0.75, 1.5]
53 | operation: "scaling"
54 | distribution: "loguniform"
55 | stiffness:
56 | range: [0.75, 1.5]
57 | operation: "scaling"
58 | distribution: "loguniform"
59 | lower:
60 | range: [0, 0.01]
61 | operation: "additive"
62 | distribution: "gaussian"
63 | upper:
64 | range: [0, 0.01]
65 | operation: "additive"
66 | distribution: "gaussian"
67 | rigid_body_properties:
68 | mass:
69 | range: [0.75, 1.25]
70 | operation: "scaling"
71 | distribution: "uniform"
72 | setup_only: True # Property will only be randomized once before simulation is started. See Domain Randomization Documentation for more info.
73 | rigid_shape_properties:
74 | friction:
75 | num_buckets: 250
76 | range: [0.75, 1.25]
77 | operation: "scaling"
78 | distribution: "uniform"
79 | object: # this must match the name defined in create_actor
80 | scale:
81 | range: [0.99, 1.01] # make the average size slightly larger to compensate for lack of silicone fingertip in simulation
82 | operation: "scaling"
83 | distribution: "uniform"
84 | setup_only: True
85 | rigid_body_properties:
86 | mass:
87 | range: [0.75, 1.25]
88 | operation: "scaling"
89 | distribution: "uniform"
90 | setup_only: True
91 | rigid_shape_properties:
92 | friction:
93 | num_buckets: 250
94 | range: [0.7, 1.3]
95 | operation: "scaling"
96 | distribution: "uniform"
97 |
--------------------------------------------------------------------------------
/faive_gym/cfg/task/FaiveHandP0_sphere.yaml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - FaiveHandP0
3 |
4 | # in-hand rotation of a sphere around a fixed axis
5 | # targeted towards sim2real;
6 | # - uses asymmetric observations where the actor only receives proprioceptive measurements
7 | # - use lower control frequency
8 | # - a lot of noise in the observations, action, and domain randomization
9 | # - the task is rather sensitive to the random seed, try with 3 or 4 and use the best result?
10 |
11 | env:
12 | object_type: ["sphere"]
13 | controlFrequencyInv: 3 # 20 Hz control
14 | use_relative_control: True
15 | relative_control_speed_scale: 6.0 # 6 rad/s max
16 | x_rotation_dir: 1.0 # rotation direction: positive is the same direction as TEDx
17 | # set the joint range that the hand hardware could actually achieve
18 | actuated_dof_range_override: [[0, 2.27], [-1.05, 0.698], [0, 0.567],
19 | [0, 0.567], [0, 0.742],
20 | [0, 0.567], [0, 0.742],
21 | [0, 0.567], [0, 0.742],
22 | [0, 0.567], [0, 0.742],
23 | ]
24 |
25 | rewards:
26 | scales:
27 | action_penalty: -0.002
28 | dof_acc_penalty: 0
29 | dof_vel_penalty: 0
30 | dof_trq_penalty: -0.01
31 | success: 0
32 | drop_penalty: -1.
33 | simple_hand_flat: 0
34 |
35 | reorienttask_obj_dist: 0
36 | reorienttask_obj_rot: 0
37 |
38 | rottask_obj_xrotvel: 0.01
39 | success_tolerance: 0
40 |
41 | observations:
42 | asymmetric_observations: True
43 | # use only physically possible observations
44 | actor_observations: ["dof_pos_history",
45 | "dof_pos_target",
46 | "actions"]
47 |
48 | critic_observations: ["dof_position", "dof_speed", "dof_force", "dof_pos_target",
49 | "obj_pos", "obj_quat", "obj_linvel", "obj_angvel_numerical",
50 | "pose_sensor_pos", "pose_sensor_quat", "pose_sensor_linvel", "pose_sensor_angvel", "force_sensor_force",
51 | "actions"]
52 |
53 | logging:
54 | rt_plt: False
55 | buf_len_s: 0.6
56 | num_rows: 1
57 | num_cols: 5 # multiplication of rows and cols should be equal to the
58 | # number of measurements in the measurements list below
59 | measurements: ["_observation_dof_position_thumb_cmc", "_observation_dof_position_thumb_mcp", "_observation_dof_position_thumb_pip", "_observation_dof_position_index_mcp", "_observation_dof_position_index_pip"]
60 | units: ["rad", "rad", "rad", "rad", "rad"]
61 |
62 | # visualization settings
63 | visualization:
64 | camera_pos_start: [11, 11, 0.8]
65 | camera_target_start: [12.5, 12.5, 0.35]
66 | move_camera: False
67 | camera_movement_vector: [.005, 0.005, 0.0]
68 |
69 | task:
70 | randomize: True
71 | randomization_params:
72 | # most params are just copied from the ShadowHandOpenAI_FF.yaml
73 | frequency: 720 # Define how many simulation steps between generating new randomizations
74 | observations:
75 | range: [0, .08] # sampled every step, regardless of "frequency". mean and variance, if distribution is "gaussian"
76 | range_correlated: [0, .05] # updated every "frequency" steps, can simulate bias
77 | operation: "additive"
78 | distribution: "gaussian"
79 | actions:
80 | range: [0., .05]
81 | range_correlated: [0, .05]
82 | operation: "additive"
83 | distribution: "gaussian"
84 | actor_params:
85 | hand: # this must match the name defined in create_actor
86 | color: True
87 | tendon_properties:
88 | damping:
89 | range: [0.3, 3.0]
90 | operation: "scaling"
91 | distribution: "loguniform"
92 | stiffness:
93 | range: [0.75, 1.5]
94 | operation: "scaling"
95 | distribution: "loguniform"
96 | dof_properties:
97 | damping:
98 | range: [0.3, 3.0]
99 | operation: "scaling"
100 | distribution: "loguniform"
101 | stiffness:
102 | range: [0.75, 1.5]
103 | operation: "scaling"
104 | distribution: "loguniform"
105 | lower:
106 | range: [0, 0.01]
107 | operation: "additive"
108 | distribution: "gaussian"
109 | upper:
110 | range: [0, 0.01]
111 | operation: "additive"
112 | distribution: "gaussian"
113 | rigid_body_properties:
114 | mass:
115 | range: [0.5, 1.5]
116 | operation: "scaling"
117 | distribution: "uniform"
118 | setup_only: True # Property will only be randomized once before simulation is started. See Domain Randomization Documentation for more info.
119 | rigid_shape_properties:
120 | friction:
121 | num_buckets: 250
122 | range: [0.7, 1.3]
123 | operation: "scaling"
124 | distribution: "uniform"
125 | object: # this must match the name defined in create_actor
126 | scale:
127 | # shift the range a bit towards the small size because other spherical objects are smaller than gacha ball
128 | range: [0.92, 1.05]
129 | operation: "scaling"
130 | distribution: "uniform"
131 | setup_only: True
132 | rigid_body_properties:
133 | mass:
134 | range: [0.5, 1.5]
135 | operation: "scaling"
136 | distribution: "uniform"
137 | setup_only: True
138 | rigid_shape_properties:
139 | friction:
140 | num_buckets: 250
141 | range: [0.7, 1.3]
142 | operation: "scaling"
143 | distribution: "uniform"
144 |
--------------------------------------------------------------------------------
/faive_gym/train.py:
--------------------------------------------------------------------------------
1 | # train.py
2 | # Script to train policies in Isaac Gym
3 | #
4 | # Copyright (c) 2018-2022, NVIDIA Corporation
5 | # All rights reserved.
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | #
10 | # 1. Redistributions of source code must retain the above copyright notice, this
11 | # list of conditions and the following disclaimer.
12 | #
13 | # 2. Redistributions in binary form must reproduce the above copyright notice,
14 | # this list of conditions and the following disclaimer in the documentation
15 | # and/or other materials provided with the distribution.
16 | #
17 | # 3. Neither the name of the copyright holder nor the names of its
18 | # contributors may be used to endorse or promote products derived from
19 | # this software without specific prior written permission.
20 | #
21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 | # OR TORT (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.
31 |
32 | # copied from IsaacGymEnvs with slight modifications
33 |
34 | import datetime
35 | import isaacgym
36 |
37 | import os
38 | import hydra
39 | import yaml
40 | from omegaconf import DictConfig, OmegaConf
41 | from hydra.utils import to_absolute_path
42 | import gym
43 |
44 | from isaacgymenvs.utils.reformat import omegaconf_to_dict, print_dict
45 |
46 | from isaacgymenvs.utils.utils import set_np_formatting, set_seed
47 |
48 | # register custom tasks for faive_gym here
49 | from isaacgymenvs.tasks import isaacgym_task_map
50 | from faive_gym.robot_hand import RobotHand
51 | from faive_gym.tasks.crawl import Crawl
52 | isaacgym_task_map["RobotHand"] = RobotHand
53 | isaacgym_task_map["Crawl"] = Crawl
54 |
55 | ## OmegaConf & Hydra Config
56 |
57 | # Resolvers used in hydra configs (see https://omegaconf.readthedocs.io/en/2.1_branch/usage.html#resolvers)
58 | @hydra.main(config_name="config", config_path="./cfg")
59 | def launch_rlg_hydra(cfg: DictConfig):
60 | from isaacgymenvs.utils.rlgames_utils import RLGPUEnv, RLGPUAlgoObserver, get_rlgames_env_creator
61 | from rl_games.common import env_configurations, vecenv
62 | from rl_games.torch_runner import Runner
63 | from rl_games.algos_torch import model_builder
64 | from isaacgymenvs.learning import amp_continuous
65 | from isaacgymenvs.learning import amp_players
66 | from isaacgymenvs.learning import amp_models
67 | from isaacgymenvs.learning import amp_network_builder
68 | import isaacgymenvs
69 |
70 | time_str = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
71 | run_name = f"{cfg.wandb_name}_{time_str}"
72 |
73 | # ensure checkpoints can be specified as relative paths
74 | if cfg.checkpoint:
75 | cfg.checkpoint = to_absolute_path(cfg.checkpoint)
76 |
77 | cfg_dict = omegaconf_to_dict(cfg)
78 | print_dict(cfg_dict)
79 |
80 | # set numpy formatting for printing only
81 | set_np_formatting()
82 |
83 | rank = int(os.getenv("LOCAL_RANK", "0"))
84 | if cfg.multi_gpu:
85 | # torchrun --standalone --nnodes=1 --nproc_per_node=2 train.py
86 | cfg.sim_device = f'cuda:{rank}'
87 | cfg.rl_device = f'cuda:{rank}'
88 |
89 | # sets seed. if seed is -1 will pick a random one
90 | cfg.seed += rank
91 | cfg.seed = set_seed(cfg.seed, torch_deterministic=cfg.torch_deterministic, rank=rank)
92 |
93 | if cfg.wandb_activate and rank == 0:
94 | # Make sure to install WandB if you actually use this.
95 | import wandb
96 |
97 | run = wandb.init(
98 | project=cfg.wandb_project,
99 | group=cfg.wandb_group,
100 | entity=cfg.wandb_entity,
101 | config=cfg_dict,
102 | sync_tensorboard=True,
103 | name=run_name,
104 | resume="allow",
105 | monitor_gym=True,
106 | )
107 |
108 | def create_env_thunk(**kwargs):
109 | envs = isaacgymenvs.make(
110 | cfg.seed,
111 | cfg.task_name,
112 | cfg.task.env.numEnvs,
113 | cfg.sim_device,
114 | cfg.rl_device,
115 | cfg.graphics_device_id,
116 | cfg.headless,
117 | cfg.multi_gpu,
118 | cfg.capture_video,
119 | cfg.force_render,
120 | cfg,
121 | **kwargs,
122 | )
123 | if cfg.capture_video:
124 | envs.is_vector_env = True
125 | envs = gym.wrappers.RecordVideo(
126 | envs,
127 | f"videos/{run_name}",
128 | step_trigger=lambda step: step % cfg.capture_video_freq == 0,
129 | video_length=cfg.capture_video_len,
130 | )
131 | return envs
132 |
133 | # register the rl-games adapter to use inside the runner
134 | vecenv.register('RLGPU',
135 | lambda config_name, num_actors, **kwargs: RLGPUEnv(config_name, num_actors, **kwargs))
136 | env_configurations.register('rlgpu', {
137 | 'vecenv_type': 'RLGPU',
138 | 'env_creator': create_env_thunk,
139 | })
140 |
141 | # register new AMP network builder and agent
142 | def build_runner(algo_observer):
143 | runner = Runner(algo_observer)
144 | runner.algo_factory.register_builder('amp_continuous', lambda **kwargs : amp_continuous.AMPAgent(**kwargs))
145 | runner.player_factory.register_builder('amp_continuous', lambda **kwargs : amp_players.AMPPlayerContinuous(**kwargs))
146 | model_builder.register_model('continuous_amp', lambda network, **kwargs : amp_models.ModelAMPContinuous(network))
147 | model_builder.register_network('amp', lambda **kwargs : amp_network_builder.AMPBuilder())
148 |
149 | return runner
150 |
151 | rlg_config_dict = omegaconf_to_dict(cfg.train)
152 |
153 | # convert CLI arguments into dictionory
154 | # create runner and set the settings
155 | runner = build_runner(RLGPUAlgoObserver())
156 | runner.load(rlg_config_dict)
157 | runner.reset()
158 |
159 | # dump config dict
160 | experiment_dir = os.path.join('runs', cfg.train.params.config.name)
161 | os.makedirs(experiment_dir, exist_ok=True)
162 | with open(os.path.join(experiment_dir, 'config.yaml'), 'w') as f:
163 | f.write(OmegaConf.to_yaml(cfg))
164 |
165 | runner.run({
166 | 'train': not cfg.test,
167 | 'play': cfg.test,
168 | 'checkpoint' : cfg.checkpoint,
169 | 'sigma' : None
170 | })
171 |
172 | if cfg.wandb_activate and rank == 0:
173 | wandb.finish()
174 |
175 | if __name__ == "__main__":
176 | launch_rlg_hydra()
177 |
--------------------------------------------------------------------------------
/faive_gym/cfg/task/RobotHandDefault.yaml:
--------------------------------------------------------------------------------
1 | # Define the default configuration for the RobotHand task.
2 | # configurations for other robotic hands can be defined by first inheriting from this config (see FaiveHandP0.yaml for an example)
3 |
4 | # define in child config- the name of the Python VecTask class used
5 | name: None
6 |
7 | physics_engine: ${..physics_engine}
8 |
9 | # if given, will override the device setting in gym.
10 | env:
11 | numEnvs: ${resolve_default:4096,${...num_envs}}
12 | numObservations: None # this will be overwritten in robot_hand.py
13 | numStates: None # this will be overwritten in robot_hand.py
14 | numActions: None # define in child config
15 | env_spacing: 0.2
16 | episode_length_s: 10 # episode length in seconds
17 | aggregate_mode: True # provides a "modest performance boost", see isaacgym/docs/programming/physics.html
18 |
19 | object_type: ["block"] # block, egg, pen, sphere, ... (check asset_files_dict of robot_hand.py for all options)
20 | use_relative_control: False
21 | relative_control_speed_scale: 5.0 # 5 rad/s max joint rotation speed
22 |
23 | enable_debug_viz: False
24 | # for contact viz to work, CPU pipeline must be used, and contact_collection must be set to 1 or 2 (there are assertions in the code that ensure this)
25 | enable_contact_viz: False
26 |
27 | controlFrequencyInv: 1 # how many steps to skip between control updates (i.e. decimation)
28 | hand_friction: 1.0 # this sets the friction and torsion_friction of the hand. 1.0 is the default value used for trifinger.
29 | object_start_offset: [0, 0, 0] # position of object initial position, relative to the hand
30 | actuated_dof_range_override: None # optionally use a smaller joint range of actuation, helpful if the real robot can't achieve the full range of motion
31 |
32 | # whether to fix objects in the world, or let them loose
33 | object_fix_base: False
34 | hand_fix_base: True
35 |
36 | # hand start pose position (x, y, z)
37 | hand_start_p: [0, 0, 0.5]
38 | # hand start pose quaternion (x, y, z, w)
39 | # rotate 200 degrees around x axis to make palm face up, and slightly tilt it downwards
40 | hand_start_r: [0.9848078, 0, 0, -0.1736482]
41 |
42 | asset:
43 | # define in child config- the robot model filepath, relative to assets directory
44 | model_file: None
45 | # define in child config- body name that each force and pose sensor are attached to
46 | # (usually the fingertips)
47 | force_sensor_names: []
48 | pose_sensor_names: []
49 |
50 |
51 | logging:
52 | # Defines the properties of online logging.
53 | rt_plt: False
54 | record_dofs: False
55 | record_observations: False
56 | record_length: 10
57 | buf_len_s: 0.6
58 | num_rows: 2
59 | num_cols: 3 # multiplication of rows and cols should be equal to the
60 | # number of measurements in the measurements list below
61 | measurements: ["_observation_dof_position_stat_thumb_mcp",
62 | "_observation_dof_speed_middle_pip",
63 | "_observation_dof_force_pinky_mcp",
64 | "_reward_dist_stat",
65 | "_observation_fingertip_force_stat_thumb",
66 | "_observation_obj_angvel_stat",
67 | ]
68 | units: ["rad",
69 | "rad/s",
70 | "Nm",
71 | "-",
72 | "m",
73 | "m"]
74 |
75 | rewards:
76 | scales:
77 | # These are read in faive_hand.py (_prepare_reward function) and the
78 | # corresponding reward functions (with the name "_reward_{name}")
79 | # are called
80 |
81 |
82 | action_penalty: -0.000002
83 | dof_acc_penalty: 0.0 # -0.0000001
84 | dof_vel_penalty: 0.0 # -0.00001
85 | dof_trq_penalty: 0.0
86 | success: 3.0
87 | drop_penalty: -0.0001
88 | simple_hand_flat: 0.0
89 |
90 | reorienttask_obj_dist: -0.05
91 | reorienttask_obj_rot: 0.01
92 |
93 | success_tolerance: 0.1
94 | fall_dist_threshold: 0.5
95 |
96 | actions:
97 | clip: True
98 | clip_value: 1.0
99 |
100 | observations:
101 | clip: True
102 | clip_value: 5.0
103 |
104 | obs_dims: None
105 | # define in child config (because each robot has different DoFs)- the observation names and dimensions
106 | # this is used to determine the size of the observation buffer
107 |
108 | obs_scales:
109 | # Optionally define how much each observation should be scaled
110 | # if not given, the default value value of 1.0 is used.
111 | # Even if the scale is not specified here,
112 | # rl_games has a running normalizer (rl_games/algos_torch/running_mean_std.py)
113 | # which tries to normalize observations before sending them to the network.
114 | # Tuning this will probably not drastically improve the performance!
115 | dof_position: 2.0
116 | dof_speed: 0.25
117 | dof_force: 5.0
118 | obj_pos: 4.0
119 | obj_quat: 2.0
120 | obj_linvel: 10.0
121 | obj_angvel: 0.4
122 | goal_pos: 4.0
123 | goal_quat: 2.0
124 | goal_quat_diff: 2.0
125 | pose_sensor_pos: 5.0
126 | pose_sensor_quat: 1.0
127 | pose_sensor_linvel: 3.0
128 | pose_sensor_angvel: 0.2
129 | force_sensor_force: 4.0
130 | actions: 1.3
131 | obj_pose_history: 3.0
132 | dof_pos_history: 2.0
133 | obj_type: 1.0
134 |
135 |
136 | # if True, feed different observations to the actor and critic (e.g. when you want to send privileged information to the critic)
137 | # otherwise, the actor_observations is used for both actor and critic
138 | asymmetric_observations: False
139 | actor_observations: ["dof_position", "dof_speed", "dof_force",
140 | "obj_pos", "obj_quat", "obj_linvel", "obj_angvel",
141 | "goal_pos", "goal_quat", "goal_quat_diff",
142 | "pose_sensor_pos", "pose_sensor_quat", "pose_sensor_linvel", "pose_sensor_angvel", "force_sensor_force",
143 | "actions"]
144 |
145 |
146 |
147 | # used only in student training (student_train.py) - what observations are given to the student
148 | student_observations: ["dof_position", "dof_speed", "dof_force",
149 | "obj_pos", "obj_quat", "obj_linvel", "obj_angvel",
150 | "goal_pos", "goal_quat", "goal_quat_diff",
151 | "actions"]
152 |
153 | visualization:
154 | camera_pos_start: [-0.5, -0.5, 0.6]
155 | camera_target_start: [0, 0, 0.5]
156 | move_camera: False # set to true if you want cool camera motion
157 | camera_movement_vector: [.005, 0.005, 0.0]
158 |
159 | reset_noise:
160 | # how much noise to add to various dofs when resetting
161 | object_pos: 0.01
162 | object_rot: 0.0
163 | dof_pos: 0.2 # ratio wrt range of motion
164 | dof_vel: 0.0
165 |
166 | task:
167 | randomize: False
168 |
169 | sim:
170 | dt: 0.01667 # 60 Hz
171 | substeps: 2
172 | gravity: [0, 0, -9.81]
173 | up_axis: "z" # 0 is y, 1 is z
174 | use_gpu_pipeline: ${eq:${...pipeline},"gpu"}
175 |
176 | physx:
177 | num_threads: 4 # Number of worker threads per scene used by PhysX - for CPU PhysX only.
178 | solver_type: 1 # 0: pgs, 1: tgs
179 | num_position_iterations: 8
180 | num_velocity_iterations: 0
181 | max_gpu_contact_pairs: 8388608 # 8*1024*1024
182 | num_subscenes: 4 # Splits the simulation into N physics scenes and runs each one in a separate thread
183 | contact_offset: 0.002
184 | rest_offset: 0.0
185 | bounce_threshold_velocity: 0.2
186 | max_depenetration_velocity: 1000.0
187 | default_buffer_size_multiplier: 5.0
188 | contact_collection: 0 # 0: CC_NEVER (don't collect contact info), 1: CC_LAST_SUBSTEP (collect only contacts on last substep), 2: CC_ALL_SUBSTEPS (default - all contacts)
189 |
190 |
--------------------------------------------------------------------------------
/faive_gym/scripts/export_policy.py:
--------------------------------------------------------------------------------
1 | # Script that saves torch jit compiled policies for sim-to-real transfer, made
2 | # by Benedek Forrai (bforrai@student.ethz.ch). A modified version of train.py,
3 | # the header of which is pasted below.
4 | #
5 | # train.py
6 | # Script to train policies in Isaac Gym
7 | #
8 | # Copyright (c) 2018-2022, NVIDIA Corporation
9 | # All rights reserved.
10 | #
11 | # Redistribution and use in source and binary forms, with or without
12 | # modification, are permitted provided that the following conditions are met:
13 | #
14 | # 1. Redistributions of source code must retain the above copyright notice, this
15 | # list of conditions and the following disclaimer.
16 | #
17 | # 2. Redistributions in binary form must reproduce the above copyright notice,
18 | # this list of conditions and the following disclaimer in the documentation
19 | # and/or other materials provided with the distribution.
20 | #
21 | # 3. Neither the name of the copyright holder nor the names of its
22 | # contributors may be used to endorse or promote products derived from
23 | # this software without specific prior written permission.
24 | #
25 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 | # Export a trained RL policy
37 | # This will output a .onnx and .pt file to the same directory, which can be loaded in faive_franka_control or other solutions to run the policy on the real robot.
38 | # The output files, created in the folder `faive_gym/exported_policies`, will have the names `[policy_name]_[timestamp]`, where `policy_name` is set by the `wandb_name`
39 | # parameter. The export can be ran as follows:
40 | # ```bash
41 | # python export_policy.py task=FaiveHandP0 checkpoint=/path/to/checkpoint/FaiveHand.pth wandb_name=policy_name
42 | # ```
43 | # To check if the `.onnx` outputs are correct, you can use [netron](https://netron.app/). An exported `.onnx` should produce the following archtiecture:
44 | # 
45 |
46 | import datetime
47 | import isaacgym
48 |
49 | import os
50 | import hydra
51 | import yaml
52 | from omegaconf import DictConfig, OmegaConf
53 | from hydra.utils import to_absolute_path
54 | import gym
55 | import torch
56 | import onnx
57 | import onnxruntime as ort
58 |
59 | from isaacgymenvs.utils.reformat import omegaconf_to_dict, print_dict
60 |
61 | from isaacgymenvs.utils.utils import set_np_formatting, set_seed
62 |
63 | # register custom tasks for faive_gym here
64 | from isaacgymenvs.tasks import isaacgym_task_map
65 | from faive_gym.robot_hand import RobotHand
66 | isaacgym_task_map["RobotHand"] = RobotHand
67 |
68 | ## ModelWrapper class from https://colab.research.google.com/github/Denys88/rl_games/blob/master/notebooks/train_and_export_onnx_example_discrete.ipynb
69 | class ModelWrapper(torch.nn.Module):
70 | '''
71 | Main idea is to ignore outputs which we don't need from model
72 | '''
73 | def __init__(self, model):
74 | torch.nn.Module.__init__(self)
75 | self._model = model
76 |
77 |
78 | def forward(self,input_dict):
79 | input_dict['obs'] = self._model.norm_obs(input_dict['obs'])
80 | '''
81 | just model export doesn't work. Looks like onnx issue with torch distributions
82 | thats why we are exporting only neural network
83 | '''
84 | #print(input_dict)
85 | #output_dict = self._model.a2c_network(input_dict)
86 | #input_dict['is_train'] = False
87 | #return output_dict['logits'], output_dict['values']
88 | return self._model.a2c_network(input_dict)
89 |
90 | ## OmegaConf & Hydra Config
91 |
92 | # Resolvers used in hydra configs (see https://omegaconf.readthedocs.io/en/2.1_branch/usage.html#resolvers)
93 | @hydra.main(config_name="config", config_path="../cfg")
94 | def launch_rlg_hydra(cfg: DictConfig):
95 | from isaacgymenvs.utils.rlgames_utils import RLGPUEnv, RLGPUAlgoObserver, get_rlgames_env_creator
96 | from rl_games.common import env_configurations, vecenv
97 | from rl_games.torch_runner import Runner
98 | from rl_games.algos_torch import model_builder
99 | from isaacgymenvs.learning import amp_continuous
100 | from isaacgymenvs.learning import amp_players
101 | from isaacgymenvs.learning import amp_models
102 | from isaacgymenvs.learning import amp_network_builder
103 | import isaacgymenvs
104 |
105 | time_str = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
106 | run_name = f"{cfg.wandb_name}_{time_str}"
107 |
108 | # ensure checkpoints can be specified as relative paths
109 | if cfg.checkpoint:
110 | cfg.checkpoint = to_absolute_path(cfg.checkpoint)
111 |
112 | cfg_dict = omegaconf_to_dict(cfg)
113 | print_dict(cfg_dict)
114 |
115 | # set numpy formatting for printing only
116 | set_np_formatting()
117 |
118 | rank = int(os.getenv("LOCAL_RANK", "0"))
119 | if cfg.multi_gpu:
120 | # torchrun --standalone --nnodes=1 --nproc_per_node=2 train.py
121 | cfg.sim_device = f'cuda:{rank}'
122 | cfg.rl_device = f'cuda:{rank}'
123 |
124 | # sets seed. if seed is -1 will pick a random one
125 | cfg.seed += rank
126 | cfg.seed = set_seed(cfg.seed, torch_deterministic=cfg.torch_deterministic, rank=rank)
127 | # force running on cpu
128 | cfg.sim_device = 'cpu'
129 |
130 | def create_env_thunk(**kwargs):
131 | envs = isaacgymenvs.make(
132 | cfg.seed,
133 | cfg.task_name,
134 | cfg.task.env.numEnvs,
135 | cfg.sim_device,
136 | cfg.rl_device,
137 | cfg.graphics_device_id,
138 | cfg.headless,
139 | cfg.multi_gpu,
140 | cfg.capture_video,
141 | cfg.force_render,
142 | cfg,
143 | **kwargs,
144 | )
145 | return envs
146 |
147 | # register the rl-games adapter to use inside the runner
148 | vecenv.register('RLGPU',
149 | lambda config_name, num_actors, **kwargs: RLGPUEnv(config_name, num_actors, **kwargs))
150 | env_configurations.register('rlgpu', {
151 | 'vecenv_type': 'RLGPU',
152 | 'env_creator': create_env_thunk,
153 | })
154 |
155 | # register new AMP network builder and agent
156 | def build_runner(algo_observer):
157 | runner = Runner(algo_observer)
158 | runner.algo_factory.register_builder('amp_continuous', lambda **kwargs : amp_continuous.AMPAgent(**kwargs))
159 | runner.player_factory.register_builder('amp_continuous', lambda **kwargs : amp_players.AMPPlayerContinuous(**kwargs))
160 | model_builder.register_model('continuous_amp', lambda network, **kwargs : amp_models.ModelAMPContinuous(network))
161 | model_builder.register_network('amp', lambda **kwargs : amp_network_builder.AMPBuilder())
162 |
163 | return runner
164 |
165 | rlg_config_dict = omegaconf_to_dict(cfg.train)
166 |
167 | # convert CLI arguments into dictionory
168 | # create runner and set the settings
169 | runner = build_runner(RLGPUAlgoObserver())
170 | runner.load(rlg_config_dict)
171 | runner.reset()
172 |
173 | # dump config dict
174 | # load agent from the path we'd like to convert
175 | agent = runner.create_player()
176 | agent.restore(cfg.checkpoint)
177 | # run tracing on cpu
178 | print("Current device of the agent:")
179 | print(agent.device)
180 | # run torch.jit.trace on the model
181 | import rl_games.algos_torch.flatten as flatten
182 | inputs = {
183 | 'obs' : torch.zeros((1,) + agent.obs_shape).to(agent.device),
184 | 'rnn_states' : agent.states,
185 | }
186 |
187 | with torch.no_grad():
188 | adapter = flatten.TracingAdapter(ModelWrapper(agent.model), inputs, allow_non_tensor=True)
189 | traced = torch.jit.trace(adapter, adapter.flattened_inputs, check_trace=False)
190 | flattened_outputs = traced(*adapter.flattened_inputs)
191 | print(flattened_outputs)
192 | # export onnx and torchscript
193 | faive_gym_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
194 | save_dir = os.path.join(faive_gym_path,"exported_policies")
195 | if not os.path.exists(save_dir):
196 | os.makedirs(save_dir)
197 | save_path_base = os.path.join(save_dir, run_name)
198 | traced.save(save_path_base + '.pt')
199 | torch.onnx.export(traced, *adapter.flattened_inputs, save_path_base + ".onnx", verbose=True, input_names=['obs'], output_names=['mu','log_std', 'value'])
200 | onnx_model = onnx.load(save_path_base + ".onnx")
201 |
202 | # Check that the model is well formed
203 | onnx.checker.check_model(onnx_model)
204 |
205 | if __name__ == "__main__":
206 | launch_rlg_hydra()
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # faive_gym
2 | IsaacGym environments for the Faive Hand (and also somewhat easily extendable to other robotic hands), intended to be used together with [IsaacGymEnvs](https://github.com/NVIDIA-Omniverse/IsaacGymEnvs)
3 | 
4 |
5 | ## Resources
6 |
7 | * [faive_gym tutorial video](https://www.youtube.com/watch?v=Nwa7xP3RtO0): A video tutorial on how to get started with the faive_gym library to train a policy with RL, configure the environment, and load your own robot model in the framework.
8 | * [faive_gym tips document](https://docs.google.com/document/d/1n91q4nECS4vzkC2Jn62DxLiTA15WmdjJsbqNxEuv4tE/edit?usp=sharing): shared Google doc with tips on how to use the library effectively.
9 | * [RL knowledge dump document](https://docs.google.com/document/d/1mLH4pmkmL0SE-hknsB_qGlR9QBu4GYbEzk0ho16TDC4/edit?usp=sharing): another shared Google doc with general tips about RL for manipulation
10 |
11 | ---
12 |
13 | * [Paper (arxiv)](https://arxiv.org/abs/2308.02453): The preprint for our Humanoids 2023 paper which uses `faive_gym`. If you use this library in your work, please cite this paper.
14 | * [Project website](https://srl-ethz.github.io/get-ball-rolling/): website introducing our Humanoids 2023 paper.
15 | * [Project overview video](https://www.youtube.com/watch?v=YahsMhqNU8o): 3-minute video introducing our Humanoids 2023 work with the Faive Hand.
16 |
17 | ## Installation Steps
18 |
19 | 1. Install Isaac Gym
20 | 1. Download Isaac Gym Preview 4 from the [website](https://developer.nvidia.com/isaac-gym)
21 | 1. Check isaacgym/docs/index.html for install instructions, but this README also documents a fast way to set it up
22 | 1. Recommended: create a conda or venv (virtual environment) Python 3.8 environment for installation. To create and activate a Python 3.8 venv,
23 | 1. `python3.8 -m venv ~/rlgpu` to create a new venv called "rlgpu" in the home directory. You might have to first run `sudo apt install python3.8-venv` to install the virtual environment package.
24 | 1. `source ~/rlgpu/bin/activate` to activate the venv. You must run this to enter the venv every time a new terminal is opened.
25 | 1. Install isaacgym with pip
26 | ```bash
27 | cd /path/to/isaacgym/python
28 | pip install -e .
29 | ```
30 | You might have to first run `sudo apt install python3.8-dev`.
31 | 1. test installation
32 | ```bash
33 | cd examples
34 | python joint_monkey.py
35 | # if you are connecting to a remote instance from Windows, GUI is not available so this command will fail- in which case you could run a non-GUI example program, e.g.
36 | python asset_info.py
37 | ```
38 | 1. Install IsaacGymEnvs
39 | 1. Clone the repository
40 | ```bash
41 | git clone https://github.com/NVIDIA-Omniverse/IsaacGymEnvs
42 | ```
43 | You might have to first run `sudo apt install git`.
44 | 1. Install with pip
45 | ```bash
46 | cd /path/to/IsaacGymEnvs
47 | pip install -e .
48 | ```
49 | 1. Test installation
50 | ```bash
51 | cd isaacgymenvs
52 | python train.py
53 | ```
54 | 1. [optional] If an error about protobuf version appears, you may have to specify the version of protobuf, with
55 | ```bash
56 | pip install --upgrade protobuf==3.20.0
57 | ```
58 | 1. [optional] if the error `ModuleNotFoundError: No module named 'tkinter'` appears, you must install it with
59 | ```bash
60 | sudo apt install python3-tk
61 | ```
62 | 1. Install this repository (faive_gym)
63 | 1. Clone this repository (if you will clone the internal closed source repo, you will have to [add the SSH public key to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account))
64 | ```bash
65 | git clone https://github.com/srl-ethz/faive_gym_oss
66 | # if you want to use the internal closed source repo, instead run
67 | git clone git@github.com:srl-ethz/faive_gym.git
68 | ```
69 | 1. Install with pip
70 | ```bash
71 | cd /path/to/faive_gym
72 | pip install -e .
73 | ```
74 |
75 | The default Faive Hand training environment can be run with
76 | ```bash
77 | cd /path/to/faive_gym/faive_gym
78 | python train.py task=FaiveHandP0
79 | ```
80 |
81 | ## Additional Arguments
82 | Some additional arguments that can be appended; This has the same effect as modifying the yaml files in faive_gym/cfg directory, and could be used to easily change hyperparameters across runs. (check IsaacGymEnvs documentation for more)
83 |
84 | arguments | meaning
85 | --- | ---
86 | capture_video=True force_render=False | occasionaly capture video while training and save it to videos/ (also uploads to W&B, if that is enabled). This also disables the windows from popping up.
87 | capture_video_freq=2000 capture_video_len=200 | adjust the frequency / length of recording (save a video of length 200 steps every 2000 steps). If this is not set when the above arguments are set, the default settings for video capture will be used.
88 | num_envs=8 | try with fewer robot instances (useful for debugging)
89 | headless=True | run without GUI
90 | test=True | no training, just rollout policy
91 | checkpoint=runs/FaiveHand/nn/*.pth | load from checkpoint (combine with `test=True` to test out trained policy without training)
92 | wandb_activate=True wandb_group=srl_ethz wandb_project=your_project_name wandb_name=your_run_name | log this run in Weights & Biases
93 | task.env.env_spacing=0.7 | Any value defined in the config yaml files can be modified. This is an example of how to modify the values defined in faive_gym/cfg/task/RobotHandDefault.yaml
94 |
95 | ## using the Python `wandb` package for Weights and Biases
96 | when using the Weights & Biases feature, there might be an error which requires you to install xvfb and ffmpeg, with `sudo apt install xvfb` and `sudo apt install ffmpeg`.
97 |
98 | ## Loading your own robotic hand model
99 | 1. Prepare a MJCF (URDF) model of your robot. **Even models that can be perfectly simulated in MuJoCo might not work in IsaacGym as IsaacGym's model conversion script does not support all modeling features**, so it might require some trial and error to adjust the model file before you can actually load it into IsaacGym.
100 | 1. within *faive_gym/cfg/task* and *faive_gym/cfg/train* directory, respectively from *FaiveHandP0.yaml* and *FaiveHandP0PPO.yaml* to create *your_robot_name.yaml* and *your_robot_namePPO.yaml* files,
101 | 1. Modify the cfg files for your own robot in *your_robot_name.yaml*:
102 | - change `asset.model_file` to the path of your model file, relative to the assets/ directory.
103 | - `env.numActions` and the `observation.obs_dims` must be set with the degrees of freedom (DoF) for your robot
104 | - `observations.obs_dims.dof_pos_history` must be set to a multiple of the DoFs of your robot.
105 | - `asset.force_sensor_names` and `asset.pose_sensor_names` should be set to the name of the bodies at the fingertip. They are the fingertip force and pose sensors. (technically, the sensors can be placed on any body, but placing them on the fingertip would make the most sense for dexterous tasks)
106 | - if the number of fingers on your hand is not 5, change `observations.obs_dims.pose_sensor_*` and `observations.obs_dims.force_sensor_force` to \[number of fingers\] \* \[sensor dimension\]
107 | 1. try running train.py with your new environment, with `python train.py num_envs=2 task=your_robot_name`
108 | Take a good look at the error statements in the terminal and the model that appears in the window to make sure it's loaded correctly.
109 | 1. If you want to set it up for the cube rotation task, adjust the robot pose with `env.hand_start_p` and `env.hand_start_r` so that the cube falls onto the robot's palm. You can also try to adjust some other parameters defined in RobotHandDefault.yaml to suit your usage (try not to edit RobotHandDefault, just override the parameters values in your own yaml file)
110 |
111 | ## Program Structure
112 | Grossly oversimplified diagram of how the data flows in this program after train.py (round nodes indocate programs in rl_games)
113 |
114 | ```mermaid
115 | flowchart
116 | train.py --> torch_runner([rl_games.torch_runner.py]) --> a2c_common([rl_games.a2c_common.py]) -- vecenv --> robot_hand[tasks/robot_hand.py:RobotHand]
117 | robot_hand --load config--> cfg/task/FaiveHandP0.yaml --load default config--> cfg/task/RobotHandDefault.yaml
118 | a2c_common --load config--> cfg/train/FaiveHandP0PPO.yaml --load default config--> cfg/train/RobotHandDefaultPPO.yaml
119 | ```
120 |
121 | ## Export a trained RL policy
122 | This will output a .onnx and .pt file to the same directory, which can be loaded in faive_franka_control or other solutions to run the policy on the real robot.
123 | The output files, created in the folder `faive_gym/exported_policies`, will have the names `[policy_name]_[timestamp]`, where `policy_name` is set by the `wandb_name`
124 | parameter. The export can be ran as follows:
125 | ```bash
126 | python export_policy.py task=FaiveHandP0 checkpoint=/path/to/checkpoint/FaiveHand.pth wandb_name=policy_name
127 | ```
128 | To check if the `.onnx` outputs are correct, you can use [netron](https://netron.app/). An exported `.onnx` should produce the following archtiecture:
129 | 
130 |
131 | To export several models at the same time (which can be handy when testing several policies on the robot), refer to `scripts/export_all_policies.py`.
132 |
133 |
134 | ## Recording observations and joint positions for debugging
135 | You can record all observations and joint positions for an already trained policy by running:
136 | ```
137 | python train.py task=FaiveHandP0 headless=True test=True checkpoint=runs/FaiveHand/nn/[your_checkpoint.pth] num_envs=[env_number] task.logging.record_dofs=True task.logging.record_observations=True task.logging.record_length=[your_record_length]
138 | ```
139 | As all environments are recorded in parallel, it is advised not to use a high number of environments - lower hundreds will work, but a high number of envs + long recordings could lead to memory issues.
140 | The recording length is given in the number of environment steps that are recording, if you'd like to record for a certain amount of seconds, check the task.sim.dt constant.
141 |
142 | ## Other comments
143 | If you use this library in your work, please cite:
144 | ```
145 | @misc{toshimitsu2023getting,
146 | title={Getting the Ball Rolling: Learning a Dexterous Policy for a Biomimetic Tendon-Driven Hand with Rolling Contact Joints},
147 | author={Yasunori Toshimitsu and Benedek Forrai and Barnabas Gavin Cangan and Ulrich Steger and Manuel Knecht and Stefan Weirich and Robert K. Katzschmann},
148 | year={2023},
149 | eprint={2308.02453},
150 | archivePrefix={arXiv},
151 | primaryClass={cs.RO}
152 | }
153 | ```
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
204 | The license file for the IsaacGymEnvs repository, which some of the code in this repository is based on, is saved in LICENSE-NVIDIA.
--------------------------------------------------------------------------------
/assets/faive_hand_p0/faive_structure.xml:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | index
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
--------------------------------------------------------------------------------
/assets/faive_hand_p0/faive_metadata.xml:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
--------------------------------------------------------------------------------
/assets/objects_dext_manip/stell_dodeca.obj:
--------------------------------------------------------------------------------
1 | # WaveFront *.obj file (generated by Autodesk ATF)
2 |
3 | mtllib 307ecb1b-4884-4cc8-a64b-91a9104cd74d.mtl
4 |
5 | g Body2
6 |
7 | v -2.639320 -8.122992 11.180340
8 | v -8.541020 0.000000 11.180340
9 | v -18.090170 -13.143278 11.180340
10 | v -2.639320 8.122992 11.180340
11 | v -18.090170 13.143278 11.180340
12 | v 6.909830 5.020285 11.180340
13 | v 6.909830 21.266270 11.180340
14 | v 6.909830 -5.020285 11.180340
15 | v 22.360680 0.000000 11.180340
16 | v 6.909830 -21.266270 11.180340
17 | v -6.909830 5.020285 -11.180340
18 | v 2.639320 8.122992 -11.180340
19 | v 0.000000 0.000000 -25.000000
20 | v -4.270510 13.143278 2.639320
21 | v -11.180340 8.122992 -2.639320
22 | v -13.819660 0.000000 2.639320
23 | v -11.180340 -8.122992 -2.639320
24 | v -6.909830 -5.020285 -11.180340
25 | v 8.541020 0.000000 -11.180340
26 | v 11.180340 8.122992 2.639320
27 | v 4.270510 13.143278 -2.639320
28 | v 2.639320 -8.122992 -11.180340
29 | v 4.270510 -13.143278 -2.639320
30 | v 11.180340 -8.122992 2.639320
31 | v -4.270510 -13.143278 2.639320
32 | v 13.819660 0.000000 -2.639320
33 | v -22.360680 0.000000 -11.180340
34 | v -0.000000 0.000000 25.000000
35 | v 18.090170 13.143278 -11.180340
36 | v -6.909830 21.266270 -11.180340
37 | v 18.090170 -13.143278 -11.180340
38 | v -6.909830 -21.266270 -11.180340
39 | vt -0.477458 -0.812299 0.000000
40 | vt -1.067627 0.000000 0.000000
41 | vt -2.022542 -1.314328 0.000000
42 | vt -0.477458 0.812299 0.000000
43 | vt -2.022542 1.314328 0.000000
44 | vt 0.477458 0.502029 0.000000
45 | vt 0.477458 2.126627 0.000000
46 | vt 0.477458 -0.502029 0.000000
47 | vt 2.022542 0.000000 0.000000
48 | vt -0.477458 -0.812299 0.000000
49 | vt 0.477458 -2.126627 0.000000
50 | vt -1.816356 2.500000 0.000000
51 | vt -0.812299 2.500000 0.000000
52 | vt -1.314328 4.045085 0.000000
53 | vt -1.314328 0.954915 0.000000
54 | vt -2.126627 1.545085 0.000000
55 | vt -2.628656 0.000000 0.000000
56 | vt -1.314328 0.954915 0.000000
57 | vt -2.126627 1.545085 0.000000
58 | vt -2.628656 0.000000 0.000000
59 | vt -1.816356 2.500000 0.000000
60 | vt -0.812299 2.500000 0.000000
61 | vt -1.314328 4.045085 0.000000
62 | vt -0.502029 1.545085 0.000000
63 | vt -1.314328 0.954915 0.000000
64 | vt 0.000000 0.000000 0.000000
65 | vt -1.816356 2.500000 0.000000
66 | vt -0.812299 2.500000 0.000000
67 | vt -1.314328 4.045085 0.000000
68 | vt -1.314328 0.954915 0.000000
69 | vt -2.126627 1.545085 0.000000
70 | vt -2.628656 0.000000 0.000000
71 | vt -1.816356 2.500000 0.000000
72 | vt -0.812299 2.500000 0.000000
73 | vt -1.314328 4.045085 0.000000
74 | vt -0.502029 1.545085 0.000000
75 | vt -1.314328 0.954915 0.000000
76 | vt -0.000000 0.000000 0.000000
77 | vt -1.314328 0.954915 0.000000
78 | vt -2.126627 1.545085 0.000000
79 | vt -2.628656 0.000000 0.000000
80 | vt -1.816356 2.500000 0.000000
81 | vt -0.812299 2.500000 0.000000
82 | vt -1.314328 4.045085 0.000000
83 | vt -0.502029 1.545085 0.000000
84 | vt -1.314328 0.954915 0.000000
85 | vt 0.000000 0.000000 0.000000
86 | vt 0.000000 0.000000 0.000000
87 | vt -1.314328 0.954915 0.000000
88 | vt -1.624598 0.000000 0.000000
89 | vt 0.000000 -0.000000 0.000000
90 | vt -1.314328 0.954915 0.000000
91 | vt -1.624598 0.000000 0.000000
92 | vt 0.000000 0.000000 0.000000
93 | vt -1.314328 0.954915 0.000000
94 | vt -1.624598 0.000000 0.000000
95 | vt 0.000000 0.000000 0.000000
96 | vt -1.314328 0.954915 0.000000
97 | vt -1.624598 -0.000000 0.000000
98 | vt -0.310271 0.954915 0.000000
99 | vt -1.624598 0.000000 0.000000
100 | vt 0.000000 0.000000 0.000000
101 | vt -0.310271 0.954915 0.000000
102 | vt -1.624598 0.000000 0.000000
103 | vt 0.000000 0.000000 0.000000
104 | vt -0.310271 0.954915 0.000000
105 | vt -1.624598 0.000000 0.000000
106 | vt 0.000000 0.000000 0.000000
107 | vt -0.310271 0.954915 0.000000
108 | vt -1.624598 -0.000000 0.000000
109 | vt 0.000000 0.000000 0.000000
110 | vt -0.310271 0.954915 0.000000
111 | vt -1.624598 0.000000 0.000000
112 | vt 0.000000 -0.000000 0.000000
113 | vt 0.000000 0.000000 0.000000
114 | vt -1.314328 0.954915 0.000000
115 | vt -1.624598 -0.000000 0.000000
116 | vt -0.502029 1.545085 0.000000
117 | vt -1.314328 0.954915 0.000000
118 | vt 0.000000 0.000000 0.000000
119 | vt -0.502029 1.545085 0.000000
120 | vt -1.314328 0.954915 0.000000
121 | vt 0.000000 -0.000000 0.000000
122 | vt -1.314328 0.954915 0.000000
123 | vt -2.126627 1.545085 0.000000
124 | vt -2.628656 0.000000 0.000000
125 | vt -0.502029 1.545085 0.000000
126 | vt -1.314328 0.954915 0.000000
127 | vt -0.000000 0.000000 0.000000
128 | vt -1.816356 2.500000 0.000000
129 | vt -0.812299 2.500000 0.000000
130 | vt -1.314328 4.045085 0.000000
131 | vt -1.314328 0.954915 0.000000
132 | vt -2.126627 1.545085 0.000000
133 | vt -2.628656 -0.000000 0.000000
134 | vt -1.816356 2.500000 0.000000
135 | vt -0.812299 2.500000 0.000000
136 | vt -1.314328 4.045085 0.000000
137 | vt -0.502029 1.545085 0.000000
138 | vt -1.314328 0.954915 0.000000
139 | vt 0.000000 0.000000 0.000000
140 | vt -1.314328 0.954915 0.000000
141 | vt -2.126627 1.545085 0.000000
142 | vt -2.628656 -0.000000 0.000000
143 | vt -0.502029 1.545085 0.000000
144 | vt -1.314328 0.954915 0.000000
145 | vt 0.000000 0.000000 0.000000
146 | vt -0.502029 1.545085 0.000000
147 | vt -1.314328 0.954915 0.000000
148 | vt 0.000000 0.000000 0.000000
149 | vt -1.816356 2.500000 0.000000
150 | vt -0.812299 2.500000 0.000000
151 | vt -1.314328 4.045085 0.000000
152 | vt -0.477458 -0.812299 0.000000
153 | vt -1.067627 0.000000 0.000000
154 | vt -2.022542 -1.314328 0.000000
155 | vt -0.477458 0.812299 0.000000
156 | vt -2.022542 1.314328 0.000000
157 | vt 0.477458 0.502029 0.000000
158 | vt 0.477458 2.126627 0.000000
159 | vt 0.477458 -0.502029 0.000000
160 | vt 2.022542 0.000000 0.000000
161 | vt -0.477458 -0.812299 0.000000
162 | vt 0.477458 -2.126627 0.000000
163 | vt -1.314328 0.954915 0.000000
164 | vt -2.126627 1.545085 0.000000
165 | vt -2.628656 0.000000 0.000000
166 | vt -0.502029 1.545085 0.000000
167 | vt -1.314328 0.954915 0.000000
168 | vt 0.000000 0.000000 0.000000
169 | vt 0.000000 0.000000 0.000000
170 | vt -1.314328 0.954915 0.000000
171 | vt -1.624598 -0.000000 0.000000
172 | vt 0.000000 0.000000 0.000000
173 | vt -1.314328 0.954915 0.000000
174 | vt -1.624598 -0.000000 0.000000
175 | vt 0.000000 0.000000 0.000000
176 | vt -1.314328 0.954915 0.000000
177 | vt -1.624598 0.000000 0.000000
178 | vt -0.000000 0.000000 0.000000
179 | vt -1.314328 0.954915 0.000000
180 | vt -1.624598 -0.000000 0.000000
181 | vt -0.310271 0.954915 0.000000
182 | vt -1.624598 -0.000000 0.000000
183 | vt -0.000000 0.000000 0.000000
184 | vt -0.310271 0.954915 0.000000
185 | vt -1.624598 0.000000 0.000000
186 | vt 0.000000 0.000000 0.000000
187 | vt -0.310271 0.954915 0.000000
188 | vt -1.624598 0.000000 0.000000
189 | vt 0.000000 0.000000 0.000000
190 | vt -0.310271 0.954915 0.000000
191 | vt -1.624598 -0.000000 0.000000
192 | vt 0.000000 0.000000 0.000000
193 | vt -0.310271 0.954915 0.000000
194 | vt -1.624598 0.000000 0.000000
195 | vt 0.000000 0.000000 0.000000
196 | vt 0.000000 0.000000 0.000000
197 | vt -1.314328 0.954915 0.000000
198 | vt -1.624598 -0.000000 0.000000
199 | vt -1.816356 2.500000 0.000000
200 | vt -0.812299 2.500000 0.000000
201 | vt -1.314328 4.045085 0.000000
202 | vt -1.314328 0.954915 0.000000
203 | vt -2.126627 1.545085 0.000000
204 | vt -2.628656 -0.000000 0.000000
205 | vt -1.816356 2.500000 0.000000
206 | vt -0.812299 2.500000 0.000000
207 | vt -1.314328 4.045085 0.000000
208 | vt -1.314328 0.954915 0.000000
209 | vt -2.126627 1.545085 0.000000
210 | vt -2.628656 0.000000 0.000000
211 | vn 0.000000 0.000000 0.100000
212 | vn 0.000000 0.000000 0.100000
213 | vn 0.000000 0.000000 0.100000
214 | vn 0.000000 0.000000 0.100000
215 | vn 0.000000 0.000000 0.100000
216 | vn 0.000000 0.000000 0.100000
217 | vn 0.000000 0.000000 0.100000
218 | vn 0.000000 0.000000 0.100000
219 | vn 0.000000 0.000000 0.100000
220 | vn 0.000000 0.000000 0.100000
221 | vn -0.027639 0.085065 -0.044721
222 | vn -0.027639 0.085065 -0.044721
223 | vn -0.027639 0.085065 -0.044721
224 | vn -0.027639 0.085065 -0.044721
225 | vn -0.027639 0.085065 -0.044721
226 | vn -0.027639 0.085065 -0.044721
227 | vn -0.089443 0.000000 -0.044721
228 | vn -0.089443 0.000000 -0.044721
229 | vn -0.089443 0.000000 -0.044721
230 | vn -0.089443 0.000000 -0.044721
231 | vn -0.089443 0.000000 -0.044721
232 | vn -0.089443 0.000000 -0.044721
233 | vn -0.089443 0.000000 -0.044721
234 | vn -0.089443 0.000000 -0.044721
235 | vn 0.072361 0.052573 -0.044721
236 | vn 0.072361 0.052573 -0.044721
237 | vn 0.072361 0.052573 -0.044721
238 | vn 0.072361 0.052573 -0.044721
239 | vn 0.072361 0.052573 -0.044721
240 | vn 0.072361 0.052573 -0.044721
241 | vn 0.072361 -0.052573 -0.044721
242 | vn 0.072361 -0.052573 -0.044721
243 | vn 0.072361 -0.052573 -0.044721
244 | vn 0.072361 -0.052573 -0.044721
245 | vn 0.072361 -0.052573 -0.044721
246 | vn 0.072361 -0.052573 -0.044721
247 | vn -0.027639 -0.085065 -0.044721
248 | vn -0.027639 -0.085065 -0.044721
249 | vn -0.027639 -0.085065 -0.044721
250 | vn -0.027639 -0.085065 -0.044721
251 | vn -0.027639 -0.085065 -0.044721
252 | vn -0.027639 -0.085065 -0.044721
253 | vn -0.027639 -0.085065 -0.044721
254 | vn -0.027639 -0.085065 -0.044721
255 | vn -0.072361 0.052573 0.044721
256 | vn -0.072361 0.052573 0.044721
257 | vn -0.072361 0.052573 0.044721
258 | vn -0.072361 -0.052573 0.044721
259 | vn -0.072361 -0.052573 0.044721
260 | vn -0.072361 -0.052573 0.044721
261 | vn 0.027639 -0.085065 0.044721
262 | vn 0.027639 -0.085065 0.044721
263 | vn 0.027639 -0.085065 0.044721
264 | vn 0.027639 0.085065 0.044721
265 | vn 0.027639 0.085065 0.044721
266 | vn 0.027639 0.085065 0.044721
267 | vn 0.027639 0.085065 0.044721
268 | vn 0.027639 0.085065 0.044721
269 | vn 0.027639 0.085065 0.044721
270 | vn -0.072361 0.052573 0.044721
271 | vn -0.072361 0.052573 0.044721
272 | vn -0.072361 0.052573 0.044721
273 | vn 0.027639 -0.085065 0.044721
274 | vn 0.027639 -0.085065 0.044721
275 | vn 0.027639 -0.085065 0.044721
276 | vn 0.089443 -0.000000 0.044721
277 | vn 0.089443 -0.000000 0.044721
278 | vn 0.089443 -0.000000 0.044721
279 | vn -0.072361 -0.052573 0.044721
280 | vn -0.072361 -0.052573 0.044721
281 | vn -0.072361 -0.052573 0.044721
282 | vn 0.089443 -0.000000 0.044721
283 | vn 0.089443 -0.000000 0.044721
284 | vn 0.089443 -0.000000 0.044721
285 | vn -0.027639 0.085065 -0.044721
286 | vn -0.027639 0.085065 -0.044721
287 | vn 0.072361 0.052573 -0.044721
288 | vn 0.072361 0.052573 -0.044721
289 | vn 0.072361 -0.052573 -0.044721
290 | vn 0.072361 -0.052573 -0.044721
291 | vn -0.072361 0.052573 0.044721
292 | vn -0.072361 0.052573 0.044721
293 | vn -0.072361 0.052573 0.044721
294 | vn 0.027639 0.085065 0.044721
295 | vn 0.027639 0.085065 0.044721
296 | vn 0.027639 0.085065 0.044721
297 | vn 0.027639 0.085065 0.044721
298 | vn 0.089443 0.000000 0.044721
299 | vn 0.089443 0.000000 0.044721
300 | vn 0.089443 0.000000 0.044721
301 | vn -0.072361 -0.052573 0.044721
302 | vn -0.072361 -0.052573 0.044721
303 | vn -0.072361 -0.052573 0.044721
304 | vn 0.000000 0.000000 -0.100000
305 | vn 0.000000 0.000000 -0.100000
306 | vn 0.000000 0.000000 -0.100000
307 | vn 0.000000 0.000000 -0.100000
308 | vn 0.000000 0.000000 -0.100000
309 | vn 0.000000 0.000000 -0.100000
310 | vn 0.000000 0.000000 -0.100000
311 | vn 0.000000 0.000000 -0.100000
312 | vn 0.000000 0.000000 -0.100000
313 | vn 0.000000 0.000000 -0.100000
314 | vn 0.027639 -0.085065 0.044721
315 | vn 0.027639 -0.085065 0.044721
316 | vn 0.027639 -0.085065 0.044721
317 | vn 0.072361 0.052573 -0.044721
318 | vn 0.072361 -0.052573 -0.044721
319 | vn -0.027639 -0.085065 -0.044721
320 | vn -0.027639 0.085065 -0.044721
321 | vn -0.027639 0.085065 -0.044721
322 | vn 0.072361 0.052573 -0.044721
323 | vn -0.027639 -0.085065 -0.044721
324 | vn -0.089443 -0.000000 -0.044721
325 | vn 0.072361 -0.052573 -0.044721
326 | vn -0.089443 -0.000000 -0.044721
327 | vn 0.089443 0.000000 0.044721
328 | vn -0.072361 0.052573 0.044721
329 | vn 0.027639 -0.085065 0.044721
330 | vn -0.072361 -0.052573 0.044721
331 | usemtl Steel_-_Satin
332 | f 1/1/1 2/2/2 3/3/3
333 | f 2/2/2 4/4/4 5/5/5
334 | f 4/4/4 6/6/6 7/7/7
335 | f 6/6/6 8/8/8 9/9/9
336 | f 8/8/8 1/10/1 10/11/10
337 | f 11/12/11 12/13/12 13/14/13
338 | f 14/15/14 15/16/15 5/17/16
339 | f 16/18/17 17/19/18 3/20/19
340 | f 18/21/20 11/22/21 13/23/22
341 | f 15/24/23 16/25/17 5/26/24
342 | f 12/27/25 19/28/26 13/29/27
343 | f 20/30/28 21/31/29 7/32/30
344 | f 19/33/31 22/34/32 13/35/33
345 | f 23/36/34 24/37/35 10/38/36
346 | f 25/39/37 23/40/38 10/41/39
347 | f 22/42/40 18/43/41 13/44/42
348 | f 17/45/43 25/46/37 3/47/44
349 | f 7/48/45 14/49/46 4/50/47
350 | f 5/51/48 16/52/49 2/53/50
351 | f 3/54/51 25/55/52 1/56/53
352 | f 9/57/54 20/58/55 6/59/56
353 | f 14/60/57 5/61/58 4/62/59
354 | f 16/63/60 3/64/61 2/65/62
355 | f 24/66/63 9/67/64 8/68/65
356 | f 20/69/66 7/70/67 6/71/68
357 | f 25/72/69 10/73/70 1/74/71
358 | f 10/75/72 24/76/73 8/77/74
359 | f 21/78/75 14/79/14 7/80/76
360 | f 26/81/77 20/82/28 9/83/78
361 | f 24/84/35 26/85/79 9/86/80
362 | f 16/87/60 15/88/81 27/89/82
363 | f 4/90/47 2/91/62 28/92/83
364 | f 21/93/84 20/94/55 29/95/85
365 | f 6/96/56 4/97/59 28/98/86
366 | f 14/99/57 21/100/84 30/101/87
367 | f 26/102/88 24/103/73 31/104/89
368 | f 20/105/66 26/106/88 29/107/90
369 | f 25/108/69 17/109/91 32/110/92
370 | f 2/111/50 1/112/71 28/113/93
371 | f 22/114/94 19/115/95 31/116/96
372 | f 19/115/95 12/117/97 29/118/98
373 | f 12/117/97 11/119/99 30/120/100
374 | f 11/119/99 18/121/101 27/122/102
375 | f 18/121/101 22/123/94 32/124/103
376 | f 23/125/104 25/126/52 32/127/105
377 | f 24/128/63 23/129/104 31/130/106
378 | f 30/131/107 21/132/29 12/133/25
379 | f 29/134/108 26/135/79 19/136/31
380 | f 31/137/109 23/138/38 22/139/40
381 | f 27/140/110 15/141/15 11/142/11
382 | f 21/143/75 29/144/111 12/145/12
383 | f 26/146/77 31/147/112 19/148/26
384 | f 17/149/43 27/150/113 18/151/41
385 | f 15/152/23 30/153/114 11/154/21
386 | f 23/155/34 32/156/115 22/157/32
387 | f 32/158/116 17/159/18 18/160/20
388 | f 8/161/74 6/162/68 28/163/117
389 | f 15/164/81 14/165/46 30/166/118
390 | f 1/167/53 8/168/65 28/169/119
391 | f 17/170/91 16/171/49 27/172/120
392 | # 32 vertices
393 | # 172 texture params
394 | # 120 normals
395 | # 60 facets
396 |
397 | # 1 groups
398 |
--------------------------------------------------------------------------------
/img/onnx_export_sample.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------