mani-skill-nightly 2025.5.3.1548__py3-none-any.whl → 2025.5.3.1619__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.
- mani_skill/envs/tasks/mobile_manipulation/open_cabinet_drawer.py +2 -2
- mani_skill/utils/structs/actor.py +19 -8
- mani_skill/utils/structs/articulation.py +15 -6
- mani_skill/utils/wrappers/action_repeat.py +85 -0
- {mani_skill_nightly-2025.5.3.1548.dist-info → mani_skill_nightly-2025.5.3.1619.dist-info}/METADATA +1 -1
- {mani_skill_nightly-2025.5.3.1548.dist-info → mani_skill_nightly-2025.5.3.1619.dist-info}/RECORD +9 -8
- {mani_skill_nightly-2025.5.3.1548.dist-info → mani_skill_nightly-2025.5.3.1619.dist-info}/LICENSE +0 -0
- {mani_skill_nightly-2025.5.3.1548.dist-info → mani_skill_nightly-2025.5.3.1619.dist-info}/WHEEL +0 -0
- {mani_skill_nightly-2025.5.3.1548.dist-info → mani_skill_nightly-2025.5.3.1619.dist-info}/top_level.txt +0 -0
@@ -131,7 +131,7 @@ class OpenCabinetDrawerEnv(BaseEnv):
|
|
131
131
|
model_ids = self._batched_episode_rng.choice(self.all_model_ids)
|
132
132
|
link_ids = self._batched_episode_rng.randint(0, 2**31)
|
133
133
|
|
134
|
-
self._cabinets = []
|
134
|
+
self._cabinets: List[Articulation] = []
|
135
135
|
handle_links: List[List[Link]] = []
|
136
136
|
handle_links_meshes: List[List[trimesh.Trimesh]] = []
|
137
137
|
for i, model_id in enumerate(model_ids):
|
@@ -163,7 +163,7 @@ class OpenCabinetDrawerEnv(BaseEnv):
|
|
163
163
|
handle_links[-1].append(link)
|
164
164
|
# save the first mesh in the link object that correspond with a handle
|
165
165
|
handle_links_meshes[-1].append(
|
166
|
-
link.
|
166
|
+
link.generate_mesh(
|
167
167
|
filter=lambda _, render_shape: "handle"
|
168
168
|
in render_shape.name,
|
169
169
|
mesh_name="handle",
|
@@ -242,27 +242,33 @@ class Actor(PhysxRigidDynamicComponentStruct[sapien.Entity]):
|
|
242
242
|
cg[group] = value
|
243
243
|
cs.set_collision_groups(cg)
|
244
244
|
|
245
|
-
def get_first_collision_mesh(
|
245
|
+
def get_first_collision_mesh(
|
246
|
+
self, to_world_frame: bool = True
|
247
|
+
) -> Union[trimesh.Trimesh, None]:
|
246
248
|
"""
|
247
249
|
Returns the collision mesh of the first managed actor object. Note results of this are not cached or optimized at the moment
|
248
|
-
so this function can be slow if called too often
|
250
|
+
so this function can be slow if called too often. Some actors have no collision meshes, in which case this function returns None
|
249
251
|
|
250
252
|
Args:
|
251
253
|
to_world_frame (bool): Whether to transform the collision mesh pose to the world frame
|
252
254
|
"""
|
253
|
-
|
255
|
+
mesh = self.get_collision_meshes(to_world_frame=to_world_frame, first_only=True)
|
256
|
+
if isinstance(mesh, trimesh.Trimesh):
|
257
|
+
return mesh
|
258
|
+
return None
|
254
259
|
|
255
260
|
def get_collision_meshes(
|
256
261
|
self, to_world_frame: bool = True, first_only: bool = False
|
257
|
-
) -> List[trimesh.Trimesh]:
|
262
|
+
) -> Union[List[trimesh.Trimesh], trimesh.Trimesh]:
|
258
263
|
"""
|
259
264
|
Returns the collision mesh of each managed actor object. Note results of this are not cached or optimized at the moment
|
260
|
-
so this function can be slow if called too often
|
265
|
+
so this function can be slow if called too often. Some actors have no collision meshes, in which case this function returns an empty list.
|
261
266
|
|
262
267
|
Args:
|
263
268
|
to_world_frame (bool): Whether to transform the collision mesh pose to the world frame
|
264
269
|
first_only (bool): Whether to return the collision mesh of just the first actor managed by this object. If True,
|
265
|
-
this also returns a single Trimesh.Mesh object instead of a list
|
270
|
+
this also returns a single Trimesh.Mesh object instead of a list. This can be useful for efficiency reasons if you know
|
271
|
+
ahead of time all of the managed actors have the same collision mesh
|
266
272
|
"""
|
267
273
|
assert (
|
268
274
|
not self.merged
|
@@ -274,9 +280,12 @@ class Actor(PhysxRigidDynamicComponentStruct[sapien.Entity]):
|
|
274
280
|
actor_meshes = []
|
275
281
|
for comp in actor.components:
|
276
282
|
if isinstance(comp, physx.PhysxRigidBaseComponent):
|
277
|
-
|
283
|
+
merged = merge_meshes(get_component_meshes(comp))
|
284
|
+
if merged is not None:
|
285
|
+
actor_meshes.append(merged)
|
278
286
|
mesh = merge_meshes(actor_meshes)
|
279
|
-
|
287
|
+
if mesh is not None:
|
288
|
+
meshes.append(mesh)
|
280
289
|
if first_only:
|
281
290
|
break
|
282
291
|
if to_world_frame:
|
@@ -287,6 +296,8 @@ class Actor(PhysxRigidDynamicComponentStruct[sapien.Entity]):
|
|
287
296
|
mesh.apply_transform(mat[i].sp.to_transformation_matrix())
|
288
297
|
else:
|
289
298
|
mesh.apply_transform(mat.sp.to_transformation_matrix())
|
299
|
+
if len(meshes) == 0:
|
300
|
+
return []
|
290
301
|
if first_only:
|
291
302
|
return meshes[0]
|
292
303
|
return meshes
|
@@ -320,19 +320,24 @@ class Articulation(BaseStruct[physx.PhysxArticulation]):
|
|
320
320
|
# g0, g1, g2, g3 = s.get_collision_groups()
|
321
321
|
# s.set_collision_groups([g0, g1, g2 | (1 << 29), g3])
|
322
322
|
|
323
|
-
def get_first_collision_mesh(
|
323
|
+
def get_first_collision_mesh(
|
324
|
+
self, to_world_frame: bool = True
|
325
|
+
) -> Union[trimesh.Trimesh, None]:
|
324
326
|
"""
|
325
327
|
Returns the collision mesh of the first managed articulation object. Note results of this are not cached or optimized at the moment
|
326
|
-
so this function can be slow if called too often
|
328
|
+
so this function can be slow if called too often. Some articulations have no collision meshes, in which case this function returns None
|
327
329
|
|
328
330
|
Args:
|
329
331
|
to_world_frame (bool): Whether to transform the collision mesh pose to the world frame
|
330
332
|
"""
|
331
|
-
|
333
|
+
mesh = self.get_collision_meshes(to_world_frame=to_world_frame, first_only=True)
|
334
|
+
if isinstance(mesh, trimesh.Trimesh):
|
335
|
+
return mesh
|
336
|
+
return None
|
332
337
|
|
333
338
|
def get_collision_meshes(
|
334
339
|
self, to_world_frame: bool = True, first_only: bool = False
|
335
|
-
) -> List[trimesh.Trimesh]:
|
340
|
+
) -> Union[List[trimesh.Trimesh], trimesh.Trimesh]:
|
336
341
|
"""
|
337
342
|
Returns the collision mesh of each managed articulation object. Note results of this are not cached or optimized at the moment
|
338
343
|
so this function can be slow if called too often
|
@@ -340,7 +345,8 @@ class Articulation(BaseStruct[physx.PhysxArticulation]):
|
|
340
345
|
Args:
|
341
346
|
to_world_frame (bool): Whether to transform the collision mesh pose to the world frame
|
342
347
|
first_only (bool): Whether to return the collision mesh of just the first articulation managed by this object. If True,
|
343
|
-
this also returns a single Trimesh.Mesh object instead of a list
|
348
|
+
this also returns a single Trimesh.Mesh object instead of a list. This can be useful for efficiency reasons if you know
|
349
|
+
ahead of time all of the managed actors have the same collision mesh
|
344
350
|
"""
|
345
351
|
assert (
|
346
352
|
not self.merged
|
@@ -365,9 +371,12 @@ class Articulation(BaseStruct[physx.PhysxArticulation]):
|
|
365
371
|
link_mesh.apply_transform(pose.sp.to_transformation_matrix())
|
366
372
|
art_meshes.append(link_mesh)
|
367
373
|
mesh = merge_meshes(art_meshes)
|
368
|
-
|
374
|
+
if mesh is not None:
|
375
|
+
meshes.append(mesh)
|
369
376
|
if first_only:
|
370
377
|
break
|
378
|
+
if len(meshes) == 0:
|
379
|
+
return []
|
371
380
|
if first_only:
|
372
381
|
return meshes[0]
|
373
382
|
return meshes
|
@@ -0,0 +1,85 @@
|
|
1
|
+
import torch
|
2
|
+
import gymnasium as gym
|
3
|
+
from mani_skill.envs.sapien_env import BaseEnv
|
4
|
+
from mani_skill.utils.structs.types import Array
|
5
|
+
|
6
|
+
|
7
|
+
class ActionRepeatWrapper(gym.Wrapper):
|
8
|
+
def __init__(self, env: BaseEnv, repeat: int):
|
9
|
+
"""
|
10
|
+
Environment wrapper that repeats the action for a number of steps.
|
11
|
+
This wrapper will perform the same action at most repeat times, if the environment is done before repeating the action repeat times, then we only return valid data (up to the done=True).
|
12
|
+
|
13
|
+
Args:
|
14
|
+
env (BaseEnv): The base environment to wrap.
|
15
|
+
repeat (int): The number of times to repeat the action, repeat=1 means no action repeat (we use perform 1 action per step), repeat=2 means the action is repeated twice, so the environment will step twice with the same action.
|
16
|
+
"""
|
17
|
+
super().__init__(env)
|
18
|
+
self.repeat = repeat
|
19
|
+
|
20
|
+
@property
|
21
|
+
def num_envs(self):
|
22
|
+
return self.base_env.num_envs
|
23
|
+
|
24
|
+
@property
|
25
|
+
def base_env(self) -> BaseEnv:
|
26
|
+
return self.env.unwrapped
|
27
|
+
|
28
|
+
def step(self, action):
|
29
|
+
final_obs, final_rew, final_terminations, final_truncations, infos = (
|
30
|
+
super().step(action)
|
31
|
+
)
|
32
|
+
|
33
|
+
is_obs_dict = isinstance(final_obs, dict)
|
34
|
+
|
35
|
+
dones = torch.logical_or(final_terminations, final_truncations)
|
36
|
+
not_dones = ~dones
|
37
|
+
|
38
|
+
if not_dones.any():
|
39
|
+
for _ in range(self.repeat - 1):
|
40
|
+
new_obs, new_rew, new_terminations, new_truncations, new_infos = (
|
41
|
+
super().step(action)
|
42
|
+
)
|
43
|
+
|
44
|
+
if is_obs_dict:
|
45
|
+
self._update_dict_values(
|
46
|
+
from_dict=new_obs, to_dict=final_obs, not_dones=not_dones
|
47
|
+
)
|
48
|
+
else:
|
49
|
+
final_obs[not_dones] = new_obs[not_dones]
|
50
|
+
|
51
|
+
final_rew[not_dones] += new_rew[not_dones]
|
52
|
+
final_terminations[not_dones] = torch.logical_or(
|
53
|
+
final_terminations, new_terminations
|
54
|
+
)[not_dones]
|
55
|
+
final_truncations[not_dones] = torch.logical_or(
|
56
|
+
final_truncations, new_truncations
|
57
|
+
)[not_dones]
|
58
|
+
self._update_dict_values(
|
59
|
+
from_dict=new_infos, to_dict=infos, not_dones=not_dones
|
60
|
+
)
|
61
|
+
|
62
|
+
dones = torch.logical_or(final_terminations, final_truncations)
|
63
|
+
not_dones = ~dones
|
64
|
+
|
65
|
+
if dones.all():
|
66
|
+
break
|
67
|
+
|
68
|
+
return final_obs, final_rew, final_terminations, final_truncations, infos
|
69
|
+
|
70
|
+
def _update_dict_values(self, from_dict: dict, to_dict: dict, not_dones: Array):
|
71
|
+
"""
|
72
|
+
Recursively updates the values of a dictionary with the values from another dictionary but only for the envs that are not done.
|
73
|
+
This allows us to update the observation and info dictionaries with new values only for the environments that are not done.
|
74
|
+
If a sub-env becomes done, its future step data will be discarded since not_dones will be false for this sub-environment.
|
75
|
+
Therefore the final observation/info will come from the true last step of the sub-env.
|
76
|
+
"""
|
77
|
+
for k, v in from_dict.items():
|
78
|
+
if isinstance(v, dict):
|
79
|
+
self._update_dict_values(
|
80
|
+
from_dict=v, to_dict=to_dict[k], not_dones=not_dones
|
81
|
+
)
|
82
|
+
elif isinstance(v, Array):
|
83
|
+
to_dict[k][not_dones] = v[not_dones]
|
84
|
+
else:
|
85
|
+
to_dict[k] = v
|
{mani_skill_nightly-2025.5.3.1548.dist-info → mani_skill_nightly-2025.5.3.1619.dist-info}/RECORD
RENAMED
@@ -587,7 +587,7 @@ mani_skill/envs/tasks/humanoid/assets/cardboard_box/01.png,sha256=UAzLp_o885YkTu
|
|
587
587
|
mani_skill/envs/tasks/humanoid/assets/cardboard_box/box.mtl,sha256=E7F4ELdSP2Yd62T_rF_-gN1xa6N6Eo3AqAb17R5TSa8,219
|
588
588
|
mani_skill/envs/tasks/humanoid/assets/cardboard_box/textured.obj,sha256=XQEt4EeMiW4kx4GhNOYk8TPi7lSuS6XTEBQjWSsxKJ0,12723
|
589
589
|
mani_skill/envs/tasks/mobile_manipulation/__init__.py,sha256=GQajIA-t_p_9Hrhkj5-MEEmbGfaIkCYgaDepVUdhJ2Q,98
|
590
|
-
mani_skill/envs/tasks/mobile_manipulation/open_cabinet_drawer.py,sha256=
|
590
|
+
mani_skill/envs/tasks/mobile_manipulation/open_cabinet_drawer.py,sha256=xokzhopVVnNJJjm0kyw7OlvrdADmIz7rkxyXG6XPj9E,15938
|
591
591
|
mani_skill/envs/tasks/mobile_manipulation/robocasa/__init__.py,sha256=mjpK3FNM5GnR4CaWfD1i2gVk5tU4N6tTkDm2pCqsfoo,40
|
592
592
|
mani_skill/envs/tasks/mobile_manipulation/robocasa/kitchen.py,sha256=fXLoTIDgk-0eEaH7TrCODYWfVOVkGP6cRzinyfKEkWc,25625
|
593
593
|
mani_skill/envs/tasks/quadruped/__init__.py,sha256=_AHS3H9Cj2XT7--5jwW1NMmVWbZxRpdGDNXudT6OrZM,92
|
@@ -784,8 +784,8 @@ mani_skill/utils/scene_builder/table/assets/Dining_Table_204_1.glb,sha256=IleHi3
|
|
784
784
|
mani_skill/utils/scene_builder/table/assets/table.glb,sha256=yw69itZDjBFg8JXZAr9VQV-dZD-MaZChhqBSJR_nlRo,3891588
|
785
785
|
mani_skill/utils/structs/README.md,sha256=qnYKimp_ZkgNcduURrYQxVTimNmq_usDMKoQ8VtMdCs,286
|
786
786
|
mani_skill/utils/structs/__init__.py,sha256=BItR3Xe0z6xCrMHAEaH0AAAVyeonsQ3q-DJUyRUibAA,524
|
787
|
-
mani_skill/utils/structs/actor.py,sha256=
|
788
|
-
mani_skill/utils/structs/articulation.py,sha256=
|
787
|
+
mani_skill/utils/structs/actor.py,sha256=L0p6vkr8rGtJmF22xAq8Q7nhXKnDD5dahzODSAko0bg,17394
|
788
|
+
mani_skill/utils/structs/articulation.py,sha256=c7e_Rfkhskg_Rqz1bkesqHCTzNubObLGZQS0BkkFZF0,34691
|
789
789
|
mani_skill/utils/structs/articulation_joint.py,sha256=TY6joQ0RpnVlHbQHdtx_QQYqTWgFHLiZ642SSWZUuTw,11736
|
790
790
|
mani_skill/utils/structs/base.py,sha256=meGQK5Y4KtHKLnp9VeOZS2gtwg9tE55whuEeqOguBaI,19465
|
791
791
|
mani_skill/utils/structs/decorators.py,sha256=Lv6wQ989dOnreo2tB-qopDnkeBp_jsn1pmfUR-OY8VQ,535
|
@@ -800,6 +800,7 @@ mani_skill/utils/visualization/jupyter_utils.py,sha256=dXXUQz-rFTOV_Xq5yA6YE6cXg
|
|
800
800
|
mani_skill/utils/visualization/misc.py,sha256=KrDCef7F5GmGOdiBQ4qFUnmUTe-7-nNBz2DVBGFD8YU,5041
|
801
801
|
mani_skill/utils/visualization/renderer.py,sha256=-Z18-fXe5NLBYBYXFB9m2EDKdhOkAdDVWSs9vjxGCSQ,1245
|
802
802
|
mani_skill/utils/wrappers/__init__.py,sha256=f6HDHHoM8gyNgX5RwTr2u3oGlAeHqawRvVNQiWXEJfI,229
|
803
|
+
mani_skill/utils/wrappers/action_repeat.py,sha256=RhCtzt3fYCtD-CClIOhAzdycGwVTXP_FG61yEf-QLqY,3542
|
803
804
|
mani_skill/utils/wrappers/flatten.py,sha256=GuHJ3fCOdj9G_jm--XgG8k0p2G1eJx4LY1tesQQjnkg,4913
|
804
805
|
mani_skill/utils/wrappers/frame_stack.py,sha256=pCp83HqXnFxbsKRYgwXreNBHnhD-yF0R2_7jdtGOTWQ,4213
|
805
806
|
mani_skill/utils/wrappers/gymnasium.py,sha256=p0kl29kkedD2arIvGskClKhYDBAH97mZO4rTepz62jQ,4174
|
@@ -810,8 +811,8 @@ mani_skill/vector/wrappers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
810
811
|
mani_skill/vector/wrappers/gymnasium.py,sha256=v1MDPIrVACBKCulrpdXBK2jDZQI7LKYFZgGgaCC5avY,7408
|
811
812
|
mani_skill/vector/wrappers/sb3.py,sha256=SlXdiEPqcNHYMhJCzA29kBU6zK7DKTe1nc0L6Z3QQtY,4722
|
812
813
|
mani_skill/viewer/__init__.py,sha256=srvDBsk4LQU75K2VIttrhiQ68p_ro7PSDqQRls2PY5c,1722
|
813
|
-
mani_skill_nightly-2025.5.3.
|
814
|
-
mani_skill_nightly-2025.5.3.
|
815
|
-
mani_skill_nightly-2025.5.3.
|
816
|
-
mani_skill_nightly-2025.5.3.
|
817
|
-
mani_skill_nightly-2025.5.3.
|
814
|
+
mani_skill_nightly-2025.5.3.1619.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
815
|
+
mani_skill_nightly-2025.5.3.1619.dist-info/METADATA,sha256=_GtuLPVaaiZsUUCPLl9Twf3rCk5MAQnQkGuxVJ5hjsY,9291
|
816
|
+
mani_skill_nightly-2025.5.3.1619.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
817
|
+
mani_skill_nightly-2025.5.3.1619.dist-info/top_level.txt,sha256=bkBgOVl_MZMoQx2aRFsSFEYlZLxjWlip5vtJ39FB3jA,11
|
818
|
+
mani_skill_nightly-2025.5.3.1619.dist-info/RECORD,,
|
{mani_skill_nightly-2025.5.3.1548.dist-info → mani_skill_nightly-2025.5.3.1619.dist-info}/LICENSE
RENAMED
File without changes
|
{mani_skill_nightly-2025.5.3.1548.dist-info → mani_skill_nightly-2025.5.3.1619.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|