diff --git a/tutorials/README.md b/tutorials/README.md index 878b7cc0..1cde19a0 100644 --- a/tutorials/README.md +++ b/tutorials/README.md @@ -1,3 +1,25 @@ # Tutorials -This folder contains completed code for all tutorials on our [website](https://evolutiongym.github.io/tutorials). \ No newline at end of file +This folder contains completed code for all tutorials on our [website](https://evolutiongym.github.io/tutorials). + +## Custom Environment + +To see an example of custom environment creation, see `envs/simple_env.py`. This environment is registered in `envs/__init__.py`, and can be visualized by running `python .\visualize_simple_env.py` from this directory. + +## Evogym Simulator API + +See `basic_api.py` for a simple example of how to create, step, and render an Evogym simulator with objects of your choice. Evogym can be used to simulate any number of objects and robots (although simulation speed may slow with many objects). + +To see understand the different rendering options available in Evogym, see `rendering_options.py`. +You can run: + +```bash +python .\rendering_options.py --render-option to-debug-screen +``` + +| Option | Description | +|--------------------|------------------------------------------------------------------------| +| to-debug-screen | Render to Evogym's default viewer | +| to-numpy-array | Render to a numpy array (visualized with open cv) | +| special-options | Render with special flags (for pretty visualization) | +| very-fast | Render without fps limit | diff --git a/tutorials/envs/__init__.py b/tutorials/envs/__init__.py index 56719962..dd84f967 100644 --- a/tutorials/envs/__init__.py +++ b/tutorials/envs/__init__.py @@ -1,7 +1,7 @@ # import envs and necessary gym packages from envs.simple_env import SimpleWalkerEnvClass -from gym.envs.registration import register +from gymnasium.envs.registration import register # register the env using gym's interface register( diff --git a/tutorials/envs/simple_env.py b/tutorials/envs/simple_env.py index 85891069..51cc8f1f 100644 --- a/tutorials/envs/simple_env.py +++ b/tutorials/envs/simple_env.py @@ -1,27 +1,34 @@ -from gym import spaces +from gymnasium import spaces from evogym import EvoWorld from evogym.envs import EvoGymBase +from typing import Optional, Dict, Any, Tuple import numpy as np import os class SimpleWalkerEnvClass(EvoGymBase): - def __init__(self, body, connections=None): + def __init__( + self, + body: np.ndarray, + connections: Optional[np.ndarray] = None, + render_mode: Optional[str] = None, + render_options: Optional[Dict[str, Any]] = None, + ): # make world self.world = EvoWorld.from_json(os.path.join('world_data', 'simple_walker_env.json')) self.world.add_from_array('robot', body, 1, 1, connections=connections) # init sim - EvoGymBase.__init__(self, self.world) + EvoGymBase.__init__(self, world=self.world, render_mode=render_mode, render_options=render_options) # set action space and observation space num_actuators = self.get_actuator_indices('robot').size - obs_size = self.reset().size + obs_size = self.reset()[0].size - self.action_space = spaces.Box(low= 0.6, high=1.6, shape=(num_actuators,), dtype=np.float) - self.observation_space = spaces.Box(low=-100.0, high=100.0, shape=(obs_size,), dtype=np.float) + self.action_space = spaces.Box(low= 0.6, high=1.6, shape=(num_actuators,), dtype=float) + self.observation_space = spaces.Box(low=-100.0, high=100.0, shape=(obs_size,), dtype=float) # set viewer to track objects self.default_viewer.track_objects('robot') @@ -58,12 +65,12 @@ def step(self, action): self.get_relative_pos_obs("robot"), )) - # observation, reward, has simulation met termination conditions, debugging info - return obs, reward, done, {} + # observation, reward, has simulation met termination conditions, truncated, debugging info + return obs, reward, done, False, {} - def reset(self): + def reset(self, seed: Optional[int] = None, options: Optional[Dict[str, Any]] = None) -> Tuple[np.ndarray, Dict[str, Any]]: - super().reset() + super().reset(seed=seed, options=options) # observation obs = np.concatenate(( @@ -71,4 +78,4 @@ def reset(self): self.get_relative_pos_obs("robot"), )) - return obs \ No newline at end of file + return obs, {} \ No newline at end of file diff --git a/tutorials/rendering_options.py b/tutorials/rendering_options.py index 682a92dd..34c533f2 100644 --- a/tutorials/rendering_options.py +++ b/tutorials/rendering_options.py @@ -2,6 +2,7 @@ import os import numpy as np import cv2 +import argparse ### CREATE A SIMPLE ENVIRONMENT ### @@ -27,13 +28,18 @@ ### SELECT A RENDERING OPTION ### -options = ['to-debug-screen', 'to-numpy-array', 'special-options', 'very-fast'] -option = options[0] - -print(f'\nUsing rendering option {option}...\n') +parser = argparse.ArgumentParser() +parser.add_argument( + '--render-option', + choices=['to-debug-screen', 'to-numpy-array', 'special-options', 'very-fast'], + help='Select a rendering option from: to-debug-screen, to-numpy-array, special-options, very-fast', + default='to-debug-screen', +) +args = parser.parse_args() +print(f'\nUsing rendering option {args.render_option}...\n') # if the 'very-fast' option is chosen, set the rendering speed to be unlimited -if option == 'very-fast': +if args.render_option == 'very-fast': viewer.set_target_rps(None) for i in range(1000): @@ -48,19 +54,19 @@ sim.step() # step and render to a debug screen - if option == 'to-debug-screen': + if args.render_option == 'to-debug-screen': viewer.render('screen') # step and render to a numpy array # use open cv to visualize output - if option == 'to-numpy-array': + if args.render_option == 'to-numpy-array': img = viewer.render('img') img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) cv2.waitKey(1) cv2.imshow("Open CV Window", img) # rendering with more options - if option == 'special-options': + if args.render_option == 'special-options': img = viewer.render( 'screen', verbose = True, @@ -70,7 +76,8 @@ hide_voxels = False) # rendering as fast as possible - if option == 'very-fast': + if args.render_option == 'very-fast': viewer.render('screen', verbose=True) cv2.destroyAllWindows() +viewer.close() diff --git a/tutorials/visualize_simple_env.py b/tutorials/visualize_simple_env.py index 5ecc77e7..d74cde3e 100644 --- a/tutorials/visualize_simple_env.py +++ b/tutorials/visualize_simple_env.py @@ -1,4 +1,4 @@ -import gym +import gymnasium as gym from evogym import sample_robot # import envs from the envs folder and register them @@ -10,17 +10,21 @@ body, connections = sample_robot((5,5)) # make the SimpleWalkingEnv using gym.make and with the robot information - env = gym.make('SimpleWalkingEnv-v0', body=body) + env = gym.make( + 'SimpleWalkingEnv-v0', + body=body, + render_mode='human', + render_options={'verbose': True} + ) env.reset() # step the environment for 500 iterations for i in range(500): action = env.action_space.sample() - ob, reward, done, info = env.step(action) - env.render(verbose=True) + ob, reward, terminated, truncated, info = env.step(action) - if done: + if terminated or truncated: env.reset() env.close()