mani-skill-nightly 2025.5.3.1545__py3-none-any.whl → 2025.5.3.1612__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/agents/robots/xarm6/xarm6_robotiq.py +12 -0
- mani_skill/envs/tasks/mobile_manipulation/open_cabinet_drawer.py +2 -2
- mani_skill/envs/tasks/tabletop/plug_charger.py +22 -21
- mani_skill/examples/motionplanning/xarm6/__init__.py +0 -0
- mani_skill/examples/motionplanning/xarm6/motionplanner.py +111 -0
- mani_skill/examples/motionplanning/xarm6/run.py +148 -0
- mani_skill/examples/motionplanning/xarm6/solutions/__init__.py +4 -0
- mani_skill/examples/motionplanning/xarm6/solutions/pick_cube.py +66 -0
- mani_skill/examples/motionplanning/xarm6/solutions/plug_charger.py +111 -0
- mani_skill/examples/motionplanning/xarm6/solutions/push_cube.py +38 -0
- mani_skill/examples/motionplanning/xarm6/solutions/stack_cube.py +92 -0
- mani_skill/utils/assets/data.py +1 -0
- mani_skill/utils/structs/actor.py +19 -8
- mani_skill/utils/structs/articulation.py +15 -6
- {mani_skill_nightly-2025.5.3.1545.dist-info → mani_skill_nightly-2025.5.3.1612.dist-info}/METADATA +1 -1
- {mani_skill_nightly-2025.5.3.1545.dist-info → mani_skill_nightly-2025.5.3.1612.dist-info}/RECORD +19 -11
- {mani_skill_nightly-2025.5.3.1545.dist-info → mani_skill_nightly-2025.5.3.1612.dist-info}/LICENSE +0 -0
- {mani_skill_nightly-2025.5.3.1545.dist-info → mani_skill_nightly-2025.5.3.1612.dist-info}/WHEEL +0 -0
- {mani_skill_nightly-2025.5.3.1545.dist-info → mani_skill_nightly-2025.5.3.1612.dist-info}/top_level.txt +0 -0
@@ -403,6 +403,18 @@ class XArm6Robotiq(BaseAgent):
|
|
403
403
|
)
|
404
404
|
return torch.logical_and(lflag, rflag)
|
405
405
|
|
406
|
+
@staticmethod
|
407
|
+
def build_grasp_pose(approaching, closing, center):
|
408
|
+
"""Build a grasp pose ()."""
|
409
|
+
assert np.abs(1 - np.linalg.norm(approaching)) < 1e-3
|
410
|
+
assert np.abs(1 - np.linalg.norm(closing)) < 1e-3
|
411
|
+
assert np.abs(approaching @ closing) <= 1e-3
|
412
|
+
ortho = np.cross(closing, approaching)
|
413
|
+
T = np.eye(4)
|
414
|
+
T[:3, :3] = np.stack([ortho, closing, approaching], axis=1)
|
415
|
+
T[:3, 3] = center
|
416
|
+
return sapien.Pose(T)
|
417
|
+
|
406
418
|
def is_static(self, threshold: float = 0.2):
|
407
419
|
qvel = self.robot.get_qvel()[..., :-6]
|
408
420
|
return torch.max(torch.abs(qvel), 1)[0] <= threshold
|
@@ -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",
|
@@ -183,28 +183,29 @@ class PlugChargerEnv(BaseEnv):
|
|
183
183
|
self.scene_builder.initialize(env_idx)
|
184
184
|
|
185
185
|
# Initialize agent
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
qpos = (
|
200
|
-
torch.normal(
|
201
|
-
0, self.robot_init_qpos_noise, (b, len(qpos)), device=self.device
|
186
|
+
if self.agent.uid == "panda_wristcam":
|
187
|
+
qpos = torch.tensor(
|
188
|
+
[
|
189
|
+
0.0,
|
190
|
+
np.pi / 8,
|
191
|
+
0,
|
192
|
+
-np.pi * 5 / 8,
|
193
|
+
0,
|
194
|
+
np.pi * 3 / 4,
|
195
|
+
np.pi / 4,
|
196
|
+
0.04,
|
197
|
+
0.04,
|
198
|
+
]
|
202
199
|
)
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
200
|
+
qpos = (
|
201
|
+
torch.normal(
|
202
|
+
0, self.robot_init_qpos_noise, (b, len(qpos)), device=self.device
|
203
|
+
)
|
204
|
+
+ qpos
|
205
|
+
)
|
206
|
+
qpos[:, -2:] = 0.04
|
207
|
+
self.agent.robot.set_qpos(qpos)
|
208
|
+
self.agent.robot.set_pose(sapien.Pose([-0.615, 0, 0]))
|
208
209
|
|
209
210
|
# Initialize charger
|
210
211
|
xy = randomization.uniform(
|
File without changes
|
@@ -0,0 +1,111 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import mplib
|
3
|
+
from mani_skill.examples.motionplanning.panda.motionplanner import PandaArmMotionPlanningSolver
|
4
|
+
from mani_skill.envs.sapien_env import BaseEnv
|
5
|
+
import sapien.core as sapien
|
6
|
+
|
7
|
+
from mani_skill.utils.structs.pose import to_sapien_pose
|
8
|
+
|
9
|
+
|
10
|
+
class XArm6RobotiqMotionPlanningSolver(PandaArmMotionPlanningSolver):
|
11
|
+
CLOSED = 0.81
|
12
|
+
OPEN = 0
|
13
|
+
|
14
|
+
def __init__(self, env: BaseEnv, debug: bool = False, vis: bool = True, base_pose: sapien.Pose = None, visualize_target_grasp_pose: bool = True, print_env_info: bool = True, joint_vel_limits=0.9, joint_acc_limits=0.9):
|
15
|
+
super().__init__(env, debug, vis, base_pose, visualize_target_grasp_pose, print_env_info, joint_vel_limits, joint_acc_limits)
|
16
|
+
self.gripper_state = self.OPEN
|
17
|
+
|
18
|
+
def setup_planner(self):
|
19
|
+
link_names = [link.get_name() for link in self.robot.get_links()]
|
20
|
+
joint_names = [joint.get_name() for joint in self.robot.get_active_joints()]
|
21
|
+
planner = mplib.Planner(
|
22
|
+
urdf=self.env_agent.urdf_path,
|
23
|
+
srdf=self.env_agent.urdf_path.replace(".urdf", ".srdf"),
|
24
|
+
user_link_names=link_names,
|
25
|
+
user_joint_names=joint_names,
|
26
|
+
move_group="eef",
|
27
|
+
joint_vel_limits=np.ones(6) * self.joint_vel_limits,
|
28
|
+
joint_acc_limits=np.ones(6) * self.joint_acc_limits,
|
29
|
+
)
|
30
|
+
planner.set_base_pose(np.hstack([self.base_pose.p, self.base_pose.q]))
|
31
|
+
return planner
|
32
|
+
|
33
|
+
def open_gripper(self):
|
34
|
+
self.gripper_state = self.OPEN
|
35
|
+
qpos = self.robot.get_qpos()[0, :6].cpu().numpy()
|
36
|
+
for i in range(6):
|
37
|
+
if self.control_mode == "pd_joint_pos":
|
38
|
+
action = np.hstack([qpos, self.gripper_state])
|
39
|
+
else:
|
40
|
+
action = np.hstack([qpos, qpos * 0, self.gripper_state])
|
41
|
+
obs, reward, terminated, truncated, info = self.env.step(action)
|
42
|
+
self.elapsed_steps += 1
|
43
|
+
if self.print_env_info:
|
44
|
+
print(
|
45
|
+
f"[{self.elapsed_steps:3}] Env Output: reward={reward} info={info}"
|
46
|
+
)
|
47
|
+
if self.vis:
|
48
|
+
self.base_env.render_human()
|
49
|
+
return obs, reward, terminated, truncated, info
|
50
|
+
|
51
|
+
def close_gripper(self, t=6, gripper_state = CLOSED):
|
52
|
+
self.gripper_state = gripper_state
|
53
|
+
qpos = self.robot.get_qpos()[0, :6].cpu().numpy()
|
54
|
+
for i in range(t):
|
55
|
+
if self.control_mode == "pd_joint_pos":
|
56
|
+
action = np.hstack([qpos, self.gripper_state])
|
57
|
+
else:
|
58
|
+
action = np.hstack([qpos, qpos * 0, self.gripper_state])
|
59
|
+
obs, reward, terminated, truncated, info = self.env.step(action)
|
60
|
+
self.elapsed_steps += 1
|
61
|
+
if self.print_env_info:
|
62
|
+
print(
|
63
|
+
f"[{self.elapsed_steps:3}] Env Output: reward={reward} info={info}"
|
64
|
+
)
|
65
|
+
if self.vis:
|
66
|
+
self.base_env.render_human()
|
67
|
+
return obs, reward, terminated, truncated, info
|
68
|
+
|
69
|
+
def move_to_pose_with_RRTStar(
|
70
|
+
self, pose: sapien.Pose, dry_run: bool = False, refine_steps: int = 0
|
71
|
+
):
|
72
|
+
pose = to_sapien_pose(pose)
|
73
|
+
if self.grasp_pose_visual is not None:
|
74
|
+
self.grasp_pose_visual.set_pose(pose)
|
75
|
+
pose = sapien.Pose(p=pose.p, q=pose.q)
|
76
|
+
result = self.planner.plan_qpos_to_pose(
|
77
|
+
np.concatenate([pose.p, pose.q]),
|
78
|
+
self.robot.get_qpos().cpu().numpy()[0],
|
79
|
+
time_step=self.base_env.control_timestep,
|
80
|
+
use_point_cloud=self.use_point_cloud,
|
81
|
+
rrt_range=0.0,
|
82
|
+
planning_time=1,
|
83
|
+
planner_name="RRTstar",
|
84
|
+
wrt_world=True,
|
85
|
+
)
|
86
|
+
if result["status"] != "Success":
|
87
|
+
print(result["status"])
|
88
|
+
self.render_wait()
|
89
|
+
return -1
|
90
|
+
self.render_wait()
|
91
|
+
if dry_run:
|
92
|
+
return result
|
93
|
+
return self.follow_path(result, refine_steps=refine_steps)
|
94
|
+
|
95
|
+
|
96
|
+
class XArm6PandaGripperMotionPlanningSolver(PandaArmMotionPlanningSolver):
|
97
|
+
def setup_planner(self):
|
98
|
+
link_names = [link.get_name() for link in self.robot.get_links()]
|
99
|
+
joint_names = [joint.get_name() for joint in self.robot.get_active_joints()]
|
100
|
+
planner = mplib.Planner(
|
101
|
+
urdf=self.env_agent.urdf_path,
|
102
|
+
srdf=self.env_agent.urdf_path.replace(".urdf", ".srdf"),
|
103
|
+
user_link_names=link_names,
|
104
|
+
user_joint_names=joint_names,
|
105
|
+
move_group="panda_hand_tcp",
|
106
|
+
joint_vel_limits=np.ones(6) * self.joint_vel_limits,
|
107
|
+
joint_acc_limits=np.ones(6) * self.joint_acc_limits,
|
108
|
+
)
|
109
|
+
planner.set_base_pose(np.hstack([self.base_pose.p, self.base_pose.q]))
|
110
|
+
return planner
|
111
|
+
|
@@ -0,0 +1,148 @@
|
|
1
|
+
import multiprocessing as mp
|
2
|
+
import os
|
3
|
+
from copy import deepcopy
|
4
|
+
import time
|
5
|
+
import argparse
|
6
|
+
import gymnasium as gym
|
7
|
+
import numpy as np
|
8
|
+
from tqdm import tqdm
|
9
|
+
import os.path as osp
|
10
|
+
from mani_skill.utils.wrappers.record import RecordEpisode
|
11
|
+
from mani_skill.trajectory.merge_trajectory import merge_trajectories
|
12
|
+
from mani_skill.examples.motionplanning.xarm6.solutions import solvePickCube, solvePushCube, solveStackCube, solvePlugCharger
|
13
|
+
|
14
|
+
MP_SOLUTIONS = {
|
15
|
+
"PickCube-v1": solvePickCube,
|
16
|
+
"PushCube-v1": solvePushCube,
|
17
|
+
"StackCube-v1": solveStackCube,
|
18
|
+
"PlugCharger-v1": solvePlugCharger,
|
19
|
+
}
|
20
|
+
|
21
|
+
def parse_args(args=None):
|
22
|
+
parser = argparse.ArgumentParser()
|
23
|
+
parser.add_argument("-e", "--env-id", type=str, default="PickCube-v1", help=f"Environment to run motion planning solver on. Available options are {list(MP_SOLUTIONS.keys())}")
|
24
|
+
parser.add_argument("-o", "--obs-mode", type=str, default="none", help="Observation mode to use. Usually this is kept as 'none' as observations are not necesary to be stored, they can be replayed later via the mani_skill.trajectory.replay_trajectory script.")
|
25
|
+
parser.add_argument("-n", "--num-traj", type=int, default=10, help="Number of trajectories to generate.")
|
26
|
+
parser.add_argument("--only-count-success", action="store_true", help="If true, generates trajectories until num_traj of them are successful and only saves the successful trajectories/videos")
|
27
|
+
parser.add_argument("--reward-mode", type=str)
|
28
|
+
parser.add_argument("-b", "--sim-backend", type=str, default="auto", help="Which simulation backend to use. Can be 'auto', 'cpu', 'gpu'")
|
29
|
+
parser.add_argument("--render-mode", type=str, default="rgb_array", help="can be 'sensors' or 'rgb_array' which only affect what is saved to videos")
|
30
|
+
parser.add_argument("--vis", action="store_true", help="whether or not to open a GUI to visualize the solution live")
|
31
|
+
parser.add_argument("--save-video", action="store_true", help="whether or not to save videos locally")
|
32
|
+
parser.add_argument("--traj-name", type=str, help="The name of the trajectory .h5 file that will be created.")
|
33
|
+
parser.add_argument("--shader", default="default", type=str, help="Change shader used for rendering. Default is 'default' which is very fast. Can also be 'rt' for ray tracing and generating photo-realistic renders. Can also be 'rt-fast' for a faster but lower quality ray-traced renderer")
|
34
|
+
parser.add_argument("--record-dir", type=str, default="demos", help="where to save the recorded trajectories")
|
35
|
+
parser.add_argument("--num-procs", type=int, default=1, help="Number of processes to use to help parallelize the trajectory replay process. This uses CPU multiprocessing and only works with the CPU simulation backend at the moment.")
|
36
|
+
return parser.parse_args()
|
37
|
+
|
38
|
+
def _main(args, proc_id: int = 0, start_seed: int = 0) -> str:
|
39
|
+
env_id = args.env_id
|
40
|
+
env = gym.make(
|
41
|
+
env_id,
|
42
|
+
obs_mode=args.obs_mode,
|
43
|
+
control_mode="pd_joint_pos",
|
44
|
+
render_mode=args.render_mode,
|
45
|
+
robot_uids="xarm6_robotiq",
|
46
|
+
reward_mode="dense" if args.reward_mode is None else args.reward_mode,
|
47
|
+
sensor_configs=dict(shader_pack=args.shader),
|
48
|
+
human_render_camera_configs=dict(shader_pack=args.shader),
|
49
|
+
viewer_camera_configs=dict(shader_pack=args.shader),
|
50
|
+
sim_backend=args.sim_backend
|
51
|
+
)
|
52
|
+
if env_id not in MP_SOLUTIONS:
|
53
|
+
raise RuntimeError(f"No already written motion planning solutions for {env_id}. Available options are {list(MP_SOLUTIONS.keys())}")
|
54
|
+
|
55
|
+
if not args.traj_name:
|
56
|
+
new_traj_name = time.strftime("%Y%m%d_%H%M%S")
|
57
|
+
else:
|
58
|
+
new_traj_name = args.traj_name
|
59
|
+
|
60
|
+
if args.num_procs > 1:
|
61
|
+
new_traj_name = new_traj_name + "." + str(proc_id)
|
62
|
+
env = RecordEpisode(
|
63
|
+
env,
|
64
|
+
output_dir=osp.join(args.record_dir, env_id, "motionplanning"),
|
65
|
+
trajectory_name=new_traj_name, save_video=args.save_video,
|
66
|
+
source_type="motionplanning",
|
67
|
+
source_desc="official motion planning solution from ManiSkill contributors",
|
68
|
+
video_fps=30,
|
69
|
+
save_on_reset=False
|
70
|
+
)
|
71
|
+
output_h5_path = env._h5_file.filename
|
72
|
+
solve = MP_SOLUTIONS[env_id]
|
73
|
+
print(f"Motion Planning Running on {env_id}")
|
74
|
+
pbar = tqdm(range(args.num_traj), desc=f"proc_id: {proc_id}")
|
75
|
+
seed = start_seed
|
76
|
+
successes = []
|
77
|
+
solution_episode_lengths = []
|
78
|
+
failed_motion_plans = 0
|
79
|
+
passed = 0
|
80
|
+
while True:
|
81
|
+
try:
|
82
|
+
res = solve(env, seed=seed, debug=False, vis=True if args.vis else False)
|
83
|
+
except Exception as e:
|
84
|
+
print(f"Cannot find valid solution because of an error in motion planning solution: {e}")
|
85
|
+
res = -1
|
86
|
+
|
87
|
+
if res == -1:
|
88
|
+
success = False
|
89
|
+
failed_motion_plans += 1
|
90
|
+
else:
|
91
|
+
success = res[-1]["success"].item()
|
92
|
+
elapsed_steps = res[-1]["elapsed_steps"].item()
|
93
|
+
solution_episode_lengths.append(elapsed_steps)
|
94
|
+
successes.append(success)
|
95
|
+
if args.only_count_success and not success:
|
96
|
+
seed += 1
|
97
|
+
env.flush_trajectory(save=False)
|
98
|
+
if args.save_video:
|
99
|
+
env.flush_video(save=False)
|
100
|
+
continue
|
101
|
+
else:
|
102
|
+
env.flush_trajectory()
|
103
|
+
if args.save_video:
|
104
|
+
env.flush_video()
|
105
|
+
pbar.update(1)
|
106
|
+
pbar.set_postfix(
|
107
|
+
dict(
|
108
|
+
success_rate=np.mean(successes),
|
109
|
+
failed_motion_plan_rate=failed_motion_plans / (seed + 1),
|
110
|
+
avg_episode_length=np.mean(solution_episode_lengths),
|
111
|
+
max_episode_length=np.max(solution_episode_lengths),
|
112
|
+
# min_episode_length=np.min(solution_episode_lengths)
|
113
|
+
)
|
114
|
+
)
|
115
|
+
seed += 1
|
116
|
+
passed += 1
|
117
|
+
if passed == args.num_traj:
|
118
|
+
break
|
119
|
+
env.close()
|
120
|
+
return output_h5_path
|
121
|
+
|
122
|
+
def main(args):
|
123
|
+
if args.num_procs > 1 and args.num_procs < args.num_traj:
|
124
|
+
if args.num_traj < args.num_procs:
|
125
|
+
raise ValueError("Number of trajectories should be greater than or equal to number of processes")
|
126
|
+
args.num_traj = args.num_traj // args.num_procs
|
127
|
+
seeds = [*range(0, args.num_procs * args.num_traj, args.num_traj)]
|
128
|
+
pool = mp.Pool(args.num_procs)
|
129
|
+
proc_args = [(deepcopy(args), i, seeds[i]) for i in range(args.num_procs)]
|
130
|
+
res = pool.starmap(_main, proc_args)
|
131
|
+
pool.close()
|
132
|
+
# Merge trajectory files
|
133
|
+
output_path = res[0][: -len("0.h5")] + "h5"
|
134
|
+
merge_trajectories(output_path, res)
|
135
|
+
for h5_path in res:
|
136
|
+
tqdm.write(f"Remove {h5_path}")
|
137
|
+
os.remove(h5_path)
|
138
|
+
json_path = h5_path.replace(".h5", ".json")
|
139
|
+
tqdm.write(f"Remove {json_path}")
|
140
|
+
os.remove(json_path)
|
141
|
+
else:
|
142
|
+
_main(args)
|
143
|
+
|
144
|
+
if __name__ == "__main__":
|
145
|
+
# start = time.time()
|
146
|
+
mp.set_start_method("spawn")
|
147
|
+
main(parse_args())
|
148
|
+
# print(f"Total time taken: {time.time() - start}")
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import sapien
|
3
|
+
|
4
|
+
from mani_skill.envs.tasks import PickCubeEnv
|
5
|
+
from mani_skill.examples.motionplanning.xarm6.motionplanner import \
|
6
|
+
XArm6RobotiqMotionPlanningSolver, XArm6PandaGripperMotionPlanningSolver
|
7
|
+
from mani_skill.examples.motionplanning.panda.utils import (
|
8
|
+
compute_grasp_info_by_obb, get_actor_obb)
|
9
|
+
|
10
|
+
def solve(env: PickCubeEnv, seed=None, debug=False, vis=False):
|
11
|
+
env.reset(seed=seed)
|
12
|
+
|
13
|
+
if env.unwrapped.robot_uids == "xarm6_robotiq":
|
14
|
+
planner_cls = XArm6RobotiqMotionPlanningSolver
|
15
|
+
elif env.unwrapped.robot_uids == "xarm6_pandagripper":
|
16
|
+
planner_cls = XArm6PandaGripperMotionPlanningSolver
|
17
|
+
else:
|
18
|
+
raise ValueError(f"Unsupported robot uid: {env.robot_uid}")
|
19
|
+
planner = planner_cls(
|
20
|
+
env,
|
21
|
+
debug=debug,
|
22
|
+
vis=vis,
|
23
|
+
base_pose=env.unwrapped.agent.robot.pose,
|
24
|
+
visualize_target_grasp_pose=vis,
|
25
|
+
print_env_info=False,
|
26
|
+
)
|
27
|
+
|
28
|
+
FINGER_LENGTH = 0.025
|
29
|
+
env = env.unwrapped
|
30
|
+
|
31
|
+
# retrieves the object oriented bounding box (trimesh box object)
|
32
|
+
obb = get_actor_obb(env.cube)
|
33
|
+
|
34
|
+
approaching = np.array([0, 0, -1])
|
35
|
+
# get transformation matrix of the tcp pose, is default batched and on torch
|
36
|
+
target_closing = env.agent.tcp.pose.to_transformation_matrix()[0, :3, 1].cpu().numpy()
|
37
|
+
# we can build a simple grasp pose using this information
|
38
|
+
grasp_info = compute_grasp_info_by_obb(
|
39
|
+
obb,
|
40
|
+
approaching=approaching,
|
41
|
+
target_closing=target_closing,
|
42
|
+
depth=FINGER_LENGTH,
|
43
|
+
)
|
44
|
+
closing, center = grasp_info["closing"], grasp_info["center"]
|
45
|
+
grasp_pose = env.agent.build_grasp_pose(approaching, closing, env.cube.pose.sp.p)
|
46
|
+
|
47
|
+
# -------------------------------------------------------------------------- #
|
48
|
+
# Reach
|
49
|
+
# -------------------------------------------------------------------------- #
|
50
|
+
reach_pose = grasp_pose * sapien.Pose([0, 0, -0.05])
|
51
|
+
planner.move_to_pose_with_RRTStar(reach_pose)
|
52
|
+
|
53
|
+
# -------------------------------------------------------------------------- #
|
54
|
+
# Grasp
|
55
|
+
# -------------------------------------------------------------------------- #
|
56
|
+
planner.move_to_pose_with_screw(grasp_pose)
|
57
|
+
planner.close_gripper()
|
58
|
+
|
59
|
+
# -------------------------------------------------------------------------- #
|
60
|
+
# Move to goal pose
|
61
|
+
# -------------------------------------------------------------------------- #
|
62
|
+
goal_pose = sapien.Pose(env.goal_site.pose.sp.p, grasp_pose.q)
|
63
|
+
res = planner.move_to_pose_with_screw(goal_pose)
|
64
|
+
|
65
|
+
planner.close()
|
66
|
+
return res
|
@@ -0,0 +1,111 @@
|
|
1
|
+
import gymnasium as gym
|
2
|
+
import numpy as np
|
3
|
+
import sapien.core as sapien
|
4
|
+
import trimesh
|
5
|
+
from tqdm import tqdm
|
6
|
+
from transforms3d.euler import euler2quat
|
7
|
+
|
8
|
+
from mani_skill.envs.tasks import PlugChargerEnv
|
9
|
+
from mani_skill.examples.motionplanning.xarm6.motionplanner import \
|
10
|
+
XArm6RobotiqMotionPlanningSolver, XArm6PandaGripperMotionPlanningSolver
|
11
|
+
from mani_skill.examples.motionplanning.panda.utils import (
|
12
|
+
compute_grasp_info_by_obb, get_actor_obb)
|
13
|
+
|
14
|
+
|
15
|
+
def main():
|
16
|
+
env: PlugChargerEnv = gym.make(
|
17
|
+
"PlugCharger-v1",
|
18
|
+
obs_mode="none",
|
19
|
+
control_mode="pd_joint_pos",
|
20
|
+
render_mode="rgb_array",
|
21
|
+
reward_mode="sparse",
|
22
|
+
)
|
23
|
+
for seed in tqdm(range(100)):
|
24
|
+
res = solve(env, seed=seed, debug=False, vis=True)
|
25
|
+
print(res[-1])
|
26
|
+
env.close()
|
27
|
+
|
28
|
+
|
29
|
+
def solve(env: PlugChargerEnv, seed=None, debug=False, vis=False):
|
30
|
+
env.reset(seed=seed)
|
31
|
+
assert env.unwrapped.control_mode in [
|
32
|
+
"pd_joint_pos",
|
33
|
+
"pd_joint_pos_vel",
|
34
|
+
], env.unwrapped.control_mode
|
35
|
+
if env.unwrapped.robot_uids == "xarm6_robotiq":
|
36
|
+
planner_cls = XArm6RobotiqMotionPlanningSolver
|
37
|
+
elif env.unwrapped.robot_uids == "xarm6_pandagripper":
|
38
|
+
planner_cls = XArm6PandaGripperMotionPlanningSolver
|
39
|
+
else:
|
40
|
+
raise ValueError(f"Unsupported robot uid: {env.robot_uid}")
|
41
|
+
planner = planner_cls(
|
42
|
+
env,
|
43
|
+
debug=debug,
|
44
|
+
vis=vis,
|
45
|
+
base_pose=env.unwrapped.agent.robot.pose,
|
46
|
+
visualize_target_grasp_pose=False,
|
47
|
+
print_env_info=False,
|
48
|
+
joint_vel_limits=0.5,
|
49
|
+
joint_acc_limits=0.5,
|
50
|
+
)
|
51
|
+
|
52
|
+
FINGER_LENGTH = 0.025
|
53
|
+
env = env.unwrapped
|
54
|
+
charger_base_pose = env.charger_base_pose
|
55
|
+
charger_base_size = np.array(env.unwrapped._base_size) * 2
|
56
|
+
|
57
|
+
obb = trimesh.primitives.Box(
|
58
|
+
extents=charger_base_size,
|
59
|
+
transform=charger_base_pose.sp.to_transformation_matrix(),
|
60
|
+
)
|
61
|
+
|
62
|
+
approaching = np.array([0, 0, -1])
|
63
|
+
target_closing = env.agent.tcp.pose.sp.to_transformation_matrix()[:3, 1]
|
64
|
+
grasp_info = compute_grasp_info_by_obb(
|
65
|
+
obb,
|
66
|
+
approaching=approaching,
|
67
|
+
target_closing=target_closing,
|
68
|
+
depth=FINGER_LENGTH,
|
69
|
+
)
|
70
|
+
closing, center = grasp_info["closing"], grasp_info["center"]
|
71
|
+
grasp_pose = env.agent.build_grasp_pose(approaching, closing, center)
|
72
|
+
|
73
|
+
# add a angle to grasp
|
74
|
+
grasp_angle = np.deg2rad(15)
|
75
|
+
grasp_pose = grasp_pose * sapien.Pose(q=euler2quat(0, grasp_angle, 0))
|
76
|
+
|
77
|
+
# -------------------------------------------------------------------------- #
|
78
|
+
# Reach
|
79
|
+
# -------------------------------------------------------------------------- #
|
80
|
+
reach_pose = grasp_pose * sapien.Pose([0, 0, -0.05])
|
81
|
+
planner.move_to_pose_with_RRTStar(reach_pose)
|
82
|
+
|
83
|
+
# -------------------------------------------------------------------------- #
|
84
|
+
# Grasp
|
85
|
+
# -------------------------------------------------------------------------- #
|
86
|
+
planner.move_to_pose_with_screw(grasp_pose)
|
87
|
+
planner.close_gripper()
|
88
|
+
|
89
|
+
# -------------------------------------------------------------------------- #
|
90
|
+
# Align
|
91
|
+
# -------------------------------------------------------------------------- #
|
92
|
+
pre_insert_pose = (
|
93
|
+
env.goal_pose.sp
|
94
|
+
* sapien.Pose([-0.05, 0.0, 0.0])
|
95
|
+
* env.charger.pose.sp.inv()
|
96
|
+
* env.agent.tcp.pose.sp
|
97
|
+
)
|
98
|
+
insert_pose = env.goal_pose.sp * env.charger.pose.sp.inv() * env.agent.tcp.pose.sp * sapien.Pose([0, 0, -0.005])
|
99
|
+
planner.move_to_pose_with_screw(pre_insert_pose, refine_steps=0)
|
100
|
+
planner.move_to_pose_with_screw(pre_insert_pose, refine_steps=5)
|
101
|
+
# -------------------------------------------------------------------------- #
|
102
|
+
# Insert
|
103
|
+
# -------------------------------------------------------------------------- #
|
104
|
+
res = planner.move_to_pose_with_screw(insert_pose)
|
105
|
+
|
106
|
+
planner.close()
|
107
|
+
return res
|
108
|
+
|
109
|
+
|
110
|
+
if __name__ == "__main__":
|
111
|
+
main()
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import sapien
|
3
|
+
|
4
|
+
from mani_skill.envs.tasks import PushCubeEnv
|
5
|
+
from mani_skill.examples.motionplanning.xarm6.motionplanner import \
|
6
|
+
XArm6RobotiqMotionPlanningSolver, XArm6PandaGripperMotionPlanningSolver
|
7
|
+
|
8
|
+
def solve(env: PushCubeEnv, seed=None, debug=False, vis=False):
|
9
|
+
env.reset(seed=seed)
|
10
|
+
if env.unwrapped.robot_uids == "xarm6_robotiq":
|
11
|
+
planner_cls = XArm6RobotiqMotionPlanningSolver
|
12
|
+
elif env.unwrapped.robot_uids == "xarm6_pandagripper":
|
13
|
+
planner_cls = XArm6PandaGripperMotionPlanningSolver
|
14
|
+
else:
|
15
|
+
raise ValueError(f"Unsupported robot uid: {env.robot_uid}")
|
16
|
+
planner = planner_cls(
|
17
|
+
env,
|
18
|
+
debug=debug,
|
19
|
+
vis=vis,
|
20
|
+
base_pose=env.unwrapped.agent.robot.pose,
|
21
|
+
visualize_target_grasp_pose=vis,
|
22
|
+
print_env_info=False,
|
23
|
+
)
|
24
|
+
|
25
|
+
FINGER_LENGTH = 0.025
|
26
|
+
env = env.unwrapped
|
27
|
+
planner.close_gripper()
|
28
|
+
reach_pose = sapien.Pose(p=env.obj.pose.sp.p + np.array([-0.05, 0, 0]), q=env.agent.tcp.pose.sp.q)
|
29
|
+
planner.move_to_pose_with_RRTStar(reach_pose)
|
30
|
+
|
31
|
+
# -------------------------------------------------------------------------- #
|
32
|
+
# Move to goal pose
|
33
|
+
# -------------------------------------------------------------------------- #
|
34
|
+
goal_pose = sapien.Pose(p=env.goal_region.pose.sp.p,q=env.agent.tcp.pose.sp.q)
|
35
|
+
res = planner.move_to_pose_with_screw(goal_pose)
|
36
|
+
|
37
|
+
planner.close()
|
38
|
+
return res
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import argparse
|
2
|
+
import gymnasium as gym
|
3
|
+
import numpy as np
|
4
|
+
import sapien
|
5
|
+
from transforms3d.euler import euler2quat
|
6
|
+
|
7
|
+
from mani_skill.envs.tasks import StackCubeEnv
|
8
|
+
from mani_skill.examples.motionplanning.xarm6.motionplanner import \
|
9
|
+
XArm6RobotiqMotionPlanningSolver, XArm6PandaGripperMotionPlanningSolver
|
10
|
+
from mani_skill.examples.motionplanning.panda.utils import (
|
11
|
+
compute_grasp_info_by_obb, get_actor_obb)
|
12
|
+
from mani_skill.utils.wrappers.record import RecordEpisode
|
13
|
+
|
14
|
+
def solve(env: StackCubeEnv, seed=None, debug=False, vis=False):
|
15
|
+
env.reset(seed=seed)
|
16
|
+
assert env.unwrapped.control_mode in [
|
17
|
+
"pd_joint_pos",
|
18
|
+
"pd_joint_pos_vel",
|
19
|
+
], env.unwrapped.control_mode
|
20
|
+
if env.unwrapped.robot_uids == "xarm6_robotiq":
|
21
|
+
planner_cls = XArm6RobotiqMotionPlanningSolver
|
22
|
+
elif env.unwrapped.robot_uids == "xarm6_pandagripper":
|
23
|
+
planner_cls = XArm6PandaGripperMotionPlanningSolver
|
24
|
+
else:
|
25
|
+
raise ValueError(f"Unsupported robot uid: {env.robot_uid}")
|
26
|
+
planner = planner_cls(
|
27
|
+
env,
|
28
|
+
debug=debug,
|
29
|
+
vis=vis,
|
30
|
+
base_pose=env.unwrapped.agent.robot.pose,
|
31
|
+
visualize_target_grasp_pose=vis,
|
32
|
+
print_env_info=False,
|
33
|
+
)
|
34
|
+
FINGER_LENGTH = 0.025
|
35
|
+
env = env.unwrapped
|
36
|
+
obb = get_actor_obb(env.cubeA)
|
37
|
+
|
38
|
+
approaching = np.array([0, 0, -1])
|
39
|
+
target_closing = env.agent.tcp.pose.to_transformation_matrix()[0, :3, 1].numpy()
|
40
|
+
grasp_info = compute_grasp_info_by_obb(
|
41
|
+
obb,
|
42
|
+
approaching=approaching,
|
43
|
+
target_closing=target_closing,
|
44
|
+
depth=FINGER_LENGTH,
|
45
|
+
)
|
46
|
+
closing, center = grasp_info["closing"], grasp_info["center"]
|
47
|
+
grasp_pose = env.agent.build_grasp_pose(approaching, closing, center)
|
48
|
+
|
49
|
+
# Search a valid pose
|
50
|
+
angles = np.arange(0, np.pi * 2 / 3, np.pi / 2)
|
51
|
+
angles = np.repeat(angles, 2)
|
52
|
+
angles[1::2] *= -1
|
53
|
+
for angle in angles:
|
54
|
+
delta_pose = sapien.Pose(q=euler2quat(0, 0, angle))
|
55
|
+
grasp_pose2 = grasp_pose * delta_pose
|
56
|
+
res = planner.move_to_pose_with_RRTStar(grasp_pose2, dry_run=True)
|
57
|
+
if res == -1:
|
58
|
+
continue
|
59
|
+
grasp_pose = grasp_pose2
|
60
|
+
break
|
61
|
+
else:
|
62
|
+
print("Fail to find a valid grasp pose")
|
63
|
+
|
64
|
+
# -------------------------------------------------------------------------- #
|
65
|
+
# Reach
|
66
|
+
# -------------------------------------------------------------------------- #
|
67
|
+
reach_pose = grasp_pose * sapien.Pose([0, 0, -0.05])
|
68
|
+
planner.move_to_pose_with_RRTStar(reach_pose)
|
69
|
+
|
70
|
+
# -------------------------------------------------------------------------- #
|
71
|
+
# Grasp
|
72
|
+
# -------------------------------------------------------------------------- #
|
73
|
+
planner.move_to_pose_with_screw(grasp_pose)
|
74
|
+
planner.close_gripper()
|
75
|
+
|
76
|
+
# -------------------------------------------------------------------------- #
|
77
|
+
# Lift
|
78
|
+
# -------------------------------------------------------------------------- #
|
79
|
+
lift_pose = sapien.Pose([0, 0, 0.1]) * grasp_pose
|
80
|
+
planner.move_to_pose_with_screw(lift_pose)
|
81
|
+
|
82
|
+
# -------------------------------------------------------------------------- #
|
83
|
+
# Stack
|
84
|
+
# -------------------------------------------------------------------------- #
|
85
|
+
goal_pose = env.cubeB.pose * sapien.Pose([0, 0, env.cube_half_size[2] * 2])
|
86
|
+
offset = (goal_pose.p - env.cubeA.pose.p).numpy()[0] # remember that all data in ManiSkill is batched and a torch tensor
|
87
|
+
align_pose = sapien.Pose(lift_pose.p + offset, lift_pose.q)
|
88
|
+
planner.move_to_pose_with_RRTStar(align_pose)
|
89
|
+
|
90
|
+
res = planner.open_gripper()
|
91
|
+
planner.close()
|
92
|
+
return res
|
mani_skill/utils/assets/data.py
CHANGED
@@ -185,6 +185,7 @@ def initialize_data_sources():
|
|
185
185
|
)
|
186
186
|
DATA_SOURCES["xarm6"] = DataSource(
|
187
187
|
source_type="robot",
|
188
|
+
# TODO: update to new url with .convex.stl assets for xarm6 to support motion planning
|
188
189
|
url="https://github.com/haosulab/ManiSkill-XArm6/archive/refs/tags/v0.1.0.zip",
|
189
190
|
target_path="robots/xarm6",
|
190
191
|
)
|
@@ -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
|
{mani_skill_nightly-2025.5.3.1545.dist-info → mani_skill_nightly-2025.5.3.1612.dist-info}/RECORD
RENAMED
@@ -65,7 +65,7 @@ mani_skill/agents/robots/xarm/__init__.py,sha256=6Mhn4vV4f9XxcK493U5W9VE6yGGgydP
|
|
65
65
|
mani_skill/agents/robots/xarm/xarm7_ability.py,sha256=yj7CUBQpbGVUiT22qweJKTniJE0DxdEyyKj329vr0HY,6106
|
66
66
|
mani_skill/agents/robots/xarm6/__init__.py,sha256=0r19OsKmm1ssKB5Rrie8syWQvpXNooVOv6m-iygrdM0,109
|
67
67
|
mani_skill/agents/robots/xarm6/xarm6_nogripper.py,sha256=FPhOpWQw5RPsSHLhZ9JWjYeh25GboO4I5_Hn05Ub84Q,7379
|
68
|
-
mani_skill/agents/robots/xarm6/xarm6_robotiq.py,sha256=
|
68
|
+
mani_skill/agents/robots/xarm6/xarm6_robotiq.py,sha256=80DsYdfcPbqL-o1VjZ_KkTWweEH1a9NS9y4lFHCtMSk,16129
|
69
69
|
mani_skill/assets/maniskill2-scene-2.glb,sha256=C5om9o9r6B-fWoauzNfUm2WV5sh8Nf7AvZRlYo1-IXQ,4737204
|
70
70
|
mani_skill/assets/deformable_manipulation/beaker.glb,sha256=MMaoH6OruVSzO8CKuK2AMyaxA5kjsbbDQXyTVycWsPI,18104
|
71
71
|
mani_skill/assets/deformable_manipulation/bottle.glb,sha256=AHWoATBEBeesfbiYNfSB0O0PWhsH0oa2wUBv79w9AVA,36476
|
@@ -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
|
@@ -602,7 +602,7 @@ mani_skill/envs/tasks/tabletop/pick_cube.py,sha256=dQC3smYUttMLJHXAFMO31vFZKzQ4N
|
|
602
602
|
mani_skill/envs/tasks/tabletop/pick_cube_cfgs.py,sha256=Zz_F3QI_sSqKNDsngp1mzPgkiyewVu47N2iHz522uOg,2166
|
603
603
|
mani_skill/envs/tasks/tabletop/pick_single_ycb.py,sha256=mrqEoOa9UVF34Z5fpsvjcr683diUffsKEjJ9Zh0qfFU,10409
|
604
604
|
mani_skill/envs/tasks/tabletop/place_sphere.py,sha256=J3ReBFK7TyZQlleIFspz7Pl1wqAzaYoveGZfNNL5DVM,10101
|
605
|
-
mani_skill/envs/tasks/tabletop/plug_charger.py,sha256=
|
605
|
+
mani_skill/envs/tasks/tabletop/plug_charger.py,sha256=jgLD2o0eRj-raAEh3ma8OLZ09es6wg8wX1ckWBdr53o,10710
|
606
606
|
mani_skill/envs/tasks/tabletop/poke_cube.py,sha256=KV6mp-Xgm9h4GYUcAUop2AZ4IECTdQKEMRRd9NThyBo,9343
|
607
607
|
mani_skill/envs/tasks/tabletop/pull_cube.py,sha256=txtWuIRFzTKxJtWbrygxVEgOPDvm73WlERXldjlUB-I,5546
|
608
608
|
mani_skill/envs/tasks/tabletop/pull_cube_tool.py,sha256=NaZpdbYYL4zC41GVY__eq4uRIQpVXthzAqe5oSq8YWU,9951
|
@@ -669,6 +669,14 @@ mani_skill/examples/motionplanning/panda/solutions/pull_cube.py,sha256=rQkvCRYjV
|
|
669
669
|
mani_skill/examples/motionplanning/panda/solutions/pull_cube_tool.py,sha256=g6adx921V2SOVYYFlh_gLwV5I0tnz70qCLm81oA6YhA,3609
|
670
670
|
mani_skill/examples/motionplanning/panda/solutions/push_cube.py,sha256=EynyseBJ_njMP74o9gVxqWOOqoC5j1rBc4XQzFug9EQ,1113
|
671
671
|
mani_skill/examples/motionplanning/panda/solutions/stack_cube.py,sha256=QIa280jNOJfJqqgbb5WWEBxErFPE7Mv4-_ZL9TCsRos,3280
|
672
|
+
mani_skill/examples/motionplanning/xarm6/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
673
|
+
mani_skill/examples/motionplanning/xarm6/motionplanner.py,sha256=OcJ2OgY09j3kKl7tFa8GcuGGknF999I_bWZGHZF8lps,4751
|
674
|
+
mani_skill/examples/motionplanning/xarm6/run.py,sha256=yejnUUasyllXZYWpWD9ksvdjgM8o9TwGVfY24kXQxSI,7053
|
675
|
+
mani_skill/examples/motionplanning/xarm6/solutions/__init__.py,sha256=csJg82Tjow5MsYEQEY86ETdPoR59s55KwSg4xaEVyy0,191
|
676
|
+
mani_skill/examples/motionplanning/xarm6/solutions/pick_cube.py,sha256=7gKuTgGrQOuSQr32nZDg07IRk2Dp9jIRCl3TZ1xlPsc,2566
|
677
|
+
mani_skill/examples/motionplanning/xarm6/solutions/plug_charger.py,sha256=myvHjl9Gc2RM2UYb12cOi56C3QbEbeNmvUBLMiHcHp0,3895
|
678
|
+
mani_skill/examples/motionplanning/xarm6/solutions/push_cube.py,sha256=iiZHwvOGGAaxPkzE_sAN6WdTYfcxEMVx0Da3e2rzL48,1419
|
679
|
+
mani_skill/examples/motionplanning/xarm6/solutions/stack_cube.py,sha256=zarkqZ2MSfBu-Uv7DNNiRmqyv_JLPiIWcpONGyfbf0Y,3595
|
672
680
|
mani_skill/examples/teleoperation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
673
681
|
mani_skill/examples/teleoperation/interactive_panda.py,sha256=NsGy_ghtXl3HPbwLjKINkizOXqX_rMr30lUfscmhyQ4,10423
|
674
682
|
mani_skill/render/__init__.py,sha256=Uy6h1bzammUO8QVPVCDcuCuhnuN3e5votaho45drAGw,118
|
@@ -698,7 +706,7 @@ mani_skill/utils/registration.py,sha256=u8ftfGvQP4qzlKNqLQjGi3cRF_-h6Rz-28xbLkW_
|
|
698
706
|
mani_skill/utils/sapien_utils.py,sha256=QMV0jRZO51KzIMB5CVW_Ne-4fPw0-mqM4a3yhNZaMYo,16430
|
699
707
|
mani_skill/utils/assets/README.md,sha256=5kkmsIiV64ySEGO34HaAlpjXTyrGs1KTV5WnofK46G0,70
|
700
708
|
mani_skill/utils/assets/__init__.py,sha256=gQVKwAczcImTXArSltBWKlSUUuguO12sZYO3Jh5KLso,159
|
701
|
-
mani_skill/utils/assets/data.py,sha256=
|
709
|
+
mani_skill/utils/assets/data.py,sha256=7TsxGBVL05Cg6TLjzx9Nv93uzLby1TaatHs-m15oHew,8686
|
702
710
|
mani_skill/utils/building/__init__.py,sha256=quCI5WYGhzGLMVg_NDyYv2G_MxRTBL8R6XD4a6iY8qc,218
|
703
711
|
mani_skill/utils/building/_mjcf_loader.py,sha256=SqzSoRootFvItHrzwrDuSHScePxbaPqWb7262M7HzIU,37011
|
704
712
|
mani_skill/utils/building/actor_builder.py,sha256=sTnpoThOqWegD-87Q7GyaVvB40fiWUwPOQpYkth-sis,14956
|
@@ -776,8 +784,8 @@ mani_skill/utils/scene_builder/table/assets/Dining_Table_204_1.glb,sha256=IleHi3
|
|
776
784
|
mani_skill/utils/scene_builder/table/assets/table.glb,sha256=yw69itZDjBFg8JXZAr9VQV-dZD-MaZChhqBSJR_nlRo,3891588
|
777
785
|
mani_skill/utils/structs/README.md,sha256=qnYKimp_ZkgNcduURrYQxVTimNmq_usDMKoQ8VtMdCs,286
|
778
786
|
mani_skill/utils/structs/__init__.py,sha256=BItR3Xe0z6xCrMHAEaH0AAAVyeonsQ3q-DJUyRUibAA,524
|
779
|
-
mani_skill/utils/structs/actor.py,sha256=
|
780
|
-
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
|
781
789
|
mani_skill/utils/structs/articulation_joint.py,sha256=TY6joQ0RpnVlHbQHdtx_QQYqTWgFHLiZ642SSWZUuTw,11736
|
782
790
|
mani_skill/utils/structs/base.py,sha256=meGQK5Y4KtHKLnp9VeOZS2gtwg9tE55whuEeqOguBaI,19465
|
783
791
|
mani_skill/utils/structs/decorators.py,sha256=Lv6wQ989dOnreo2tB-qopDnkeBp_jsn1pmfUR-OY8VQ,535
|
@@ -802,8 +810,8 @@ mani_skill/vector/wrappers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
802
810
|
mani_skill/vector/wrappers/gymnasium.py,sha256=v1MDPIrVACBKCulrpdXBK2jDZQI7LKYFZgGgaCC5avY,7408
|
803
811
|
mani_skill/vector/wrappers/sb3.py,sha256=SlXdiEPqcNHYMhJCzA29kBU6zK7DKTe1nc0L6Z3QQtY,4722
|
804
812
|
mani_skill/viewer/__init__.py,sha256=srvDBsk4LQU75K2VIttrhiQ68p_ro7PSDqQRls2PY5c,1722
|
805
|
-
mani_skill_nightly-2025.5.3.
|
806
|
-
mani_skill_nightly-2025.5.3.
|
807
|
-
mani_skill_nightly-2025.5.3.
|
808
|
-
mani_skill_nightly-2025.5.3.
|
809
|
-
mani_skill_nightly-2025.5.3.
|
813
|
+
mani_skill_nightly-2025.5.3.1612.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
814
|
+
mani_skill_nightly-2025.5.3.1612.dist-info/METADATA,sha256=4nixw1uljNAUYQ0gC6Th21pC-pStemPbqA4SlftUBdU,9291
|
815
|
+
mani_skill_nightly-2025.5.3.1612.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
816
|
+
mani_skill_nightly-2025.5.3.1612.dist-info/top_level.txt,sha256=bkBgOVl_MZMoQx2aRFsSFEYlZLxjWlip5vtJ39FB3jA,11
|
817
|
+
mani_skill_nightly-2025.5.3.1612.dist-info/RECORD,,
|
{mani_skill_nightly-2025.5.3.1545.dist-info → mani_skill_nightly-2025.5.3.1612.dist-info}/LICENSE
RENAMED
File without changes
|
{mani_skill_nightly-2025.5.3.1545.dist-info → mani_skill_nightly-2025.5.3.1612.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|