-
Notifications
You must be signed in to change notification settings - Fork 389
Add Stack Pyramid task and motionplanning solution #683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
chenyenru
wants to merge
20
commits into
haosulab:main
Choose a base branch
from
chenyenru:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
be0abbd
[Feature] Add Stack Pyramid task environment
chenyenru 0cb1abc
[Feature] Add panda motionplanning solution for Stack Pyramid for Tra…
chenyenru b4086b6
[BugFix] Add StackPyramid demo video for StackPyramid task card
chenyenru 738cd9e
[Feature] Add example to run Diffusion Policy on StackPyramid-v1 in e…
chenyenru e52e2bf
[BugFix] Corrected file name for StackPyramid's replay trajectory exa…
chenyenru 2903e8c
[BugFix] Rename Stack Pyramid Solution File
chenyenru 40679c8
[BugFix] StackPyramid: Removed unused variables, deleted repeated lin…
chenyenru bb5c2d5
[BugFix] Set different initial pose for the 3 Cubes to avoid collision
chenyenru ef6d348
[Feature] Added PickAndPlace task and build container with custom siz…
chenyenru 1838abe
remove unnecessary build_ycb_object from pick_and_place.py
chenyenru d2799e4
removed unnecessary distance variable from pick_and_place
chenyenru b22bf94
Added task description for PickAndPlace-v1 and StackPyramid-v1
chenyenru ab0cf50
Resolve merge conflict and fix get obs extra bug for PickAndPlace
chenyenru 9d38041
[Feature] Add Stack Pyramid task environment
chenyenru 2f6c20b
[Feature] Add panda motionplanning solution for Stack Pyramid for Tra…
chenyenru 8617720
[Feature] Add example to run Diffusion Policy on StackPyramid-v1 in e…
chenyenru dff5617
[Feature] Add Stack Pyramid task environment
chenyenru fac3614
[Feature] Added PickAndPlace task and build container with custom siz…
chenyenru 541080c
[BugFix] Change container grid body type from static to kinematic
chenyenru 32aecb4
[BugFix] Add StackPyramid and PickAndPlace to MP Solution Dictionary
chenyenru File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| ### Example scripts for training Diffusion Policy that have some results ### | ||
|
|
||
| # Learning from motion planning generated demonstrations | ||
|
|
||
| # PushCube-v1 | ||
| python -m mani_skill.trajectory.replay_trajectory \ | ||
| --traj-path ~/.maniskill/demos/PushCube-v1/motionplanning/trajectory.h5 \ | ||
| --use-first-env-state -c pd_ee_delta_pos -o state \ | ||
| --save-traj --num-procs 10 -b cpu | ||
|
|
||
| python train.py --env-id PushCube-v1 \ | ||
| --demo-path ~/.maniskill/demos/PushCube-v1/motionplanning/trajectory.state.pd_ee_delta_pos.cpu.h5 \ | ||
| --control-mode "pd_ee_delta_pos" --sim-backend "cpu" --num-demos 100 --max_episode_steps 100 \ | ||
| --total_iters 30000 | ||
|
|
||
| # PickCube-v1 | ||
| python -m mani_skill.trajectory.replay_trajectory \ | ||
| --traj-path ~/.maniskill/demos/PickCube-v1/motionplanning/trajectory.h5 \ | ||
| --use-first-env-state -c pd_ee_delta_pos -o state \ | ||
| --save-traj --num-procs 10 -b cpu | ||
|
|
||
| python train.py --env-id PickCube-v1 \ | ||
| --demo-path ~/.maniskill/demos/PickCube-v1/motionplanning/trajectory.state.pd_ee_delta_pos.cpu.h5 \ | ||
| --control-mode "pd_ee_delta_pos" --sim-backend "cpu" --num-demos 100 --max_episode_steps 100 \ | ||
| --total_iters 30000 | ||
|
|
||
| # StackCube-v1 | ||
| python -m mani_skill.trajectory.replay_trajectory \ | ||
| --traj-path ~/.maniskill/demos/StackCube-v1/motionplanning/trajectory.h5 \ | ||
| --use-first-env-state -c pd_ee_delta_pos -o state \ | ||
| --save-traj --num-procs 10 -b cpu | ||
|
|
||
| python train.py --env-id StackCube-v1 \ | ||
| --demo-path ~/.maniskill/demos/StackCube-v1/motionplanning/trajectory.state.pd_ee_delta_pos.cpu.h5 \ | ||
| --control-mode "pd_ee_delta_pos" --sim-backend "cpu" --num-demos 100 --max_episode_steps 200 \ | ||
| --total_iters 30000 | ||
|
|
||
| # PegInsertionSide-v1 | ||
| python -m mani_skill.trajectory.replay_trajectory \ | ||
| --traj-path ~/.maniskill/demos/PegInsertionSide-v1/motionplanning/trajectory.h5 \ | ||
| --use-first-env-state -c pd_ee_delta_pose -o state \ | ||
| --save-traj --num-procs 10 -b cpu | ||
|
|
||
| python train.py --env-id PegInsertionSide-v1 \ | ||
| --demo-path ~/.maniskill/demos/PegInsertionSide-v1/motionplanning/trajectory.state.pd_ee_delta_pose.cpu.h5 \ | ||
| --control-mode "pd_ee_delta_pose" --sim-backend "cpu" --num-demos 100 --max_episode_steps 300 \ | ||
| --total_iters 300000 | ||
|
|
||
| # StackPyramid-v1 | ||
| stack_pyramid_traj_name="stack_pyramid_trajectory" | ||
| python -m mani_skill.examples.motionplanning.panda.run -e "StackPyramid-v1" \ | ||
| --num-procs 20 -n 100 --reward-mode="sparse" \ | ||
| --sim-backend cpu --only-count-success \ | ||
| --traj-name $stack_pyramid_traj_name | ||
|
|
||
| python -m mani_skill.trajectory.replay_trajectory -b cpu \ | ||
| --traj-path ./demos/StackPyramid-v1/motionplanning/$stack_pyramid_traj_name.h5 \ | ||
| --use-first-env-state -c pd_joint_delta_pos -o state \ | ||
| --save-traj --num-procs 20 | ||
|
|
||
| python train.py --env-id StackPyramid-v1 \ | ||
| --demo-path ./demos/StackPyramid-v1/motionplanning/$stack_pyramid_traj_name.state.pd_joint_delta_pos.cpu.h5 \ | ||
| --control-mode "pd_joint_delta_pos" --sim-backend "cpu" --num-demos 100 \ | ||
| --max_episode_steps 300 --total_iters 30000 --num-eval-envs 20 | ||
|
|
||
| # PickAndPlace-v1 | ||
| pick_and_place_traj_name="pick_and_place_trajectory" | ||
| python -m mani_skill.examples.motionplanning.panda.run -e "PickAndPlace-v1" \ | ||
| --num-procs 20 -n 100 --reward-mode="sparse" \ | ||
| --sim-backend cpu --only-count-success \ | ||
| --traj-name $pick_and_place_traj_name | ||
|
|
||
| python -m mani_skill.trajectory.replay_trajectory -b cpu \ | ||
| --traj-path ./demos/PickAndPlace-v1/motionplanning/$pick_and_place_traj_name.h5 \ | ||
| --use-first-env-state -c pd_joint_delta_pos -o state \ | ||
| --save-traj --num-procs 20 | ||
|
|
||
| python train.py --env-id PickAndPlace-v1 \ | ||
| --demo-path ./demos/PickAndPlace-v1/motionplanning/$pick_and_place_traj_name.state.pd_joint_delta_pos.cpu.h5 \ | ||
| --control-mode "pd_joint_delta_pos" --sim-backend "cpu" --num-demos 100 \ | ||
| --max_episode_steps 300 --total_iters 30000 --num-eval-envs 20 | ||
|
|
||
|
|
||
| python train.py --env-id PickAndPlace-v1 \ | ||
| --demo-path ../../../demos/PickAndPlace-v1/motionplanning/20241209_162523.state.pd_joint_delta_pos.cpu.h5 \ | ||
| --control-mode "pd_joint_delta_pos" --sim-backend "cpu" --num-demos 100 --max_episode_steps 800 \ | ||
| --total_iters 30000 --num-eval-envs 20 |
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,7 +16,7 @@ | |
| @register_agent() | ||
| class Panda(BaseAgent): | ||
| uid = "panda" | ||
| urdf_path = f"{PACKAGE_ASSET_DIR}/robots/panda/panda_v2.urdf" | ||
| urdf_path = f"{PACKAGE_ASSET_DIR}/robots/panda/panda_v3.urdf" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this changed? |
||
| urdf_config = dict( | ||
| _materials=dict( | ||
| gripper=dict(static_friction=2.0, dynamic_friction=2.0, restitution=0.0) | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| from typing import Any, Dict, Union | ||
|
|
||
| import numpy as np | ||
| import sapien | ||
| import torch | ||
|
|
||
| from mani_skill import logger | ||
| import mani_skill.envs.utils.randomization as randomization | ||
| from mani_skill.agents.robots.panda.panda_wristcam import PandaWristCam | ||
| from mani_skill.envs.sapien_env import BaseEnv | ||
| from mani_skill.sensors.camera import CameraConfig | ||
| from mani_skill.utils import sapien_utils | ||
| from mani_skill.utils.building import actors | ||
| from mani_skill.utils.registration import register_env | ||
| from mani_skill.utils.scene_builder.table import TableSceneBuilder | ||
| from mani_skill.utils.structs.actor import Actor | ||
| from mani_skill.utils.structs.pose import Pose | ||
| from mani_skill.utils.structs.types import SimConfig | ||
| from mani_skill.utils.building.actors.common import build_container_grid | ||
|
|
||
|
|
||
| @register_env("PickAndPlace-v1", max_episode_steps=500) | ||
| class PickAndPlaceEnv(BaseEnv): | ||
| """ | ||
| **Task Description:** | ||
| - Pick and place the four cubes into distinct container cells. | ||
| - The red cube must be placed on the upper left cell. | ||
| - The green cube must be placed on the upper right cell. | ||
| - The blue cube must be placed on the lower left cell. | ||
| - The yellow cube must be placed on the lower right cell. | ||
|
|
||
| **Randomizations:** | ||
| - The four cubes' positions are randomized in the xy range of x in [0.05, 0.09] and y in [-0.15, -0.1]. | ||
| - The z-coordinate of the cubes is fixed at 0.04 to place them on the table surface. | ||
| - The cubes' orientations are randomized. | ||
| - Even though randomized, the cubes are ensured to have a minimum Euclidean distance of 0.06 from each other to avoid overlaps. | ||
|
|
||
| **Success Conditions:** | ||
| - Each cube is placed into its corresponding cell. | ||
| - Robot is static within the threshold of 0.2 | ||
|
|
||
| **Goal Specification:** | ||
| - 3D goal position (also visualized in human renders) | ||
|
|
||
| _sample_video_link = "https://github.com/haosulab/ManiSkill/raw/main/figures/environment_demos/PickAndPlace-v1_rt.mp4" | ||
| """ | ||
| SUPPORTED_ROBOTS = ["panda_wristcam"] | ||
| SUPPORTED_REWARD_MODES = ["none", "sparse"] | ||
| agent: Union[PandaWristCam] | ||
| cube_half_size = 0.02 | ||
| goal_thresh = 0.05 | ||
|
|
||
| def __init__(self, *args, robot_uids="panda", robot_init_qpos_noise=0.02, **kwargs): | ||
| self.robot_init_qpos_noise = robot_init_qpos_noise | ||
| super().__init__(*args, robot_uids=robot_uids, **kwargs) | ||
|
|
||
| @property | ||
| def _default_sensor_configs(self): | ||
| pose = sapien_utils.look_at(eye=[0.3, 0, 0.6], target=[-0.1, 0, 0.1]) | ||
| return [CameraConfig("base_camera", pose, 128, 128, np.pi / 2, 0.01, 100)] | ||
|
|
||
| @property | ||
| def _default_human_render_camera_configs(self): | ||
| pose = sapien_utils.look_at([0.6, 0.7, 0.6], [0.0, 0.0, 0.35]) | ||
| return CameraConfig("render_camera", pose, 512, 512, 1, 0.01, 100) | ||
|
|
||
| def _load_agent(self, options: dict): | ||
| super()._load_agent(options, sapien.Pose(p=[-0.615, 0, 0])) | ||
|
|
||
| def _load_scene(self, options: dict): | ||
| self.table_scene = TableSceneBuilder( | ||
| self, robot_init_qpos_noise=self.robot_init_qpos_noise | ||
| ) | ||
| self.table_scene.build() | ||
| self.container_grid, self.goal_sites = build_container_grid( | ||
| self.scene, | ||
| initial_pose=sapien.Pose(p=[0.0, 0.2, 0.04], q=[1, 0, 0, 0]), | ||
| size=0.25, | ||
| height=0.05, | ||
| thickness=0.01, | ||
| color=(0.8, 0.6, 0.4), | ||
| name="container_grid", | ||
| n=2, | ||
| m=2, | ||
| body_type="kinematic", | ||
| ) | ||
| self.red_cube = actors.build_cube( | ||
| self.scene, | ||
| half_size=self.cube_half_size, | ||
| color=[1, 0, 0, 1], | ||
| name="red_cube", | ||
| initial_pose=sapien.Pose(p=[0,0,0.1]) | ||
| ) | ||
|
|
||
| self.green_cube = actors.build_cube( | ||
| self.scene, | ||
| half_size=self.cube_half_size, | ||
| color=[0, 1, 0, 1], | ||
| name="green_cube", | ||
| initial_pose=sapien.Pose(p=[0,0,0.5]) | ||
| ) | ||
|
|
||
| self.blue_cube = actors.build_cube( | ||
| self.scene, | ||
| half_size=self.cube_half_size, | ||
| color=[0, 0, 1, 1], | ||
| name="blue_cube", | ||
| initial_pose=sapien.Pose(p=[0,0,1.0]) | ||
| ) | ||
|
|
||
| self.yellow_cube = actors.build_cube( | ||
| self.scene, | ||
| half_size=self.cube_half_size, | ||
| color=[1, 1, 0, 1], | ||
| name="yellow_cube", | ||
| initial_pose=sapien.Pose(p=[0,0,1.5]) | ||
| ) | ||
|
|
||
| self.cubes = [self.red_cube, self.green_cube, self.blue_cube, self.yellow_cube] | ||
| self._hidden_objects.extend(self.goal_sites) | ||
|
|
||
| def _initialize_episode(self, env_idx: torch.Tensor, options: dict): | ||
| with torch.device(self.device): | ||
| env_count = len(env_idx) | ||
| self.table_scene.initialize(env_idx) | ||
|
|
||
| # Initialize container grid | ||
| container_pose = sapien.Pose(p=[0.0, 0.2, 0.04], q=[1, 0, 0, 0]) | ||
| self.container_grid.set_pose(container_pose) | ||
|
|
||
| region = [[0.05, -0.15], [0.09, -0.1]] | ||
| radius = torch.linalg.norm(torch.tensor([0.02, 0.02])) + 0.001 | ||
| min_distance = 0.06 | ||
|
|
||
| # Randomize cube positions | ||
| for i, cube in enumerate(self.cubes): | ||
| while True: | ||
| xyz = torch.zeros((env_count, 3)) | ||
| sampler = randomization.UniformPlacementSampler( | ||
| bounds=region, batch_size=env_count, device=self.device | ||
| ) | ||
| cube_xy = torch.rand((env_count, 2)) * 0.4 - 0.4 + sampler.sample(radius, 100) | ||
| xyz[:, :2] = cube_xy | ||
| xyz[:, 2] = 0.04 | ||
| qs = randomization.random_quaternions( | ||
| env_count, | ||
| lock_x=True, | ||
| lock_y=True, | ||
| lock_z=False, | ||
| ) | ||
| cube.set_pose(Pose.create_from_pq(p=xyz, q=qs)) | ||
|
|
||
| overlap = False | ||
| for j in range(i): | ||
| other_cube = self.cubes[j] | ||
| other_xyz = other_cube.pose.p | ||
| distance = torch.linalg.norm(xyz - other_xyz, axis=1) | ||
| if torch.any(distance < min_distance): | ||
| overlap = True | ||
| break | ||
|
|
||
| if not overlap: | ||
| break | ||
|
|
||
| def _get_obs_extra(self, info: Dict): | ||
| # in reality some people hack is_grasped into observations by checking if the gripper can close fully or not | ||
| obs = {"tcp_pose": self.agent.tcp.pose.raw_pose} | ||
| for goal_site in self.goal_sites: | ||
| obs[f"{goal_site.name}_pose"] = goal_site.pose.p | ||
|
|
||
| for i, obj in enumerate(self.cubes): | ||
| obs[f"{obj.name}_pose"] = obj.pose.raw_pose | ||
| if "state" in self.obs_mode: | ||
| pass | ||
| obs[f"{obj.name}_to_goal_pos"] = self.goal_sites[i].pose.p - obj.pose.p | ||
| obs[f"tcp_to_{obj.name}_pos"] = obj.pose.p - self.agent.tcp.pose.p | ||
|
|
||
| return obs | ||
|
|
||
|
|
||
| def evaluate(self): | ||
| results = dict() | ||
| all_placed = torch.tensor(True, device=self.device) | ||
| any_grasped = torch.tensor(False, device=self.device) | ||
| # only count success after all objects grasped and placed | ||
|
|
||
| for i, goal_site in enumerate(self.goal_sites): | ||
| obj = self.cubes[i] | ||
| obj_name = obj.name | ||
|
|
||
| distance_to_goal = torch.linalg.norm(goal_site.pose.p - obj.pose.p, axis=1) | ||
| is_placed = ( | ||
| distance_to_goal | ||
| <= self.goal_thresh | ||
| ) | ||
| is_grasped = self.agent.is_grasping(obj) | ||
|
|
||
| results[f"{obj_name}_distance_to_goal"] = distance_to_goal | ||
| results[f"is_{obj_name}_placed"] = is_placed | ||
| results[f"is_{obj_name}_grasped"] = is_grasped | ||
|
|
||
| all_placed = torch.logical_and(all_placed, is_placed) | ||
| any_grasped = torch.logical_or(any_grasped, is_grasped) | ||
|
|
||
|
|
||
| # Success is defined as all cubes being placed and none being grasped | ||
| results["success"] = torch.logical_and(all_placed, torch.logical_not(any_grasped)) | ||
|
|
||
| # Reward for the robot being static | ||
| results["is_robot_static"] = self.agent.is_static(0.2) | ||
|
|
||
| return results |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
repeated line