mani-skill-nightly 2025.5.3.813__py3-none-any.whl → 2025.5.3.1548__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.
@@ -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
@@ -183,28 +183,29 @@ class PlugChargerEnv(BaseEnv):
183
183
  self.scene_builder.initialize(env_idx)
184
184
 
185
185
  # Initialize agent
186
- qpos = torch.tensor(
187
- [
188
- 0.0,
189
- np.pi / 8,
190
- 0,
191
- -np.pi * 5 / 8,
192
- 0,
193
- np.pi * 3 / 4,
194
- np.pi / 4,
195
- 0.04,
196
- 0.04,
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
- + qpos
204
- )
205
- qpos[:, -2:] = 0.04
206
- self.agent.robot.set_qpos(qpos)
207
- self.agent.robot.set_pose(sapien.Pose([-0.615, 0, 0]))
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,4 @@
1
+ from .pick_cube import solve as solvePickCube
2
+ from .push_cube import solve as solvePushCube
3
+ from .stack_cube import solve as solveStackCube
4
+ from .plug_charger import solve as solvePlugCharger
@@ -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
@@ -557,6 +557,8 @@ def main(args: Args):
557
557
  )
558
558
 
559
559
  else:
560
+ env_kwargs["num_envs"] = 1
561
+ ori_env_kwargs["num_envs"] = 1
560
562
  if args.num_envs > 1:
561
563
  pool = mp.Pool(args.num_envs)
562
564
  proc_args = [
@@ -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
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mani-skill-nightly
3
- Version: 2025.5.3.813
3
+ Version: 2025.5.3.1548
4
4
  Summary: ManiSkill3: A Unified Benchmark for Generalizable Manipulation Skills
5
5
  Home-page: https://github.com/haosulab/ManiSkill
6
6
  Author: ManiSkill contributors
@@ -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=FIc_BvV7x5Fs9GsE5-m88NaSjPitnDYIGU2ZJbqE-m4,15651
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
@@ -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=0g-rkNf-oo2ovttlcQ58jqUq6So4SKvYMTHORZUOi_0,10571
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
@@ -681,7 +689,7 @@ mani_skill/sensors/depth_camera.py,sha256=KCT7DMqQacVag_24MjkKAml87T6FtDqNS0TJFf
681
689
  mani_skill/trajectory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
682
690
  mani_skill/trajectory/dataset.py,sha256=nrG3jkhdzRqAdjxC_c8Z4FxpkvW3A9XPvUp9-Ux_u38,6351
683
691
  mani_skill/trajectory/merge_trajectory.py,sha256=zsjRMTsiIirZGIV4KrtYOM2-zoOAzd7ObZEdWGJzZbE,3685
684
- mani_skill/trajectory/replay_trajectory.py,sha256=cnqQX9ThXhnTSGyzp4CrQRLESXH9UgDLe-7iJfTm67s,27000
692
+ mani_skill/trajectory/replay_trajectory.py,sha256=AtmsIV4Oj_vh6MDbHV5Kyrlv7J6mXSHvAWwjuFBVMZo,27074
685
693
  mani_skill/trajectory/utils/__init__.py,sha256=Nchv09IpXv0FOgpf7Ng1Ekus6ZfAh3kI0KJs-79QOig,1515
686
694
  mani_skill/trajectory/utils/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
687
695
  mani_skill/trajectory/utils/actions/conversion.py,sha256=x88C64ke44gB-HEbqq_gSRFv34L7irSwT_wYttkQUn8,12922
@@ -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=YRobBeCxdf23kJxMac9J-dvvJoLSck8mQTbPZGeIAi4,8591
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
@@ -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.813.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
806
- mani_skill_nightly-2025.5.3.813.dist-info/METADATA,sha256=J-PnBnL_k7V9P90nfNB_WDfe4KTaoIAiOP2NQ7US2hk,9290
807
- mani_skill_nightly-2025.5.3.813.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
808
- mani_skill_nightly-2025.5.3.813.dist-info/top_level.txt,sha256=bkBgOVl_MZMoQx2aRFsSFEYlZLxjWlip5vtJ39FB3jA,11
809
- mani_skill_nightly-2025.5.3.813.dist-info/RECORD,,
813
+ mani_skill_nightly-2025.5.3.1548.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
814
+ mani_skill_nightly-2025.5.3.1548.dist-info/METADATA,sha256=MFsr_RXRUCYN__3kPl9e6aAwQ8wkLN_Cwe4dC4thaB4,9291
815
+ mani_skill_nightly-2025.5.3.1548.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
816
+ mani_skill_nightly-2025.5.3.1548.dist-info/top_level.txt,sha256=bkBgOVl_MZMoQx2aRFsSFEYlZLxjWlip5vtJ39FB3jA,11
817
+ mani_skill_nightly-2025.5.3.1548.dist-info/RECORD,,