mani-skill-nightly 2025.10.21.2011__py3-none-any.whl → 2025.10.22.157__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mani-skill-nightly might be problematic. Click here for more details.
- mani_skill/agents/base_agent.py +20 -14
- mani_skill/agents/base_real_agent.py +6 -6
- mani_skill/agents/controllers/base_controller.py +6 -6
- mani_skill/agents/controllers/pd_joint_pos.py +2 -2
- mani_skill/agents/controllers/utils/kinematics.py +27 -12
- mani_skill/agents/multi_agent.py +5 -5
- mani_skill/agents/registration.py +3 -4
- mani_skill/agents/robots/allegro_hand/allegro.py +1 -2
- mani_skill/agents/robots/allegro_hand/allegro_touch.py +3 -3
- mani_skill/agents/robots/dclaw/dclaw.py +2 -3
- mani_skill/agents/robots/fetch/fetch.py +2 -2
- mani_skill/agents/robots/floating_ability_hand/floating_ability_hand.py +10 -13
- mani_skill/agents/robots/floating_robotiq_2f_85_gripper/floating_robotiq_2f_85_gripper.py +2 -2
- mani_skill/agents/robots/lerobot/manipulator.py +4 -4
- mani_skill/agents/robots/panda/panda_stick.py +2 -2
- mani_skill/agents/robots/trifingerpro/trifingerpro.py +1 -2
- mani_skill/agents/robots/xarm/xarm7_ability.py +2 -2
- mani_skill/agents/utils.py +2 -2
- mani_skill/envs/minimal_template.py +4 -4
- mani_skill/envs/sapien_env.py +36 -33
- mani_skill/envs/scene.py +27 -27
- mani_skill/envs/scenes/base_env.py +3 -3
- mani_skill/envs/sim2real_env.py +10 -10
- mani_skill/envs/tasks/control/ant.py +6 -6
- mani_skill/envs/tasks/control/cartpole.py +4 -4
- mani_skill/envs/tasks/control/hopper.py +7 -7
- mani_skill/envs/tasks/control/humanoid.py +20 -20
- mani_skill/envs/tasks/dexterity/insert_flower.py +41 -23
- mani_skill/envs/tasks/dexterity/rotate_single_object_in_hand.py +6 -6
- mani_skill/envs/tasks/dexterity/rotate_valve.py +5 -5
- mani_skill/envs/tasks/digital_twins/base_env.py +4 -4
- mani_skill/envs/tasks/digital_twins/bridge_dataset_eval/base_env.py +22 -12
- mani_skill/envs/tasks/digital_twins/so100_arm/grasp_cube.py +4 -4
- mani_skill/envs/tasks/drawing/draw.py +1 -3
- mani_skill/envs/tasks/drawing/draw_svg.py +6 -8
- mani_skill/envs/tasks/drawing/draw_triangle.py +1 -2
- mani_skill/envs/tasks/empty_env.py +1 -3
- mani_skill/envs/tasks/fmb/fmb.py +1 -2
- mani_skill/envs/tasks/humanoid/humanoid_pick_place.py +7 -7
- mani_skill/envs/tasks/humanoid/humanoid_stand.py +5 -5
- mani_skill/envs/tasks/humanoid/transport_box.py +4 -4
- mani_skill/envs/tasks/mobile_manipulation/open_cabinet_drawer.py +8 -8
- mani_skill/envs/tasks/mobile_manipulation/robocasa/kitchen.py +2 -3
- mani_skill/envs/tasks/quadruped/quadruped_reach.py +5 -5
- mani_skill/envs/tasks/quadruped/quadruped_spin.py +5 -5
- mani_skill/envs/tasks/rotate_cube.py +4 -4
- mani_skill/envs/tasks/tabletop/assembling_kits.py +2 -2
- mani_skill/envs/tasks/tabletop/lift_peg_upright.py +4 -4
- mani_skill/envs/tasks/tabletop/peg_insertion_side.py +4 -4
- mani_skill/envs/tasks/tabletop/pick_clutter_ycb.py +4 -4
- mani_skill/envs/tasks/tabletop/pick_cube.py +4 -4
- mani_skill/envs/tasks/tabletop/pick_single_ycb.py +5 -5
- mani_skill/envs/tasks/tabletop/place_sphere.py +4 -4
- mani_skill/envs/tasks/tabletop/plug_charger.py +2 -2
- mani_skill/envs/tasks/tabletop/poke_cube.py +4 -4
- mani_skill/envs/tasks/tabletop/pull_cube.py +5 -5
- mani_skill/envs/tasks/tabletop/pull_cube_tool.py +4 -4
- mani_skill/envs/tasks/tabletop/push_cube.py +6 -6
- mani_skill/envs/tasks/tabletop/push_t.py +4 -4
- mani_skill/envs/tasks/tabletop/roll_ball.py +4 -4
- mani_skill/envs/tasks/tabletop/stack_cube.py +4 -4
- mani_skill/envs/tasks/tabletop/stack_pyramid.py +44 -25
- mani_skill/envs/tasks/tabletop/turn_faucet.py +4 -4
- mani_skill/envs/tasks/tabletop/two_robot_pick_cube.py +4 -4
- mani_skill/envs/tasks/tabletop/two_robot_stack_cube.py +4 -4
- mani_skill/envs/template.py +4 -4
- mani_skill/envs/utils/observations/observations.py +2 -3
- mani_skill/envs/utils/randomization/batched_rng.py +7 -7
- mani_skill/envs/utils/randomization/samplers.py +2 -2
- mani_skill/examples/benchmarking/envs/maniskill/franka_move.py +2 -2
- mani_skill/examples/benchmarking/envs/maniskill/franka_pick_cube.py +2 -2
- mani_skill/examples/benchmarking/profiling.py +2 -2
- mani_skill/examples/demo_random_action.py +1 -1
- mani_skill/render/shaders.py +5 -5
- mani_skill/sensors/base_sensor.py +1 -2
- mani_skill/sensors/camera.py +4 -4
- mani_skill/trajectory/replay_trajectory.py +0 -1
- mani_skill/utils/assets/data.py +3 -3
- mani_skill/utils/building/_mjcf_loader.py +11 -11
- mani_skill/utils/building/actor_builder.py +4 -4
- mani_skill/utils/building/articulation_builder.py +3 -3
- mani_skill/utils/building/mjcf_loader.py +6 -6
- mani_skill/utils/building/urdf_loader.py +6 -6
- mani_skill/utils/common.py +2 -2
- mani_skill/utils/geometry/bounding_cylinder.py +4 -4
- mani_skill/utils/geometry/geometry.py +1 -3
- mani_skill/utils/geometry/trimesh_utils.py +1 -3
- mani_skill/utils/gym_utils.py +2 -4
- mani_skill/utils/registration.py +6 -6
- mani_skill/utils/sapien_utils.py +21 -21
- mani_skill/utils/scene_builder/ai2thor/constants.py +1 -2
- mani_skill/utils/scene_builder/ai2thor/scene_builder.py +9 -9
- mani_skill/utils/scene_builder/control/planar/scene_builder.py +2 -4
- mani_skill/utils/scene_builder/kitchen_counter/scene_builder.py +1 -2
- mani_skill/utils/scene_builder/registration.py +1 -2
- mani_skill/utils/scene_builder/replicacad/rearrange/scene_builder.py +16 -16
- mani_skill/utils/scene_builder/replicacad/scene_builder.py +15 -15
- mani_skill/utils/scene_builder/robocasa/fixtures/windows.py +2 -4
- mani_skill/utils/scene_builder/robocasa/scene_builder.py +5 -5
- mani_skill/utils/scene_builder/scene_builder.py +15 -15
- mani_skill/utils/scene_builder/table/scene_builder.py +1 -2
- mani_skill/utils/structs/actor.py +6 -6
- mani_skill/utils/structs/articulation.py +32 -30
- mani_skill/utils/structs/articulation_joint.py +6 -6
- mani_skill/utils/structs/base.py +14 -9
- mani_skill/utils/structs/drive.py +2 -2
- mani_skill/utils/structs/link.py +10 -8
- mani_skill/utils/structs/pose.py +3 -3
- mani_skill/utils/structs/render_camera.py +4 -4
- mani_skill/utils/structs/types.py +3 -1
- mani_skill/utils/visualization/jupyter_utils.py +1 -3
- mani_skill/utils/visualization/misc.py +5 -5
- mani_skill/utils/wrappers/cached_reset.py +5 -3
- mani_skill/utils/wrappers/flatten.py +1 -2
- mani_skill/utils/wrappers/record.py +10 -8
- mani_skill/utils/wrappers/visual_encoders.py +2 -2
- mani_skill/vector/wrappers/gymnasium.py +23 -13
- mani_skill/vector/wrappers/sb3.py +5 -5
- {mani_skill_nightly-2025.10.21.2011.dist-info → mani_skill_nightly-2025.10.22.157.dist-info}/METADATA +1 -1
- {mani_skill_nightly-2025.10.21.2011.dist-info → mani_skill_nightly-2025.10.22.157.dist-info}/RECORD +124 -124
- {mani_skill_nightly-2025.10.21.2011.dist-info → mani_skill_nightly-2025.10.22.157.dist-info}/WHEEL +0 -0
- {mani_skill_nightly-2025.10.21.2011.dist-info → mani_skill_nightly-2025.10.22.157.dist-info}/licenses/LICENSE +0 -0
- {mani_skill_nightly-2025.10.21.2011.dist-info → mani_skill_nightly-2025.10.22.157.dist-info}/licenses/LICENSE-3RD-PARTY +0 -0
- {mani_skill_nightly-2025.10.21.2011.dist-info → mani_skill_nightly-2025.10.22.157.dist-info}/top_level.txt +0 -0
mani_skill/sensors/camera.py
CHANGED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import TYPE_CHECKING,
|
|
5
|
+
from typing import TYPE_CHECKING, Optional, Union
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import sapien
|
|
@@ -68,7 +68,7 @@ class CameraConfig(BaseSensorConfig):
|
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
def update_camera_configs_from_dict(
|
|
71
|
-
camera_configs:
|
|
71
|
+
camera_configs: dict[str, CameraConfig], config_dict: dict[str, dict]
|
|
72
72
|
):
|
|
73
73
|
# Update CameraConfig to StereoDepthCameraConfig
|
|
74
74
|
if config_dict.pop("use_stereo_depth", False):
|
|
@@ -264,8 +264,8 @@ def normalize_depth(depth, min_depth=0, max_depth=None):
|
|
|
264
264
|
|
|
265
265
|
|
|
266
266
|
def camera_observations_to_images(
|
|
267
|
-
observations:
|
|
268
|
-
) ->
|
|
267
|
+
observations: dict[str, torch.Tensor], max_depth=None
|
|
268
|
+
) -> list[Array]:
|
|
269
269
|
"""Parse images from camera observations."""
|
|
270
270
|
images = dict()
|
|
271
271
|
for key in observations:
|
|
@@ -399,7 +399,6 @@ def _main(
|
|
|
399
399
|
# Load associated json
|
|
400
400
|
json_path = traj_path.replace(".h5", ".json")
|
|
401
401
|
json_data = io_utils.load_json(json_path)
|
|
402
|
-
env_kwargs["sim_config"]["scene_config"]["gravity"] = np.array(env_kwargs["sim_config"]["scene_config"]["gravity"])
|
|
403
402
|
env = gym.make(env_id, **env_kwargs)
|
|
404
403
|
if isinstance(env.action_space, gym.spaces.Dict):
|
|
405
404
|
logger.warning(
|
mani_skill/utils/assets/data.py
CHANGED
|
@@ -4,7 +4,7 @@ Asset sources and tooling for managing the assets
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
-
from typing import
|
|
7
|
+
from typing import Optional
|
|
8
8
|
|
|
9
9
|
from mani_skill import ASSET_DIR, PACKAGE_ASSET_DIR
|
|
10
10
|
from mani_skill.utils import io_utils
|
|
@@ -27,9 +27,9 @@ class DataSource:
|
|
|
27
27
|
output_dir: str = ASSET_DIR
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
DATA_SOURCES:
|
|
30
|
+
DATA_SOURCES: dict[str, DataSource] = {}
|
|
31
31
|
"""Data sources map data source IDs to their respective DataSource objects which contain info on what the data is and where to download it"""
|
|
32
|
-
DATA_GROUPS:
|
|
32
|
+
DATA_GROUPS: dict[str, list[str]] = {}
|
|
33
33
|
"""Data groups map group ids (typically environment IDs) to a list of data source/group IDs for easy group management. data groups can be done hierarchicaly"""
|
|
34
34
|
|
|
35
35
|
|
|
@@ -44,7 +44,7 @@ from collections import defaultdict
|
|
|
44
44
|
from copy import deepcopy
|
|
45
45
|
from dataclasses import dataclass
|
|
46
46
|
from functools import reduce
|
|
47
|
-
from typing import Any,
|
|
47
|
+
from typing import Any, Literal, Tuple, Union
|
|
48
48
|
from xml.etree.ElementTree import Element
|
|
49
49
|
|
|
50
50
|
import numpy as np
|
|
@@ -98,7 +98,7 @@ def _str_to_float(string: str, delimiter=" "):
|
|
|
98
98
|
return res
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
def _merge_attrib(default_attrib: dict, incoming_attribs: Union[
|
|
101
|
+
def _merge_attrib(default_attrib: dict, incoming_attribs: Union[list[dict], dict]):
|
|
102
102
|
def helper_merge(a: dict, b: dict, path=[]):
|
|
103
103
|
for key in b:
|
|
104
104
|
if key in a:
|
|
@@ -199,14 +199,14 @@ class MJCFLoader:
|
|
|
199
199
|
# self._link_min_patch_radius = dict()
|
|
200
200
|
# self._link_density = dict()
|
|
201
201
|
|
|
202
|
-
self._defaults:
|
|
202
|
+
self._defaults: dict[str, Element] = dict()
|
|
203
203
|
self._assets = dict()
|
|
204
204
|
self._materials = dict()
|
|
205
|
-
self._textures:
|
|
206
|
-
self._meshes:
|
|
205
|
+
self._textures: dict[str, MJCFTexture] = dict()
|
|
206
|
+
self._meshes: dict[str, Element] = dict()
|
|
207
207
|
|
|
208
|
-
self._link2builder:
|
|
209
|
-
self._link2parent_joint:
|
|
208
|
+
self._link2builder: dict[str, LinkBuilder] = dict()
|
|
209
|
+
self._link2parent_joint: dict[str, Any] = dict()
|
|
210
210
|
self._group_count = 0
|
|
211
211
|
|
|
212
212
|
def set_scene(self, scene):
|
|
@@ -735,7 +735,7 @@ class MJCFLoader:
|
|
|
735
735
|
|
|
736
736
|
def _parse_mjcf(
|
|
737
737
|
self, mjcf_string: str
|
|
738
|
-
) -> Tuple[
|
|
738
|
+
) -> Tuple[list[ArticulationBuilder], list[ActorBuilder], None]:
|
|
739
739
|
"""Helper function for self.parse"""
|
|
740
740
|
xml: Element = ET.fromstring(mjcf_string.encode("utf-8"))
|
|
741
741
|
self.xml = xml
|
|
@@ -793,8 +793,8 @@ class MJCFLoader:
|
|
|
793
793
|
|
|
794
794
|
# NOTE (stao): For now we assume there is only one articulation. Some setups like Aloha 2 are technically 2 articulations
|
|
795
795
|
# but you can treat it as a single one anyway
|
|
796
|
-
articulation_builders:
|
|
797
|
-
actor_builders:
|
|
796
|
+
articulation_builders: list[ArticulationBuilder] = []
|
|
797
|
+
actor_builders: list[ActorBuilder] = []
|
|
798
798
|
for i, body in enumerate(xml.find("worldbody").findall("body")):
|
|
799
799
|
# determine first if this body is really an articulation or a actor
|
|
800
800
|
has_freejoint = body.find("freejoint") is not None
|
|
@@ -899,7 +899,7 @@ class MJCFLoader:
|
|
|
899
899
|
mjcf_file, package_dir
|
|
900
900
|
)
|
|
901
901
|
|
|
902
|
-
articulations:
|
|
902
|
+
articulations: list[PhysxArticulation] = []
|
|
903
903
|
for b in articulation_builders:
|
|
904
904
|
articulations.append(b.build())
|
|
905
905
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING,
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, Sequence, Union
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import sapien
|
|
@@ -38,7 +38,7 @@ class ActorBuilder(SAPIENActorBuilder):
|
|
|
38
38
|
def set_scene_idxs(
|
|
39
39
|
self,
|
|
40
40
|
scene_idxs: Optional[
|
|
41
|
-
Union[
|
|
41
|
+
Union[list[int], Sequence[int], torch.Tensor, np.ndarray]
|
|
42
42
|
] = None,
|
|
43
43
|
):
|
|
44
44
|
"""
|
|
@@ -267,9 +267,9 @@ class ActorBuilder(SAPIENActorBuilder):
|
|
|
267
267
|
def add_plane_repeated_visual(
|
|
268
268
|
self,
|
|
269
269
|
pose: sapien.Pose = sapien.Pose(),
|
|
270
|
-
half_size:
|
|
270
|
+
half_size: list[float] = [5, 5],
|
|
271
271
|
mat: sapien.render.RenderMaterial = None,
|
|
272
|
-
texture_repeat:
|
|
272
|
+
texture_repeat: list[float] = [1, 1],
|
|
273
273
|
):
|
|
274
274
|
"""Procedurally generateds a repeated 2D texture. Works similarly to https://mujoco.readthedocs.io/en/stable/XMLreference.html#asset-material-texrepeat
|
|
275
275
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING,
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, Sequence, Union
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import sapien
|
|
@@ -37,7 +37,7 @@ class ArticulationBuilder(SapienArticulationBuilder):
|
|
|
37
37
|
def set_scene_idxs(
|
|
38
38
|
self,
|
|
39
39
|
scene_idxs: Optional[
|
|
40
|
-
Union[
|
|
40
|
+
Union[list[int], Sequence[int], torch.Tensor, np.ndarray]
|
|
41
41
|
] = None,
|
|
42
42
|
):
|
|
43
43
|
"""
|
|
@@ -149,7 +149,7 @@ class ArticulationBuilder(SapienArticulationBuilder):
|
|
|
149
149
|
articulation_pose = to_sapien_pose(initial_pose_np)
|
|
150
150
|
else:
|
|
151
151
|
articulation_pose = to_sapien_pose(initial_pose_np[i])
|
|
152
|
-
links:
|
|
152
|
+
links: list[sapien.Entity] = self._build_entities(
|
|
153
153
|
name_prefix=f"scene-{scene_idx}-{self.name}_",
|
|
154
154
|
initial_pose=articulation_pose,
|
|
155
155
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any,
|
|
3
|
+
from typing import TYPE_CHECKING, Any, TypedDict
|
|
4
4
|
|
|
5
5
|
from mani_skill.utils.building.actor_builder import ActorBuilder
|
|
6
6
|
from mani_skill.utils.building.articulation_builder import ArticulationBuilder
|
|
@@ -13,9 +13,9 @@ from ._mjcf_loader import MJCFLoader as SAPIENMJCFLoader
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class ParsedMJCFData(TypedDict):
|
|
16
|
-
articulation_builders:
|
|
17
|
-
actor_builders:
|
|
18
|
-
cameras:
|
|
16
|
+
articulation_builders: list[ArticulationBuilder]
|
|
17
|
+
actor_builders: list[ActorBuilder]
|
|
18
|
+
cameras: list[Any]
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class MJCFLoader(SAPIENMJCFLoader):
|
|
@@ -72,13 +72,13 @@ class MJCFLoader(SAPIENMJCFLoader):
|
|
|
72
72
|
_parsed_mjcf_data["actor_builders"]
|
|
73
73
|
cameras = _parsed_mjcf_data["cameras"]
|
|
74
74
|
|
|
75
|
-
articulations:
|
|
75
|
+
articulations: list[Articulation] = []
|
|
76
76
|
for b in articulation_builders[:1]:
|
|
77
77
|
b.set_scene_idxs(scene_idxs)
|
|
78
78
|
b.disable_self_collisions = self.disable_self_collisions
|
|
79
79
|
articulations.append(b.build())
|
|
80
80
|
|
|
81
|
-
actors:
|
|
81
|
+
actors: list[Actor] = []
|
|
82
82
|
# for b in actor_builders:
|
|
83
83
|
# actors.append(b.build())
|
|
84
84
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any,
|
|
3
|
+
from typing import TYPE_CHECKING, Any, TypedDict
|
|
4
4
|
|
|
5
5
|
from sapien.render import RenderCameraComponent
|
|
6
6
|
from sapien.wrapper.urdf_loader import URDFLoader as SapienURDFLoader
|
|
@@ -15,9 +15,9 @@ if TYPE_CHECKING:
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ParsedURDFData(TypedDict):
|
|
18
|
-
articulation_builders:
|
|
19
|
-
actor_builders:
|
|
20
|
-
cameras:
|
|
18
|
+
articulation_builders: list[ArticulationBuilder]
|
|
19
|
+
actor_builders: list[ActorBuilder]
|
|
20
|
+
cameras: list[Any]
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class URDFLoader(SapienURDFLoader):
|
|
@@ -83,13 +83,13 @@ class URDFLoader(SapienURDFLoader):
|
|
|
83
83
|
"URDF contains multiple objects, call load_multiple instead"
|
|
84
84
|
)
|
|
85
85
|
|
|
86
|
-
articulations:
|
|
86
|
+
articulations: list[Articulation] = []
|
|
87
87
|
for b in articulation_builders:
|
|
88
88
|
b.set_scene_idxs(scene_idxs)
|
|
89
89
|
b.disable_self_collisions = self.disable_self_collisions
|
|
90
90
|
articulations.append(b.build())
|
|
91
91
|
|
|
92
|
-
actors:
|
|
92
|
+
actors: list[Actor] = []
|
|
93
93
|
for b in actor_builders:
|
|
94
94
|
actors.append(b.build())
|
|
95
95
|
|
mani_skill/utils/common.py
CHANGED
|
@@ -3,7 +3,7 @@ Common utilities often reused for internal code and task building for users.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from collections import defaultdict
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Optional, Sequence, Tuple, Union
|
|
7
7
|
|
|
8
8
|
import gymnasium as gym
|
|
9
9
|
import numpy as np
|
|
@@ -84,7 +84,7 @@ def dict_merge(dct: dict, merge_dct: dict):
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
# TODO (stao): Consolidate this function with the one above..
|
|
87
|
-
def merge_dicts(ds: Sequence[
|
|
87
|
+
def merge_dicts(ds: Sequence[dict], asarray=False):
|
|
88
88
|
"""Merge multiple dicts with the same keys to a single one."""
|
|
89
89
|
# NOTE(jigu): To be compatible with generator, we only iterate once.
|
|
90
90
|
ret = defaultdict(list)
|
|
@@ -6,13 +6,13 @@ https://www.nayuki.io/page/smallest-enclosing-circle
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import math
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import Optional, Tuple
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def _compute_smallest_circle(
|
|
15
|
-
points:
|
|
15
|
+
points: list[Tuple[float, float]]
|
|
16
16
|
) -> Optional[Tuple[float, float, float]]:
|
|
17
17
|
points = [(float(x), float(y)) for x, y in points]
|
|
18
18
|
np.random.shuffle(points)
|
|
@@ -25,7 +25,7 @@ def _compute_smallest_circle(
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
def _compute_circle_with_point(
|
|
28
|
-
points:
|
|
28
|
+
points: list[Tuple[float, float]], p: Tuple[float, float]
|
|
29
29
|
) -> Tuple[float, float, float]:
|
|
30
30
|
circle = (p[0], p[1], 0.0)
|
|
31
31
|
for i, q in enumerate(points):
|
|
@@ -38,7 +38,7 @@ def _compute_circle_with_point(
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def _compute_circle_with_two_points(
|
|
41
|
-
points:
|
|
41
|
+
points: list[Tuple[float, float]], p: Tuple[float, float], q: Tuple[float, float]
|
|
42
42
|
) -> Tuple[float, float, float]:
|
|
43
43
|
circle = _get_circle_from_diameter(p, q)
|
|
44
44
|
left = right = None
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Dict
|
|
2
|
-
|
|
3
1
|
import numpy as np
|
|
4
2
|
import sapien
|
|
5
3
|
import sapien.physx as physx
|
|
@@ -153,7 +151,7 @@ def invert_transform(H: np.ndarray):
|
|
|
153
151
|
|
|
154
152
|
def get_oriented_bounding_box_for_2d_points(
|
|
155
153
|
points_2d: np.ndarray, resolution=0.0
|
|
156
|
-
) ->
|
|
154
|
+
) -> dict:
|
|
157
155
|
assert len(points_2d.shape) == 2 and points_2d.shape[1] == 2
|
|
158
156
|
if resolution > 0.0:
|
|
159
157
|
points_2d = np.round(points_2d / resolution) * resolution
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
1
|
## TODO clean up the code here, too many functions that are plurals of one or the other and confusing naming
|
|
4
2
|
import numpy as np
|
|
5
3
|
import sapien
|
|
@@ -92,7 +90,7 @@ def get_actor_visual_meshes(actor: sapien.Entity):
|
|
|
92
90
|
return meshes
|
|
93
91
|
|
|
94
92
|
|
|
95
|
-
def merge_meshes(meshes:
|
|
93
|
+
def merge_meshes(meshes: list[trimesh.Trimesh]):
|
|
96
94
|
n, vs, fs = 0, [], []
|
|
97
95
|
for mesh in meshes:
|
|
98
96
|
v, f = mesh.vertices, mesh.faces
|
mani_skill/utils/gym_utils.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"""various gymnasium/gym utilities used in ManiSkill, mostly to handle observation/action spaces and noramlization"""
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
from typing import Dict
|
|
5
|
-
|
|
6
4
|
import gymnasium as gym
|
|
7
5
|
import numpy as np
|
|
8
6
|
import torch
|
|
@@ -46,7 +44,7 @@ def find_max_episode_steps_value(env):
|
|
|
46
44
|
|
|
47
45
|
def extract_scalars_from_info(
|
|
48
46
|
info: dict, blacklist=(), batch_size=1
|
|
49
|
-
) ->
|
|
47
|
+
) -> dict[str, float]:
|
|
50
48
|
"""Recursively extract scalar metrics from an info dict returned by env.step.
|
|
51
49
|
|
|
52
50
|
Args:
|
|
@@ -54,7 +52,7 @@ def extract_scalars_from_info(
|
|
|
54
52
|
blacklist (tuple, optional): keys to exclude.
|
|
55
53
|
|
|
56
54
|
Returns:
|
|
57
|
-
|
|
55
|
+
dict[str, float]: scalar metrics
|
|
58
56
|
"""
|
|
59
57
|
ret = {}
|
|
60
58
|
for k, v in info.items():
|
mani_skill/utils/registration.py
CHANGED
|
@@ -4,7 +4,7 @@ import json
|
|
|
4
4
|
import sys
|
|
5
5
|
from copy import deepcopy
|
|
6
6
|
from functools import partial
|
|
7
|
-
from typing import TYPE_CHECKING,
|
|
7
|
+
from typing import TYPE_CHECKING, Optional, Type
|
|
8
8
|
|
|
9
9
|
import gymnasium as gym
|
|
10
10
|
import torch
|
|
@@ -25,7 +25,7 @@ class EnvSpec:
|
|
|
25
25
|
uid: str,
|
|
26
26
|
cls: Type[BaseEnv],
|
|
27
27
|
max_episode_steps=None,
|
|
28
|
-
asset_download_ids: Optional[
|
|
28
|
+
asset_download_ids: Optional[list[str]] = [],
|
|
29
29
|
default_kwargs: dict = None,
|
|
30
30
|
):
|
|
31
31
|
"""A specification for a ManiSkill environment."""
|
|
@@ -90,14 +90,14 @@ class EnvSpec:
|
|
|
90
90
|
)
|
|
91
91
|
|
|
92
92
|
|
|
93
|
-
REGISTERED_ENVS:
|
|
93
|
+
REGISTERED_ENVS: dict[str, EnvSpec] = {}
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
def register(
|
|
97
97
|
name: str,
|
|
98
98
|
cls: Type[BaseEnv],
|
|
99
99
|
max_episode_steps=None,
|
|
100
|
-
asset_download_ids:
|
|
100
|
+
asset_download_ids: list[str] = [],
|
|
101
101
|
default_kwargs: dict = None,
|
|
102
102
|
):
|
|
103
103
|
"""Register a ManiSkill environment."""
|
|
@@ -193,7 +193,7 @@ def register_env(
|
|
|
193
193
|
uid: str,
|
|
194
194
|
max_episode_steps=None,
|
|
195
195
|
override=False,
|
|
196
|
-
asset_download_ids:
|
|
196
|
+
asset_download_ids: list[str] = [],
|
|
197
197
|
**kwargs,
|
|
198
198
|
):
|
|
199
199
|
"""A decorator to register ManiSkill environments.
|
|
@@ -201,7 +201,7 @@ def register_env(
|
|
|
201
201
|
Args:
|
|
202
202
|
uid (str): unique id of the environment.
|
|
203
203
|
max_episode_steps (int): maximum number of steps in an episode.
|
|
204
|
-
asset_download_ids (
|
|
204
|
+
asset_download_ids (list[str]): asset download ids the environment depends on. When environments are created
|
|
205
205
|
this list is checked to see if the user has all assets downloaded and if not, prompt the user if they wish to download them.
|
|
206
206
|
override (bool): whether to override the environment if it is already registered.
|
|
207
207
|
|
mani_skill/utils/sapien_utils.py
CHANGED
|
@@ -4,7 +4,7 @@ Utilities that work with the simulation / SAPIEN
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
import sys
|
|
7
|
-
from typing import TYPE_CHECKING,
|
|
7
|
+
from typing import TYPE_CHECKING, Tuple, TypeVar
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
import sapien
|
|
@@ -27,11 +27,11 @@ from mani_skill.utils.structs.types import Array, Device
|
|
|
27
27
|
T = TypeVar("T")
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def get_obj_by_name(objs:
|
|
30
|
+
def get_obj_by_name(objs: list[T], name: str, is_unique=True):
|
|
31
31
|
"""Get a object given the name.
|
|
32
32
|
|
|
33
33
|
Args:
|
|
34
|
-
objs (
|
|
34
|
+
objs (list[T]): objs to query. Expect these objects to have a get_name function. These may be sapien.Entity, physx.PhysxArticulationLink etc.
|
|
35
35
|
name (str): name for query.
|
|
36
36
|
is_unique (bool, optional):
|
|
37
37
|
whether the name should be unique. Defaults to True.
|
|
@@ -40,7 +40,7 @@ def get_obj_by_name(objs: List[T], name: str, is_unique=True):
|
|
|
40
40
|
RuntimeError: The name is not unique when @is_unique is True.
|
|
41
41
|
|
|
42
42
|
Returns:
|
|
43
|
-
T or
|
|
43
|
+
T or list[T]:
|
|
44
44
|
matched T or Ts. None if no matches.
|
|
45
45
|
"""
|
|
46
46
|
matched_objects = [x for x in objs if x.get_name() == name]
|
|
@@ -55,15 +55,15 @@ def get_obj_by_name(objs: List[T], name: str, is_unique=True):
|
|
|
55
55
|
return None
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
def get_objs_by_names(objs:
|
|
58
|
+
def get_objs_by_names(objs: list[T], names: list[str]) -> list[T]:
|
|
59
59
|
"""Get a list of objects given a list of names from a larger list of objects (objs). The returned list is in the order of the names given
|
|
60
60
|
|
|
61
61
|
Args:
|
|
62
|
-
objs (
|
|
62
|
+
objs (list[T]): objs to query. Expect these objects to have a get_name function. These may be sapien.Entity, physx.PhysxArticulationLink etc.
|
|
63
63
|
name (str): names to query.
|
|
64
64
|
|
|
65
65
|
Returns:
|
|
66
|
-
T or
|
|
66
|
+
T or list[T]:
|
|
67
67
|
matched T or Ts. None if no matches.
|
|
68
68
|
"""
|
|
69
69
|
assert isinstance(objs, (list, tuple)), type(objs)
|
|
@@ -76,7 +76,7 @@ def get_objs_by_names(objs: List[T], names: List[str]) -> List[T]:
|
|
|
76
76
|
return ret
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
def get_obj_by_type(objs:
|
|
79
|
+
def get_obj_by_type(objs: list[T], target_type: T, is_unique=True):
|
|
80
80
|
matched_objects = [x for x in objs if type(x) == target_type]
|
|
81
81
|
if len(matched_objects) > 1:
|
|
82
82
|
if not is_unique:
|
|
@@ -112,14 +112,14 @@ def check_urdf_config(urdf_config: dict):
|
|
|
112
112
|
)
|
|
113
113
|
|
|
114
114
|
|
|
115
|
-
def parse_urdf_config(config_dict: dict) ->
|
|
115
|
+
def parse_urdf_config(config_dict: dict) -> dict:
|
|
116
116
|
"""Parse config from dict for SAPIEN URDF loader.
|
|
117
117
|
|
|
118
118
|
Args:
|
|
119
119
|
config_dict (dict): a dict containing link physical properties.
|
|
120
120
|
|
|
121
121
|
Returns:
|
|
122
|
-
|
|
122
|
+
dict: urdf config passed to `sapien.URDFLoader.load`.
|
|
123
123
|
"""
|
|
124
124
|
# urdf_config = deepcopy(config_dict)
|
|
125
125
|
urdf_config = dict()
|
|
@@ -214,8 +214,8 @@ def get_articulation_padded_state(articulation: physx.PhysxArticulation, max_dof
|
|
|
214
214
|
# and check if the entity is the same
|
|
215
215
|
# -------------------------------------------------------------------------- #
|
|
216
216
|
def get_pairwise_contacts(
|
|
217
|
-
contacts:
|
|
218
|
-
) ->
|
|
217
|
+
contacts: list[physx.PhysxContact], actor0: sapien.Entity, actor1: sapien.Entity
|
|
218
|
+
) -> list[Tuple[physx.PhysxContact, bool]]:
|
|
219
219
|
"""
|
|
220
220
|
Given a list of contacts, return the list of contacts involving the two actors
|
|
221
221
|
"""
|
|
@@ -229,10 +229,10 @@ def get_pairwise_contacts(
|
|
|
229
229
|
|
|
230
230
|
|
|
231
231
|
def get_multiple_pairwise_contacts(
|
|
232
|
-
contacts:
|
|
232
|
+
contacts: list[physx.PhysxContact],
|
|
233
233
|
actor0: sapien.Entity,
|
|
234
|
-
actor1_list:
|
|
235
|
-
) ->
|
|
234
|
+
actor1_list: list[sapien.Entity],
|
|
235
|
+
) -> dict[sapien.Entity, list[Tuple[physx.PhysxContact, bool]]]:
|
|
236
236
|
"""
|
|
237
237
|
Given a list of contacts, return the dict of contacts involving the one actor and actors
|
|
238
238
|
This function is used to avoid double for-loop when using `get_pairwise_contacts` with multiple actors
|
|
@@ -252,7 +252,7 @@ def get_multiple_pairwise_contacts(
|
|
|
252
252
|
return pairwise_contacts
|
|
253
253
|
|
|
254
254
|
|
|
255
|
-
def compute_total_impulse(contact_infos:
|
|
255
|
+
def compute_total_impulse(contact_infos: list[Tuple[physx.PhysxContact, bool]]):
|
|
256
256
|
total_impulse = np.zeros(3)
|
|
257
257
|
for contact, flag in contact_infos:
|
|
258
258
|
contact_impulse = np.sum([point.impulse for point in contact.points], axis=0)
|
|
@@ -262,7 +262,7 @@ def compute_total_impulse(contact_infos: List[Tuple[physx.PhysxContact, bool]]):
|
|
|
262
262
|
|
|
263
263
|
|
|
264
264
|
def get_pairwise_contact_impulse(
|
|
265
|
-
contacts:
|
|
265
|
+
contacts: list[physx.PhysxContact], actor0: sapien.Entity, actor1: sapien.Entity
|
|
266
266
|
):
|
|
267
267
|
pairwise_contacts = get_pairwise_contacts(contacts, actor0, actor1)
|
|
268
268
|
total_impulse = compute_total_impulse(pairwise_contacts)
|
|
@@ -270,8 +270,8 @@ def get_pairwise_contact_impulse(
|
|
|
270
270
|
|
|
271
271
|
|
|
272
272
|
def get_cpu_actor_contacts(
|
|
273
|
-
contacts:
|
|
274
|
-
) ->
|
|
273
|
+
contacts: list[physx.PhysxContact], actor: sapien.Entity
|
|
274
|
+
) -> list[Tuple[physx.PhysxContact, bool]]:
|
|
275
275
|
entity_contacts = []
|
|
276
276
|
for contact in contacts:
|
|
277
277
|
if contact.bodies[0].entity == actor:
|
|
@@ -282,8 +282,8 @@ def get_cpu_actor_contacts(
|
|
|
282
282
|
|
|
283
283
|
|
|
284
284
|
def get_cpu_actors_contacts(
|
|
285
|
-
contacts:
|
|
286
|
-
) ->
|
|
285
|
+
contacts: list[physx.PhysxContact], actors: list[sapien.Entity]
|
|
286
|
+
) -> dict[sapien.Entity, list[Tuple[physx.PhysxContact, bool]]]:
|
|
287
287
|
"""
|
|
288
288
|
This function is used to avoid double for-loop when using `get_actor_contacts` with multiple actors
|
|
289
289
|
"""
|
|
@@ -2,7 +2,6 @@ import json
|
|
|
2
2
|
import os.path as osp
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Dict
|
|
6
5
|
|
|
7
6
|
from mani_skill import ASSET_DIR
|
|
8
7
|
|
|
@@ -143,7 +142,7 @@ def load_ai2thor_metadata():
|
|
|
143
142
|
|
|
144
143
|
|
|
145
144
|
# This maps a scene set e.g. ProcTHOR to an adapter, metadata, and where the scenes are saved to. The adapter is a class that can load the scene set
|
|
146
|
-
SCENE_SOURCE_TO_DATASET:
|
|
145
|
+
SCENE_SOURCE_TO_DATASET: dict[str, SceneDataset] = {
|
|
147
146
|
"ProcTHOR": SceneDataset(
|
|
148
147
|
metadata_path="ProcTHOR.json",
|
|
149
148
|
dataset_path=osp.join(
|
|
@@ -6,7 +6,7 @@ SceneBuilder for the AI2Thor scenes, using configurations and assets stored in h
|
|
|
6
6
|
import json
|
|
7
7
|
import os.path as osp
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import Tuple, Union
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
12
12
|
import sapien
|
|
@@ -79,7 +79,7 @@ class AI2THORBaseSceneBuilder(SceneBuilder):
|
|
|
79
79
|
SEMANTIC_ID_OBJECT_MAPPING,
|
|
80
80
|
MOVEABLE_OBJECT_IDS,
|
|
81
81
|
) = load_ai2thor_metadata()
|
|
82
|
-
self.build_configs:
|
|
82
|
+
self.build_configs: list[AI2BuildConfig] = []
|
|
83
83
|
if self.scene_dataset not in ALL_SCENE_CONFIGS:
|
|
84
84
|
dataset_path = SCENE_SOURCE_TO_DATASET[self.scene_dataset].metadata_path
|
|
85
85
|
with open(osp.join(DATASET_CONFIG_DIR, dataset_path)) as f:
|
|
@@ -93,7 +93,7 @@ class AI2THORBaseSceneBuilder(SceneBuilder):
|
|
|
93
93
|
self.build_configs = ALL_SCENE_CONFIGS[self.scene_dataset]
|
|
94
94
|
|
|
95
95
|
self._navigable_positions = [None] * len(self.build_configs)
|
|
96
|
-
self.build_config_idxs:
|
|
96
|
+
self.build_config_idxs: list[int] = None
|
|
97
97
|
|
|
98
98
|
def _should_be_static(self, template_name: str):
|
|
99
99
|
object_config_json = (
|
|
@@ -110,7 +110,7 @@ class AI2THORBaseSceneBuilder(SceneBuilder):
|
|
|
110
110
|
# TODO (arth): figure out coacd building issues (currenlty fails on > 80% objs)
|
|
111
111
|
def build(
|
|
112
112
|
self,
|
|
113
|
-
build_config_idxs: Union[int,
|
|
113
|
+
build_config_idxs: Union[int, list[int]],
|
|
114
114
|
convex_decomposition="none",
|
|
115
115
|
):
|
|
116
116
|
# build_config_idxs is a list of integers, where the ith value is the scene idx for the ith parallel env
|
|
@@ -121,10 +121,10 @@ class AI2THORBaseSceneBuilder(SceneBuilder):
|
|
|
121
121
|
|
|
122
122
|
# save scene and movable objects when building scene
|
|
123
123
|
self.build_config_idxs = build_config_idxs
|
|
124
|
-
self.scene_objects:
|
|
125
|
-
self.movable_objects:
|
|
126
|
-
self.articulations:
|
|
127
|
-
self._default_object_poses:
|
|
124
|
+
self.scene_objects: dict[str, Actor] = dict()
|
|
125
|
+
self.movable_objects: dict[str, Actor] = dict()
|
|
126
|
+
self.articulations: dict[str, Articulation] = dict()
|
|
127
|
+
self._default_object_poses: list[Tuple[Actor, sapien.Pose]] = []
|
|
128
128
|
|
|
129
129
|
# keep track of background objects separately as we need to disable mobile robot collisions
|
|
130
130
|
# note that we will create a merged actor using these objects to represent the bg
|
|
@@ -292,5 +292,5 @@ class AI2THORBaseSceneBuilder(SceneBuilder):
|
|
|
292
292
|
)
|
|
293
293
|
|
|
294
294
|
@property
|
|
295
|
-
def navigable_positions(self) ->
|
|
295
|
+
def navigable_positions(self) -> list[np.ndarray]:
|
|
296
296
|
return [self._navigable_positions[bci] for bci in self.build_config_idxs]
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
1
|
import numpy as np
|
|
4
2
|
import sapien
|
|
5
3
|
import sapien.render
|
|
@@ -11,7 +9,7 @@ from mani_skill.utils.scene_builder import SceneBuilder
|
|
|
11
9
|
|
|
12
10
|
|
|
13
11
|
class PlanarSceneBuilder(SceneBuilder):
|
|
14
|
-
def build(self, build_config_idxs:
|
|
12
|
+
def build(self, build_config_idxs: list[int] = None):
|
|
15
13
|
# ground - a strip with length along +x
|
|
16
14
|
self.ground = build_ground(
|
|
17
15
|
self.scene,
|
|
@@ -31,4 +29,4 @@ class PlanarSceneBuilder(SceneBuilder):
|
|
|
31
29
|
),
|
|
32
30
|
)
|
|
33
31
|
self.wall.build_static(name="wall")
|
|
34
|
-
self.scene_objects:
|
|
32
|
+
self.scene_objects: list[sapien.Entity] = [self.ground, self.wall]
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import os.path as osp
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import List
|
|
4
3
|
|
|
5
4
|
import numpy as np
|
|
6
5
|
import sapien
|
|
@@ -34,7 +33,7 @@ class KitchenCounterSceneBuilder(SceneBuilder):
|
|
|
34
33
|
floor_width = 500
|
|
35
34
|
self.ground = build_ground(self.scene, floor_width=floor_width, altitude=0)
|
|
36
35
|
self.table = table
|
|
37
|
-
self.scene_objects:
|
|
36
|
+
self.scene_objects: list[sapien.Entity] = [self.table, self.ground]
|
|
38
37
|
|
|
39
38
|
def initialize(self, env_idx: torch.Tensor):
|
|
40
39
|
pass
|