Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MuJoCo version of shadow hand and mia hand grasping environments #52

Merged
merged 61 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
14e25a3
basic shadow hand grasp env
xkiixkii Jul 2, 2024
e172d81
basic shadow hand grasp env
xkiixkii Jul 2, 2024
cdb71f5
Add sensor related utils
xkiixkii Jul 8, 2024
e507f0e
Step simulation according to simulation time not actual time; Initial…
xkiixkii Jul 8, 2024
a1cb212
Initialize object use factory
xkiixkii Jul 8, 2024
6433850
Remove unnecessary top level settings
xkiixkii Jul 8, 2024
297e579
Set up qpos and qvel independently
xkiixkii Jul 8, 2024
e8d286e
Volumetric mesh for insole in GMSH format
xkiixkii Jul 10, 2024
fafdb30
Add load_keyfram and set_state function
xkiixkii Jul 10, 2024
05cb750
some basic logging set up
xkiixkii Jul 10, 2024
d4b913c
move set_state and load_keyframe to base_mjenv
xkiixkii Jul 10, 2024
c64a1d5
fix hand passes through insole after applying solid plugin
xkiixkii Jul 10, 2024
98b286a
some placement adjustments
xkiixkii Jul 10, 2024
5ef6a7e
update requirements
xkiixkii Jul 11, 2024
1539157
Include object com in observation space
xkiixkii Jul 15, 2024
7f4f384
add mj_utils test
xkiixkii Jul 19, 2024
0f92413
euler2quat take arraylike args; add load_model_from_string()
xkiixkii Jul 19, 2024
52611ba
Registration of MjShadowGraspInsole-v0
xkiixkii Jul 22, 2024
0aa6da5
asset manager to manager all assets path
xkiixkii Jul 22, 2024
8730d2b
base env can combine different robots and objects with asset manager
xkiixkii Jul 22, 2024
b77e4ab
initialize via obj name now
xkiixkii Jul 22, 2024
00e859a
add set position to set initial position
xkiixkii Jul 22, 2024
9b04736
load env via gymnasium
xkiixkii Jul 22, 2024
8f4017e
organize meshes and models
xkiixkii Jul 22, 2024
afca959
Add equality constraint
xkiixkii Jul 23, 2024
f92abe5
Add equality constraint utils
xkiixkii Jul 23, 2024
cc4de44
add observable obj position
xkiixkii Jul 23, 2024
29d4d13
Add load_model for individual model
xkiixkii Jul 23, 2024
1e0dc75
Add trailing slash for meshdir; Separate the floor.xml from robot an…
xkiixkii Aug 14, 2024
5794055
add obs and action space
xkiixkii Aug 14, 2024
cd2840d
grasp environment for overall grasping
xkiixkii Aug 14, 2024
e6dcf6a
basic floor for all environments
xkiixkii Aug 14, 2024
04f2cd9
Remove floor and platform, add more eq constraint to make insole float
xkiixkii Aug 14, 2024
5495e2d
Add ee joints and actuator, enable gravcomp to make robot float
xkiixkii Aug 14, 2024
f0f2ad9
Add mia hand model
xkiixkii Aug 14, 2024
40f1266
Add joint and actuator utils
xkiixkii Aug 14, 2024
bc85fd9
use mju.Pose as object pose description
xkiixkii Aug 14, 2024
8a0befe
add Mia hand
xkiixkii Aug 14, 2024
db0431c
add mia hand example
xkiixkii Aug 14, 2024
bb401db
Add test for joints and actuator utils
xkiixkii Aug 14, 2024
6d285a4
new grasp env for mia hand and shadow hand
xkiixkii Aug 14, 2024
1be3319
Register MjMiaGraspInsole-v0
xkiixkii Aug 14, 2024
389c4db
mujoco version update
xkiixkii Aug 14, 2024
8ca8384
Pose.orientation dim check
xkiixkii Aug 14, 2024
fdc7777
Add test for insole_fixed
xkiixkii Aug 14, 2024
bd879d2
Add function of getting body pose
xkiixkii Aug 14, 2024
50b1a0d
Add test cases
xkiixkii Aug 14, 2024
13e97be
Add doc string
xkiixkii Aug 16, 2024
977d7bc
typehint compatible with Python 3.8
xkiixkii Aug 17, 2024
746320a
typehint compatible with Python 3.8
xkiixkii Aug 19, 2024
fe56df8
Add observation space range and
xkiixkii Aug 20, 2024
61bb91f
Add observation space range
xkiixkii Aug 20, 2024
f6816a8
more readable function names
xkiixkii Aug 27, 2024
2dd8d4f
type hint fixed
xkiixkii Aug 27, 2024
240ac60
type hint fixed and use consistent variable name with gym
xkiixkii Aug 27, 2024
c3b4a05
typo fixed and use consistent variable name with gym
xkiixkii Aug 27, 2024
34b6621
type hint fixed
xkiixkii Aug 27, 2024
8d2728f
more readable var names
xkiixkii Aug 27, 2024
8b37076
function name changed
xkiixkii Aug 27, 2024
7845602
new assets directory
xkiixkii Aug 27, 2024
db55159
Bump version
mlaux1 Sep 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions deformable_gym/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,17 @@
"observable_object_pos": True,
},
)

