Made quadrotor gymnasium env compatible with Gymnasium 1.0.0 (Issue #11)
This commit is contained in:
@@ -48,7 +48,7 @@ env = gym.make("Quadrotor-v0",
|
|||||||
# Now reset the quadrotor.
|
# Now reset the quadrotor.
|
||||||
# Setting initial_state to 'random' will randomly place the vehicle in the map near the origin.
|
# Setting initial_state to 'random' will randomly place the vehicle in the map near the origin.
|
||||||
# But you can also set the environment resetting to be deterministic.
|
# But you can also set the environment resetting to be deterministic.
|
||||||
observation, info = env.reset(initial_state='random')
|
observation, info = env.reset(options={'initial_state': 'random'})
|
||||||
|
|
||||||
# Number of timesteps
|
# Number of timesteps
|
||||||
T = 300
|
T = 300
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ env = gym.make("Quadrotor-v0",
|
|||||||
# check_env(env, warn=True) # you can check the environment using built-in tools
|
# check_env(env, warn=True) # you can check the environment using built-in tools
|
||||||
|
|
||||||
# Reset the environment
|
# Reset the environment
|
||||||
observation, info = env.reset(initial_state='random', options={'pos_bound': 2, 'vel_bound': 0})
|
observation, info = env.reset(options={'initial_state': 'random', 'pos_bound': 2, 'vel_bound': 0})
|
||||||
|
|
||||||
# Create a new model
|
# Create a new model
|
||||||
model = PPO(MlpPolicy, env, verbose=1, ent_coef=0.01, tensorboard_log=log_dir)
|
model = PPO(MlpPolicy, env, verbose=1, ent_coef=0.01, tensorboard_log=log_dir)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ dependencies = [
|
|||||||
'scipy',
|
'scipy',
|
||||||
'pandas',
|
'pandas',
|
||||||
'tqdm',
|
'tqdm',
|
||||||
'gymnasium == 0.29.1',
|
'gymnasium',
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
|||||||
@@ -70,9 +70,9 @@ class QuadrotorEnv(gym.Env):
|
|||||||
|
|
||||||
self.metadata['render_fps'] = render_fps
|
self.metadata['render_fps'] = render_fps
|
||||||
|
|
||||||
self.initial_state = initial_state
|
self.initial_state = deepcopy(initial_state)
|
||||||
|
|
||||||
self.vehicle_state = initial_state
|
self.vehicle_state = deepcopy(initial_state)
|
||||||
|
|
||||||
assert control_mode in self.metadata["control_modes"] # Don't accept improper control modes
|
assert control_mode in self.metadata["control_modes"] # Don't accept improper control modes
|
||||||
self.control_mode = control_mode
|
self.control_mode = control_mode
|
||||||
@@ -184,34 +184,44 @@ class QuadrotorEnv(gym.Env):
|
|||||||
# Close the plots
|
# Close the plots
|
||||||
plt.close('all')
|
plt.close('all')
|
||||||
|
|
||||||
def reset(self, seed=None, initial_state='random', options={'pos_bound': 2, 'vel_bound': 0}):
|
def reset(self, seed=None, options={'initial_state': 'random', 'pos_bound': 2, 'vel_bound': 0}):
|
||||||
"""
|
"""
|
||||||
Reset the environment
|
Reset the environment
|
||||||
Inputs:
|
Inputs:
|
||||||
seed: the seed for any random number generation, mostly for reproducibility.
|
seed: the seed for any random number generation, mostly for reproducibility.
|
||||||
initial_state: determines how to set the quadrotor again. Options are...
|
|
||||||
'random': will randomly select the state of the quadrotor.
|
|
||||||
'deterministic': will set the state to the initial state selected by the user when creating
|
|
||||||
the quadrotor environment (usually hover).
|
|
||||||
the user can also specify the state itself as a dictionary... e.g.
|
|
||||||
reset(options={'initial_state':
|
|
||||||
{'x': np.array([0,0,0]),
|
|
||||||
'v': np.zeros(3,),
|
|
||||||
'q': np.array([0, 0, 0, 1]), # [i,j,k,w]
|
|
||||||
'w': np.zeros(3,),
|
|
||||||
'wind': np.array([0,0,0]), # Since wind is handled elsewhere, this value is overwritten
|
|
||||||
'rotor_speeds': np.array([1788.53, 1788.53, 1788.53, 1788.53])}
|
|
||||||
})
|
|
||||||
options: dictionary for misc options for resetting the scene.
|
options: dictionary for misc options for resetting the scene.
|
||||||
|
'initial_state': determines how to set the quadrotor again. Options are...
|
||||||
|
'random': will randomly select the state of the quadrotor.
|
||||||
|
'deterministic': will set the state to the initial state selected by the user when creating
|
||||||
|
the quadrotor environment (usually hover).
|
||||||
|
the user can also specify the state itself as a dictionary... e.g.
|
||||||
|
reset(options={'initial_state':
|
||||||
|
{'x': np.array([0,0,0]),
|
||||||
|
'v': np.zeros(3,),
|
||||||
|
'q': np.array([0, 0, 0, 1]), # [i,j,k,w]
|
||||||
|
'w': np.zeros(3,),
|
||||||
|
'wind': np.array([0,0,0]), # Since wind is handled elsewhere, this value is overwritten
|
||||||
|
'rotor_speeds': np.array([1788.53, 1788.53, 1788.53, 1788.53])}
|
||||||
|
})
|
||||||
'pos_bound': the min/max position region for random placement.
|
'pos_bound': the min/max position region for random placement.
|
||||||
'vel_bound': the min/max velocity region for random placement
|
'vel_bound': the min/max velocity region for random placement
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# If any options are not specified, set them to default values.
|
||||||
|
if 'pos_bound' not in options:
|
||||||
|
options['pos_bound'] = 2
|
||||||
|
if 'vel_bound' not in options:
|
||||||
|
options['vel_bound'] = 0
|
||||||
|
if 'initial_state' not in options:
|
||||||
|
options['initial_state'] = 'random'
|
||||||
|
|
||||||
|
# Assert that the bounds are greater than or equal to 0.
|
||||||
assert options['pos_bound'] >= 0 and options['vel_bound'] >= 0 , "Bounds must be greater than or equal to 0."
|
assert options['pos_bound'] >= 0 and options['vel_bound'] >= 0 , "Bounds must be greater than or equal to 0."
|
||||||
|
|
||||||
|
# Reset the gym environment
|
||||||
super().reset(seed=seed)
|
super().reset(seed=seed)
|
||||||
|
|
||||||
if initial_state == 'random':
|
if options['initial_state'] == 'random':
|
||||||
# Randomly select an initial state for the quadrotor. At least assume it is level.
|
# Randomly select an initial state for the quadrotor. At least assume it is level.
|
||||||
pos = np.random.uniform(low=-options['pos_bound'], high=options['pos_bound'], size=(3,))
|
pos = np.random.uniform(low=-options['pos_bound'], high=options['pos_bound'], size=(3,))
|
||||||
vel = np.random.uniform(low=-options['vel_bound'], high=options['vel_bound'], size=(3,))
|
vel = np.random.uniform(low=-options['vel_bound'], high=options['vel_bound'], size=(3,))
|
||||||
@@ -222,13 +232,13 @@ class QuadrotorEnv(gym.Env):
|
|||||||
'wind': np.array([0,0,0]), # Since wind is handled elsewhere, this value is overwritten
|
'wind': np.array([0,0,0]), # Since wind is handled elsewhere, this value is overwritten
|
||||||
'rotor_speeds': np.array([1788.53, 1788.53, 1788.53, 1788.53])}
|
'rotor_speeds': np.array([1788.53, 1788.53, 1788.53, 1788.53])}
|
||||||
|
|
||||||
elif initial_state == 'deterministic':
|
elif options['initial_state'] == 'deterministic':
|
||||||
state = self.initial_state
|
state = self.initial_state
|
||||||
|
|
||||||
elif isinstance(initial_state, dict):
|
elif isinstance(options['initial_state'], dict):
|
||||||
# Ensure the correct keys are in dict.
|
# Ensure the correct keys are in dict.
|
||||||
if all(key in initial_state for key in ('x', 'v', 'q', 'w', 'wind', 'rotor_speeds')):
|
if all(key in options['initial_state'] for key in ('x', 'v', 'q', 'w', 'wind', 'rotor_speeds')):
|
||||||
state = initial_state
|
state = options['initial_state']
|
||||||
else:
|
else:
|
||||||
raise KeyError("Missing state keys in your initial_state. You must specify values for ('x', 'v', 'q', 'w', 'wind', 'rotor_speeds')")
|
raise KeyError("Missing state keys in your initial_state. You must specify values for ('x', 'v', 'q', 'w', 'wind', 'rotor_speeds')")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user