Spaces:
Sleeping
Sleeping
| # <-- this must come first, before any mujoco / gym imports | |
| # import os | |
| # os.environ["MUJOCO_GL"] = "egl" | |
| import numpy as np | |
| import gymnasium as gym | |
| import gymnasium_robotics | |
| import mujoco | |
| class CustomFetchWrapper(gym.Wrapper): | |
| def __init__(self, env, block_xy=None, goal_xyz=None, object=True): | |
| super().__init__(env) | |
| self.u = env.unwrapped # MujocoFetchPickAndPlaceEnv | |
| # stash your fixed coords (or None to randomize) | |
| self.default_block_xy = (np.array(block_xy, dtype=float) | |
| if block_xy is not None else None) | |
| self.default_goal_xyz = (np.array(goal_xyz, dtype=float) | |
| if goal_xyz is not None else None) | |
| self.object = object | |
| def reset(self, *args, **kwargs): | |
| # 1) do the normal reset — gets you a random goal in obs | |
| obs, info = super().reset(*args, **kwargs) | |
| u = self.unwrapped | |
| model = u.model | |
| data = u.data | |
| utils = u._utils | |
| rng = u.np_random | |
| # 2) reset the robot slides to your home pose | |
| for name, val in zip( | |
| ["robot0:slide0","robot0:slide1","robot0:slide2"], | |
| [0.405, 0.48, 0.0], | |
| ): | |
| utils.set_joint_qpos(model, data, name, val) | |
| # pull out the actual goal so we can avoid it | |
| goal_pos = obs["desired_goal"][:2].copy() | |
| if (self.object==True): | |
| # 3) pick block position | |
| if self.default_block_xy is None: | |
| home_xy = u.initial_gripper_xpos[:2] | |
| obj_range = u.obj_range | |
| min_dist = u.distance_threshold | |
| while True: | |
| offset = rng.uniform(-obj_range, obj_range, size=2) | |
| # 3a) must be outside the “too-close to gripper” zone | |
| if np.linalg.norm(offset) < min_dist: | |
| continue | |
| candidate_xy = home_xy + offset | |
| # 3b) must be outside the “too-close to goal” zone | |
| if np.linalg.norm(candidate_xy - goal_pos) < min_dist: | |
| continue | |
| # if we get here, both checks passed | |
| break | |
| block_xy = candidate_xy | |
| else: | |
| block_xy = self.default_block_xy | |
| # place the block | |
| blk_qpos = utils.get_joint_qpos(model, data, "object0:joint") | |
| blk_qpos[0:2] = block_xy | |
| blk_qpos[2] = 0.42 # table height | |
| utils.set_joint_qpos(model, data, "object0:joint", blk_qpos) | |
| # 4) pick goal position | |
| if self.default_goal_xyz is not None: | |
| new_goal = self.default_goal_xyz | |
| # override the goal both in the env and in the MuJoCo site | |
| u.goal = new_goal | |
| sid = mujoco.mj_name2id(model, | |
| mujoco.mjtObj.mjOBJ_SITE, | |
| "target0") | |
| data.site_xpos[sid] = new_goal | |
| # 5) forward‐kinematics + fresh obs | |
| u._mujoco.mj_forward(model, data) | |
| obs = u._get_obs() | |
| return obs, info | |
| def create_env(render_mode=None, block_xy=None, goal_xyz=None, environment = "FetchPickAndPlace-v3"): | |
| gym.register_envs(gymnasium_robotics) | |
| if(environment == "FetchReach-v3"): | |
| object = False | |
| else: | |
| object = True | |
| base_env = gym.make(environment, render_mode=render_mode) | |
| u = base_env.unwrapped | |
| # 1) compute table center in world coords | |
| # – X,Y: same as the gripper’s initial XY (over table center) | |
| # – Z: the table‐top height the wrapper uses (0.42 m) | |
| center_xy = u.initial_gripper_xpos[:2] # e.g. [1.366, 0.750] | |
| table_z = 0.42 # match blk_qpos[2] in your wrapper | |
| table_center = np.array([*center_xy, table_z]) | |
| # 2) turn your “relative” block_xy into an absolute XY | |
| if block_xy is not None: | |
| rel = np.array(block_xy, dtype=float) | |
| abs_block_xy = center_xy + rel | |
| else: | |
| abs_block_xy = None | |
| # 3) turn your “relative” goal_xyz into an absolute XYZ | |
| if goal_xyz is not None: | |
| rel = np.array(goal_xyz, dtype=float) | |
| abs_goal_xyz = table_center + rel | |
| else: | |
| abs_goal_xyz = None | |
| # 4) build the wrapped env with those absolutes | |
| env = CustomFetchWrapper( | |
| base_env, | |
| block_xy=abs_block_xy, | |
| goal_xyz=abs_goal_xyz, | |
| object=object | |
| ) | |
| return env |