class MixedTerrainWorld(_ComplexTerrainWorld):
"""World with repeated blocks, gaps, and flat floor sections."""
def __init__(
self,
name: str = "mixed_terrain_world",
*,
x_ranges: tuple[tuple[float, float], ...] = ((-4, 5), (5, 14), (14, 23)),
y_range: tuple[float, float] = (-20, 20),
gap_width: float = 0.3,
gapped_block_width: float = 1.0,
gap_depth: float = 2.0,
block_size: float = 1.3,
height_range: tuple[float, float] = (0.35, 0.35),
ground_alpha: float = 1.0,
rand_seed: int = 0,
) -> None:
super().__init__(name=name)
y_halfwidth = (y_range[1] - y_range[0]) / 2
rand_state = np.random.RandomState(rand_seed)
height_expected_value = np.mean(height_range)
for range_idx, x_range in enumerate(x_ranges):
x_centers = np.arange(
x_range[0] + block_size / 2,
x_range[0] + block_size * 3,
block_size,
)
y_centers = np.arange(y_range[0] + block_size / 2, y_range[1], block_size)
for i, x_pos in enumerate(x_centers):
for j, y_pos in enumerate(y_centers):
if (i % 2 == 1) != (j % 2 == 1):
height = 0.1
else:
height = 0.1 + rand_state.uniform(*height_range)
self._add_ground_box(
name=(
f"ground_mixed_block{range_idx}_"
f"x{_format_name_number(x_pos)}_"
f"y{_format_name_number(y_pos)}"
),
size=(
0.55 * block_size,
0.55 * block_size,
height / 2 + block_size / 2,
),
pos=(
x_pos,
y_pos,
height / 2 - block_size / 2 - height_expected_value - 0.1,
),
rgba=(0.3, 0.3, 0.3, ground_alpha),
)
curr_x_pos = x_range[0] + block_size * 3
self._add_ground_box(
name=f"ground_gap_pre{range_idx}",
size=(gapped_block_width / 4, y_halfwidth, gap_depth / 2),
pos=(curr_x_pos + gapped_block_width / 4, 0, -gap_depth / 2),
rgba=(0.3, 0.3, 0.3, ground_alpha),
)
curr_x_pos += gapped_block_width / 2 + gap_width
self._add_ground_box(
name=f"ground_gap_post{range_idx}",
size=(gapped_block_width / 2, y_halfwidth, gap_depth / 2),
pos=(curr_x_pos + gapped_block_width / 2, 0, -gap_depth / 2),
rgba=(0.3, 0.3, 0.3, ground_alpha),
)
curr_x_pos += gapped_block_width + gap_width
remaining_space = x_range[1] - curr_x_pos
if remaining_space <= 0:
raise ValueError(
"Each mixed-terrain x-range must leave positive flat-floor "
"space after the block and gap sections."
)
self._add_ground_box(
name=f"ground_flat{range_idx}",
size=(remaining_space / 2, y_halfwidth, gap_depth / 2),
pos=(curr_x_pos + remaining_space / 2, 0, -gap_depth / 2),
rgba=(0.3, 0.3, 0.3, ground_alpha),
)
self._add_ground_plane(
name=f"ground_base{range_idx}",
size=((x_range[1] - x_range[0]) / 2, y_halfwidth, 1),
pos=(np.mean(x_range), 0, -gap_depth / 2),
rgba=(0.3, 0.3, 0.3, ground_alpha),
)