diff --git a/README.md b/README.md index 0e8e135c..d4193a28 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ pip install -e panda-gym import gymnasium as gym import panda_gym -env = gym.make('PandaReach-v3', render=True) +env = gym.make('PandaReach-v3', render_mode="human") observation, info = env.reset() diff --git a/docs/_static/notebook/PickAndPlace.ipynb b/docs/_static/notebook/PickAndPlace.ipynb index ded81a19..117e29b7 100644 --- a/docs/_static/notebook/PickAndPlace.ipynb +++ b/docs/_static/notebook/PickAndPlace.ipynb @@ -48,18 +48,18 @@ "import gymnasium as gym\n", "import panda_gym\n", "\n", - "env = gym.make(\"PandaPickAndPlace-v3\", render=True)\n", + "env = gym.make(\"PandaPickAndPlace-v3\", render_mode=\"rgb_array\")\n", "observation, info = env.reset()\n", "\n", - "images = [env.render(\"rgb_array\")]\n", + "images = [env.render()]\n", "for _ in range(1000):\n", " action = env.action_space.sample()\n", " observation, reward, terminated, truncated, info = env.step(action)\n", - " images.append(env.render(\"rgb_array\"))\n", + " images.append(env.render())\n", "\n", " if terminated or truncated:\n", " observation, info = env.reset()\n", - " images.append(env.render(\"rgb_array\"))\n", + " images.append(env.render())\n", "\n", "env.close()" ] @@ -107,8 +107,19 @@ } ], "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "name": "python", + "version": "3.9.6 (default, Sep 26 2022, 11:37:49) \n[Clang 14.0.0 (clang-1400.0.29.202)]" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } } }, "nbformat": 4, diff --git a/docs/conf.py b/docs/conf.py index 2cb460f9..0e317b97 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ author = "Quentin Gallouédec" # The full version, including alpha/beta/rc tags -release = "v3.0.0" +release = "v3.0.1" # -- General configuration --------------------------------------------------- diff --git a/docs/custom/custom_env.rst b/docs/custom/custom_env.rst index f737fb4b..71a5bb45 100644 --- a/docs/custom/custom_env.rst +++ b/docs/custom/custom_env.rst @@ -17,8 +17,8 @@ Then, you have to inherit from the :py:class:`RobotTaskEnv` section. \ No newline at end of file diff --git a/docs/custom/custom_task.rst b/docs/custom/custom_task.rst index ba06e059..ecc27404 100644 --- a/docs/custom/custom_task.rst +++ b/docs/custom/custom_task.rst @@ -74,7 +74,7 @@ The task is ready. To test it, execute the following code. from panda_gym.pybullet import PyBullet - sim = PyBullet(render=True) + sim = PyBullet(render_mode="human") task = MyTask(sim) task.reset() diff --git a/docs/guide/quick_start.rst b/docs/guide/quick_start.rst index fc16a0e7..26e93dff 100644 --- a/docs/guide/quick_start.rst +++ b/docs/guide/quick_start.rst @@ -10,18 +10,16 @@ Once ``panda-gym`` installed, you can start the "Reach" task by executing the fo import gymnasium as gym import panda_gym - env = gym.make('PandaReach-v3', render=True) + env = gym.make('PandaReach-v3', render_mode="human") observation, info = env.reset() for _ in range(1000): action = env.action_space.sample() # random action observation, reward, terminated, truncated, info = env.step(action) - env.render() # wait the right amount of time to make the rendering real-time if terminated or truncated: observation, info = env.reset() - env.render() # wait the right amount of time to make the rendering real-time Obviously, since the chosen actions are random, you will not see any learning. To access the section dedicated to the learning of the tasks, refer to the section :ref:`Train with stable-baselines3`. diff --git a/docs/usage/manual_control.rst b/docs/usage/manual_control.rst index 1e117bb6..19a3c64b 100644 --- a/docs/usage/manual_control.rst +++ b/docs/usage/manual_control.rst @@ -10,7 +10,7 @@ It is possible to manually control the robot, giving it deterministic actions, d import gymnasium as gym import panda_gym - env = gym.make("PandaReach-v3", render=True) + env = gym.make("PandaReach-v3", render_mode="human") observation, info = env.reset() for _ in range(1000): diff --git a/docs/usage/save_restore_state.rst b/docs/usage/save_restore_state.rst index 2ec7bc15..2c755d11 100644 --- a/docs/usage/save_restore_state.rst +++ b/docs/usage/save_restore_state.rst @@ -12,7 +12,7 @@ It is possible to save a state of the entire simulation environment. This is use import panda_gym - env = gym.make("PandaReachDense-v3", render=True) + env = gym.make("PandaReachDense-v3", render_mode="human") observation, _ = env.reset() for _ in range(1000): diff --git a/docs/usage/train_with_sb3.rst b/docs/usage/train_with_sb3.rst index 8581eff1..b39e0df1 100644 --- a/docs/usage/train_with_sb3.rst +++ b/docs/usage/train_with_sb3.rst @@ -60,8 +60,8 @@ For example, to train an agent with TQC on ``PandaPickAndPlace-v3``: Enjoy ~~~~~ -To visualize the trained agent, follow the `instructions `_ in the SB3 documentation. It is necessary to add ``--env-kwargs render:True`` when running the enjoy script. +To visualize the trained agent, follow the `instructions `_ in the SB3 documentation. It is necessary to add ``--env-kwargs render_mode:human`` when running the enjoy script. .. code-block:: bash - python enjoy.py --algo --env --folder --env-kwargs render:True \ No newline at end of file + python enjoy.py --algo --env --folder --env-kwargs render_mode:human \ No newline at end of file diff --git a/examples/reach.py b/examples/reach.py index 5d7687bb..1c60ab46 100644 --- a/examples/reach.py +++ b/examples/reach.py @@ -2,7 +2,7 @@ import panda_gym -env = gym.make("PandaReach-v3", render=True) +env = gym.make("PandaReach-v3", render_mode="human") observation, info = env.reset() diff --git a/examples/rgb_rendering.py b/examples/rgb_rendering.py index b6a47331..686717c6 100644 --- a/examples/rgb_rendering.py +++ b/examples/rgb_rendering.py @@ -3,21 +3,21 @@ import panda_gym -env = gym.make("PandaStack-v3", render=True) +env = gym.make("PandaStack-v3", render_mode="rgb_array") images = [] observation, info = env.reset() -images.append(env.render("rgb_array")) +images.append(env.render()) for _ in range(1000): action = env.action_space.sample() observation, reward, terminated, truncated, info = env.step(action) - images.append(env.render("rgb_array")) + images.append(env.render()) if terminated or truncated: observation, info = env.reset() - images.append(env.render("rgb_array")) + images.append(env.render()) env.close() diff --git a/panda_gym/envs/core.py b/panda_gym/envs/core.py index 0df03fab..16911571 100644 --- a/panda_gym/envs/core.py +++ b/panda_gym/envs/core.py @@ -1,3 +1,4 @@ +import warnings from abc import ABC, abstractmethod from typing import Any, Dict, Optional, Tuple @@ -291,7 +292,6 @@ def close(self) -> None: def render( self, - mode: str = "human", width: int = 720, height: int = 480, target_position: Optional[np.ndarray] = None, @@ -299,15 +299,13 @@ def render( yaw: float = 45, pitch: float = -30, roll: float = 0, + mode: Optional[str] = None, ) -> Optional[np.ndarray]: """Render. - If mode is "human", make the rendering real-time. All other arguments are - unused. If mode is "rgb_array", return an RGB array of the scene. + If render mode is "rgb_array", return an RGB array of the scene. Else, do nothing. Args: - mode (str): "human" of "rgb_array". If "human", this method waits for the time necessary to have - a realistic temporal rendering and all other args are ignored. Else, return an RGB array. width (int, optional): Image width. Defaults to 720. height (int, optional): Image height. Defaults to 480. target_position (np.ndarray, optional): Camera targetting this postion, as (x, y, z). @@ -316,13 +314,20 @@ def render( yaw (float, optional): Yaw of the camera. Defaults to 45. pitch (float, optional): Pitch of the camera. Defaults to -30. roll (int, optional): Rool of the camera. Defaults to 0. + mode (str, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument of the constructor instead. Returns: RGB np.ndarray or None: An RGB array if mode is 'rgb_array', else None. """ + if mode is not None: + warnings.warn( + "The 'mode' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument of the constructor instead.", + DeprecationWarning, + ) target_position = target_position if target_position is not None else np.zeros(3) return self.sim.render( - mode, width=width, height=height, target_position=target_position, diff --git a/panda_gym/envs/panda_tasks.py b/panda_gym/envs/panda_tasks.py index 7b9bb7ac..bfd45d9b 100644 --- a/panda_gym/envs/panda_tasks.py +++ b/panda_gym/envs/panda_tasks.py @@ -1,3 +1,6 @@ +import warnings +from typing import Optional + import numpy as np from panda_gym.envs.core import RobotTaskEnv @@ -15,14 +18,28 @@ class PandaFlipEnv(RobotTaskEnv): """Pick and Place task wih Panda robot. Args: - render (bool, optional): Activate rendering. Defaults to False. + render_mode (str, optional): Render mode. Defaults to "rgb_array". reward_type (str, optional): "sparse" or "dense". Defaults to "sparse". control_type (str, optional): "ee" to control end-effector position or "joints" to control joint values. Defaults to "ee". + render (bool, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument instead. """ - def __init__(self, render: bool = False, reward_type: str = "sparse", control_type: str = "ee") -> None: - sim = PyBullet(render=render) + def __init__( + self, + render_mode: str = "rgb_array", + reward_type: str = "sparse", + control_type: str = "ee", + render: Optional[bool] = None, + ) -> None: + if render is not None: + warnings.warn( + "The 'render' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument instead.", + DeprecationWarning, + ) + sim = PyBullet(render_mode=render_mode) robot = Panda(sim, block_gripper=False, base_position=np.array([-0.6, 0.0, 0.0]), control_type=control_type) task = Flip(sim, reward_type=reward_type) super().__init__(robot, task) @@ -32,14 +49,28 @@ class PandaPickAndPlaceEnv(RobotTaskEnv): """Pick and Place task wih Panda robot. Args: - render (bool, optional): Activate rendering. Defaults to False. + render_mode (str, optional): Render mode. Defaults to "rgb_array". reward_type (str, optional): "sparse" or "dense". Defaults to "sparse". control_type (str, optional): "ee" to control end-effector position or "joints" to control joint values. Defaults to "ee". + render (bool, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument instead. """ - def __init__(self, render: bool = False, reward_type: str = "sparse", control_type: str = "ee") -> None: - sim = PyBullet(render=render) + def __init__( + self, + render_mode: str = "rgb_array", + reward_type: str = "sparse", + control_type: str = "ee", + render: Optional[bool] = None, + ) -> None: + if render is not None: + warnings.warn( + "The 'render' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument instead.", + DeprecationWarning, + ) + sim = PyBullet(render_mode=render_mode) robot = Panda(sim, block_gripper=False, base_position=np.array([-0.6, 0.0, 0.0]), control_type=control_type) task = PickAndPlace(sim, reward_type=reward_type) super().__init__(robot, task) @@ -49,14 +80,28 @@ class PandaPushEnv(RobotTaskEnv): """Push task wih Panda robot. Args: - render (bool, optional): Activate rendering. Defaults to False. + render_mode (str, optional): Render mode. Defaults to "rgb_array". reward_type (str, optional): "sparse" or "dense". Defaults to "sparse". control_type (str, optional): "ee" to control end-effector position or "joints" to control joint values. Defaults to "ee". + render (bool, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument instead. """ - def __init__(self, render: bool = False, reward_type: str = "sparse", control_type: str = "ee") -> None: - sim = PyBullet(render=render) + def __init__( + self, + render_mode: str = "rgb_array", + reward_type: str = "sparse", + control_type: str = "ee", + render: Optional[bool] = None, + ) -> None: + if render is not None: + warnings.warn( + "The 'render' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument instead.", + DeprecationWarning, + ) + sim = PyBullet(render_mode=render_mode) robot = Panda(sim, block_gripper=True, base_position=np.array([-0.6, 0.0, 0.0]), control_type=control_type) task = Push(sim, reward_type=reward_type) super().__init__(robot, task) @@ -66,14 +111,28 @@ class PandaReachEnv(RobotTaskEnv): """Reach task wih Panda robot. Args: - render (bool, optional): Activate rendering. Defaults to False. + render_mode (str, optional): Render mode. Defaults to "rgb_array". reward_type (str, optional): "sparse" or "dense". Defaults to "sparse". control_type (str, optional): "ee" to control end-effector position or "joints" to control joint values. Defaults to "ee". + render (bool, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument instead. """ - def __init__(self, render: bool = False, reward_type: str = "sparse", control_type: str = "ee") -> None: - sim = PyBullet(render=render) + def __init__( + self, + render_mode: str = "rgb_array", + reward_type: str = "sparse", + control_type: str = "ee", + render: Optional[bool] = None, + ) -> None: + if render is not None: + warnings.warn( + "The 'render' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument instead.", + DeprecationWarning, + ) + sim = PyBullet(render_mode=render_mode) robot = Panda(sim, block_gripper=True, base_position=np.array([-0.6, 0.0, 0.0]), control_type=control_type) task = Reach(sim, reward_type=reward_type, get_ee_position=robot.get_ee_position) super().__init__(robot, task) @@ -83,14 +142,28 @@ class PandaSlideEnv(RobotTaskEnv): """Slide task wih Panda robot. Args: - render (bool, optional): Activate rendering. Defaults to False. + render_mode (str, optional): Render mode. Defaults to "rgb_array". reward_type (str, optional): "sparse" or "dense". Defaults to "sparse". control_type (str, optional): "ee" to control end-effector position or "joints" to control joint values. Defaults to "ee". + render (bool, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument instead. """ - def __init__(self, render: bool = False, reward_type: str = "sparse", control_type: str = "ee") -> None: - sim = PyBullet(render=render) + def __init__( + self, + render_mode: str = "rgb_array", + reward_type: str = "sparse", + control_type: str = "ee", + render: Optional[bool] = None, + ) -> None: + if render is not None: + warnings.warn( + "The 'render' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument instead.", + DeprecationWarning, + ) + sim = PyBullet(render_mode=render_mode) robot = Panda(sim, block_gripper=True, base_position=np.array([-0.6, 0.0, 0.0]), control_type=control_type) task = Slide(sim, reward_type=reward_type) super().__init__(robot, task) @@ -100,14 +173,28 @@ class PandaStackEnv(RobotTaskEnv): """Stack task wih Panda robot. Args: - render (bool, optional): Activate rendering. Defaults to False. + render_mode (str, optional): Render mode. Defaults to "rgb_array". reward_type (str, optional): "sparse" or "dense". Defaults to "sparse". control_type (str, optional): "ee" to control end-effector position or "joints" to control joint values. Defaults to "ee". + render (bool, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument instead. """ - def __init__(self, render: bool = False, reward_type: str = "sparse", control_type: str = "ee") -> None: - sim = PyBullet(render=render) + def __init__( + self, + render_mode: str = "rgb_array", + reward_type: str = "sparse", + control_type: str = "ee", + render: Optional[bool] = None, + ) -> None: + if render is not None: + warnings.warn( + "The 'render' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument instead.", + DeprecationWarning, + ) + sim = PyBullet(render_mode=render_mode) robot = Panda(sim, block_gripper=False, base_position=np.array([-0.6, 0.0, 0.0]), control_type=control_type) task = Stack(sim, reward_type=reward_type) super().__init__(robot, task) diff --git a/panda_gym/pybullet.py b/panda_gym/pybullet.py index fff5981d..b4e869b3 100644 --- a/panda_gym/pybullet.py +++ b/panda_gym/pybullet.py @@ -1,5 +1,4 @@ import os -import time import warnings from contextlib import contextmanager from typing import Any, Dict, Iterator, Optional @@ -16,19 +15,39 @@ class PyBullet: """Convenient class to use PyBullet physics engine. Args: - render (bool, optional): Enable rendering. Defaults to False. + render_mode (str, optional): Render mode. Defaults to "rgb_array". n_substeps (int, optional): Number of sim substep when step() is called. Defaults to 20. background_color (np.ndarray, optional): The background color as (red, green, blue). Defaults to np.array([223, 54, 45]). + render (bool, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument instead. """ - def __init__(self, render: bool = False, n_substeps: int = 20, background_color: Optional[np.ndarray] = None) -> None: + def __init__( + self, + render_mode: str = "rgb_array", + n_substeps: int = 20, + background_color: Optional[np.ndarray] = None, + render: Optional[bool] = None, + ) -> None: + self.render_mode = render_mode + if render is not None: + warnings.warn( + "The 'render' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument instead.", + DeprecationWarning, + ) background_color = background_color if background_color is not None else np.array([223.0, 54.0, 45.0]) self.background_color = background_color.astype(np.float32) / 255 options = "--background_color_red={} --background_color_green={} --background_color_blue={}".format( *self.background_color ) - self.connection_mode = p.GUI if render else p.DIRECT + if self.render_mode == "human": + self.connection_mode = p.GUI + elif self.render_mode == "rgb_array": + self.connection_mode = p.DIRECT + else: + raise ValueError("The 'render' argument is must be in {'rgb_array', 'human'}") self.physics_client = bc.BulletClient(connection_mode=self.connection_mode, options=options) self.physics_client.configureDebugVisualizer(p.COV_ENABLE_GUI, 0) self.physics_client.configureDebugVisualizer(p.COV_ENABLE_MOUSE_PICKING, 0) @@ -82,7 +101,6 @@ def remove_state(self, state_id: int) -> None: def render( self, - mode: str = "human", width: int = 720, height: int = 480, target_position: Optional[np.ndarray] = None, @@ -90,15 +108,13 @@ def render( yaw: float = 45, pitch: float = -30, roll: float = 0, + mode: Optional[str] = None, ) -> Optional[np.ndarray]: """Render. - If mode is "human", make the rendering real-time. All other arguments are - unused. If mode is "rgb_array", return an RGB array of the scene. + If render mode is "rgb_array", return an RGB array of the scene. Else, do nothing. Args: - mode (str): "human" of "rgb_array". If "human", this method waits for the time necessary to have - a realistic temporal rendering and all other args are ignored. Else, return an RGB array. width (int, optional): Image width. Defaults to 720. height (int, optional): Image height. Defaults to 480. target_position (np.ndarray, optional): Camera targetting this postion, as (x, y, z). @@ -107,21 +123,26 @@ def render( yaw (float, optional): Yaw of the camera. Defaults to 45. pitch (float, optional): Pitch of the camera. Defaults to -30. roll (int, optional): Rool of the camera. Defaults to 0. + mode (str, optional): Deprecated: This argument is deprecated and will be removed in a future + version. Use the render_mode argument of the constructor instead. Returns: RGB np.ndarray or None: An RGB array if mode is 'rgb_array', else None. """ + if mode is not None: + warnings.warn( + "The 'mode' argument is deprecated and will be removed in " + "a future version. Use the 'render_mode' argument of the constructor instead.", + DeprecationWarning, + ) target_position = target_position if target_position is not None else np.zeros(3) - if mode == "human": - self.physics_client.configureDebugVisualizer(self.physics_client.COV_ENABLE_SINGLE_STEP_RENDERING) - time.sleep(self.dt) # wait to seems like real speed - if mode == "rgb_array": + if self.render_mode == "rgb_array": if self.connection_mode == p.DIRECT: warnings.warn( "The use of the render method is not recommended when the environment " - "has not been created with render=True. The rendering will probably be weird. " - "Prefer making the environment with option `render=True`. For example: " - "`env = gym.make('PandaReach-v3', render=True)`.", + "has not been created with render_mode='human'. The rendering will probably be weird. " + "Prefer making the environment with option `render_mode='rgb_array'. For example: " + "`env = gym.make('PandaReach-v3', render_mode='rgb_array')`.", UserWarning, ) view_matrix = self.physics_client.computeViewMatrixFromYawPitchRoll( diff --git a/panda_gym/version.txt b/panda_gym/version.txt index 56fea8a0..13d683cc 100644 --- a/panda_gym/version.txt +++ b/panda_gym/version.txt @@ -1 +1 @@ -3.0.0 \ No newline at end of file +3.0.1 \ No newline at end of file