register(
id="MjShadowGraspInsole-v0",
entry_point="deformable_gym.envs.mujoco.shadow_grasp:ShadowHandGrasp",
disable_env_checker=True,
kwargs={"obj_name": "insole_fixed"},
)

register(
id="MjMiaGraspInsole-v0",
entry_point="deformable_gym.envs.mujoco.mia_grasp:MiaHandGrasp",
disable_env_checker=True,
kwargs={"obj_name": "insole_fixed"},
)
155 changes: 155 additions & 0 deletions deformable_gym/envs/mujoco/asset_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import os
import xml.etree.ElementTree as ET
from typing import Optional, Sequence, Union

xkiixkii marked this conversation as resolved.
Show resolved Hide resolved
import mujoco

from ...helpers import mj_utils as mju

ROBOTS = {
"shadow_hand": "shadow_hand.xml",
"mia_hand": "mia_hand.xml",
}
OBJECTS = {"insole_fixed": "insole_fixed.xml"}


class AssetManager:
"""
The AssetManager class manages the loading and combining of MuJoCo models (robots and objects)
into a single simulation scene. It provides methods to load individual robot or object models,
create complex scenes, and save the resulting XML configuration.
"""

def __init__(self) -> None:
self.assets_dir = os.path.join(os.path.dirname(__file__), "assets")
self.meshdir = os.path.join(self.assets_dir, "meshes")
xkiixkii marked this conversation as resolved.
Show resolved Hide resolved
self.robots = ROBOTS
self.objects = OBJECTS

def load_asset(self, name: str) -> mujoco.MjModel:
"""
Loads a asset (robot or object mujoco Model) based on its name.

Args:
name (str): The name of the robot or object to be loaded. Must be a key in either
self.robots or self.objects.

Returns:
mujoco.MjModel: The loaded MuJoCo model.

Raises:
AssertionError: If the specified name is not found in either self.robots or self.objects.
"""
assert (
name in self.robots or name in self.objects
), f"Model {name} not found.\n available: {list(self.robots.keys()) + list(self.objects.keys())}"
model_path = self.robots.get(name, self.objects.get(name))
full_path = self._get_full_path(model_path)
model, _ = mju.load_model_from_file(full_path)
return model

def create_scene(self, robot_name: str, obj_name: str) -> str:
"""
Creates an MJCF string representing a MuJoCo scene that includes a robot and an object.

Args:
robot_name (str): The name of the robot to include in the scene. Must be a key in self.robots.
obj_name (str): The name of the object to include in the scene. Must be a key in self.objects.

Returns:
str: A MJCF string representing the combined MuJoCo scene.

Raises:
AssertionError: If the specified robot_name is not found in self.robots.
AssertionError: If the specified obj_name is not found in self.objects.
"""
assert (
robot_name in self.robots
), f"Robot {robot_name} not found.\n available: {list(self.robots.keys())}"
assert (
obj_name in self.objects
), f"Object {obj_name} not found.\n available: {list(self.objects.keys())}"

floor_path = self._get_full_path("floor.xml")
robot_path = self._get_full_path(self.robots[robot_name])
obj_path = self._get_full_path(self.objects[obj_name])

scene = self.include_mjcf(
obj_path, [robot_path, floor_path], meshdir=self.meshdir
)
return scene

# def create_scene(self, robot_name: str, *obj_name: str) -> str:
# assert (
# robot_name in self.robots
# ), f"Robot {robot_name} not found.\n available: {list(self.robots.keys())}"

# robot_path = self._get_full_path(self.robots[robot_name])

# for obj in obj_name:
# assert (
# obj in self.objects
# ), f"Object {obj} not found.\n available: {list(self.objects.keys())}"
# obj_path = [self._get_full_path(self.objects[obj]) for obj in obj_name]
# scene = self.include_mjcf(robot_path, obj_path, meshdir=self.meshdir)
# return scene

