Skip to content

Commit 93884de

Browse files
Add designed environment mapping
1 parent d4e43a6 commit 93884de

File tree

1 file changed

+69
-26
lines changed

1 file changed

+69
-26
lines changed

gymnasium/envs/box2d/bipedal_walker.py

+69-26
Original file line numberDiff line numberDiff line change
@@ -82,27 +82,75 @@
8282

8383

8484
class TerrainMetadata:
85+
"""
86+
## Description
87+
This is metadata object handler for the BipedalWalker environment.
88+
89+
<!-- ## References -->
90+
91+
## Credits
92+
Created by Arthur Plautz Ventura
93+
94+
"""
95+
8596
def __init__(self, metadata: dict = {}):
86-
self._states, self._counters = [], [] # Control parameters
87-
self._metadata = {0: [], 1: [], 2: [], 3: []} # Random values for terrain types
97+
self._states = [] # Control parameters
98+
self._metadata = {1: [], 2: [], 3: []} # Random values for terrain types
99+
self._variations = True
100+
self.__generate = False
88101

89102
if metadata:
90103
self.__from_dict(metadata) # Copy values from existing metadata
91104
else:
92105
self.__generate = True # New values should be generated
93106

107+
@property
108+
def grass_variations(self):
109+
return self._variations
110+
111+
def _pit_length(self, metadata=None):
112+
return 4
113+
114+
def _stairs_length(self, metadata):
115+
_, stair_width, stair_steps = metadata
116+
return stair_width * stair_steps
117+
118+
def _stump_length(self, metadata):
119+
return metadata
120+
121+
def get_obstacles_length(self):
122+
total_length = 0
123+
state_length = {
124+
1: self._stump_length,
125+
2: self._stairs_length,
126+
3: self._pit_length,
127+
}
128+
129+
n_states = len(self._states)
130+
metadata = deepcopy(self._metadata)
131+
for state in self._states:
132+
length_map = state_length[state]
133+
total_length += length_map(metadata[state].pop(0))
134+
return total_length, n_states
135+
94136
def get_dict(self):
95137
return dict(
96138
states=deepcopy(self._states),
97-
counters=deepcopy(self._counters),
98139
metadata=deepcopy(self._metadata),
140+
variations=self._variations,
99141
)
100142

101143
def __from_dict(self, metadata: dict):
102-
self._states: list = deepcopy(metadata.get("states"))
103-
self._counters: list = deepcopy(metadata.get("counters"))
104-
self._metadata: list = deepcopy(metadata.get("metadata"))
105-
self.__generate = False
144+
if metadata.get("designed", False):
145+
self._variations = metadata.get("variations", True)
146+
for state_obj in metadata.get("states", []):
147+
state = state_obj["state"]
148+
self._states.append(state)
149+
self._metadata[state].append(state_obj["metadata"])
150+
else:
151+
self._states = metadata.get("states", self._states)
152+
self._metadata = metadata.get("metadata", self._metadata)
153+
self._variations = metadata.get("variations", self._variations)
106154

107155
def mode(self) -> bool:
108156
return self.__generate
@@ -119,12 +167,6 @@ def get_state(self) -> int:
119167
def add_state(self, state: int):
120168
self._states.append(state)
121169

122-
def get_counter(self) -> int:
123-
return self._counters.pop(0)
124-
125-
def add_counter(self, counter: int):
126-
self._counters.append(counter)
127-
128170

129171
class ContactDetector(contactListener):
130172
def __init__(self, env):
@@ -334,6 +376,13 @@ def terrain_metadata(self):
334376

335377
def _generate_terrain(self, hardcore):
336378
generate = self._terrain_metadata.mode()
379+
if not generate:
380+
obstacles_length, n_obstacles = (
381+
self._terrain_metadata.get_obstacles_length()
382+
)
383+
self.terrain_grass = (TERRAIN_LENGTH - obstacles_length) // n_obstacles
384+
else:
385+
self.terrain_grass = TERRAIN_GRASS
337386

338387
GRASS, STUMP, STAIRS, PIT, _STATES_ = range(5)
339388
state = GRASS
@@ -352,13 +401,9 @@ def _generate_terrain(self, hardcore):
352401
self.terrain_x.append(x)
353402

354403
if state == GRASS and not oneshot:
355-
if generate:
356-
velocity = 0.8 * velocity + 0.01 * np.sign(TERRAIN_HEIGHT - y)
357-
if i > TERRAIN_STARTPAD:
358-
velocity += self.np_random.uniform(-1, 1) / SCALE # 1
359-
self._terrain_metadata.set_metadata(state=GRASS, value=velocity)
360-
else:
361-
velocity = self._terrain_metadata.get_metadata(state=GRASS)
404+
velocity = 0.8 * velocity + 0.01 * np.sign(TERRAIN_HEIGHT - y)
405+
if self._terrain_metadata.grass_variations and i > TERRAIN_STARTPAD:
406+
velocity += self.np_random.uniform(-1, 1) / SCALE # 1
362407
y += velocity
363408

364409
elif state == PIT and oneshot:
@@ -367,6 +412,8 @@ def _generate_terrain(self, hardcore):
367412
self._terrain_metadata.set_metadata(state=PIT, value=counter)
368413
else:
369414
counter = self._terrain_metadata.get_metadata(state=PIT)
415+
if not counter:
416+
counter = self.np_random.integers(3, 5)
370417

371418
poly = [
372419
(x, y),
@@ -459,11 +506,7 @@ def _generate_terrain(self, hardcore):
459506
self.terrain_y.append(y)
460507
counter -= 1
461508
if counter == 0:
462-
if generate:
463-
counter = self.np_random.integers(TERRAIN_GRASS / 2, TERRAIN_GRASS)
464-
self._terrain_metadata.add_counter(counter)
465-
else:
466-
counter = self._terrain_metadata.get_counter()
509+
counter = self.terrain_grass
467510

468511
if state == GRASS and hardcore:
469512
if generate:
@@ -691,7 +734,7 @@ def step(self, action: np.ndarray):
691734
if self.game_over or pos[0] < 0:
692735
reward = -100
693736
terminated = True
694-
if pos[0] > (TERRAIN_LENGTH - TERRAIN_GRASS) * TERRAIN_STEP:
737+
if pos[0] > (TERRAIN_LENGTH - self.terrain_grass) * TERRAIN_STEP:
695738
terminated = True
696739

697740
if self.render_mode == "human":

0 commit comments

Comments
 (0)