def _get_full_path(self, file: str) -> str:
"""
Generates the full path to a file within the assets directory.

Args:
file (str): The file name (with extension) for which to generate the full path.

Returns:
str: The full path to the specified file within the assets directory.
"""
return os.path.join(self.assets_dir, file)

@staticmethod
def include_mjcf(
base_path: str,
include_path: Union[str, Sequence[str]],
xkiixkii marked this conversation as resolved.
Show resolved Hide resolved
*,
meshdir: Optional[str] = None,
xkiixkii marked this conversation as resolved.
Show resolved Hide resolved
) -> str:
"""
Generates an XML string for a MuJoCo scene by including additional MJCF files within a base MJCF file.

Args:
base_path (str): The file path to the base MJCF file.
include_path (Union[str, Sequence[str]]): A string or list of strings representing file paths
to MJCF files to be included in the base file.
meshdir (Optional[str]): A string representing the path to the directory containing mesh files.
If provided, this path is added to the meshdir attribute of the compiler
element in the MJCF XML.

Returns:
str: An XML string representing the combined MJCF file.
"""
tree = ET.parse(base_path)
root = tree.getroot()
if isinstance(include_path, list) or isinstance(include_path, tuple):
for path in include_path:
new_elem = ET.Element("include", {"file": path})
root.insert(0, new_elem)
else:
new_elem = ET.Element("include", {"file": include_path})
root.insert(0, new_elem)
if meshdir is not None:
if meshdir[-1] != "/":
meshdir += "/"
elems = root.findall("compiler")
if len(elems) != 0:
for elem in elems:
elem.set("meshdir", meshdir)
else:
new_elem = ET.Element("compiler", {"meshdir": meshdir})
root.insert(0, new_elem)
new_mjcf = ET.tostring(root, encoding="utf-8").decode("utf-8")

return new_mjcf

def save_mjcf_string(self, mjcf: str, path: str) -> None:
with open(path, "w") as f:
f.write(mjcf)
17 changes: 17 additions & 0 deletions deformable_gym/envs/mujoco/assets/floor.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<mujoco>
<!-- <option timestep="0.005"/> -->
<visual>
<rgba haze="0.15 0.25 0.35 1" />
<quality shadowsize="8192" />
<global azimuth="220" elevation="-30" />
</visual>
<asset>
<texture type="skybox" builtin="gradient" rgb1="0.3 0.5 0.7" rgb2="0 0 0" width="512" height="3072" />
<texture type="2d" name="groundplane" builtin="checker" mark="edge" rgb1="0.2 0.3 0.4" rgb2="0.1 0.2 0.3" markrgb="0.8 0.8 0.8" width="300" height="300" />
<material name="groundplane" texture="groundplane" texuniform="true" texrepeat="5 5" reflectance="0.2" />
</asset>
<worldbody>
<light pos="0.3 0 1.5" dir="0 0 -1" directional="true" />
<geom name="floor" pos="0 0 0" size="0 0 .05" type="plane" material="groundplane" />
</worldbody>
</mujoco>
29 changes: 29 additions & 0 deletions deformable_gym/envs/mujoco/assets/insole_fixed.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<mujoco>
<!-- <include file="floor.xml"/> -->
<compiler meshdir="meshes/" />
<extension>
<plugin plugin="mujoco.elasticity.solid" />
</extension>
<worldbody>
<body name="insole_fixed" pos=".12 -.05 .456">
<flexcomp name="insole" mass=".5" dim="3" type="gmsh" file="insole.msh" rgba=".1 .9 .1 1" radius="0.001">
<edge equality="true" />
<plugin plugin="mujoco.elasticity.solid">
<config key="young" value="1e4" />
<config key="poisson" value="0.1" />
<config key="damping" value="1e-4" />
</plugin>
</flexcomp>
</body>
</worldbody>
<equality>
<weld name="fix_1" body1="insole_27" body2="world" />
<weld name="fix_2" body1="insole_44" body2="world" />
<weld name="fix_3" body1="insole_37" body2="world" />
<weld name="fix_4" body1="insole_35" body2="world" />
<weld name="fix_5" body1="insole_43" body2="world" />
<weld name="fix_6" body1="insole_1" body2="world" />
<weld name="fix_7" body1="insole_32" body2="world" />
<weld name="fix_8" body1="insole_69" body2="world" />
</equality>
</mujoco>
Loading
Loading