Source code for unilab.terrains.config

"""Terrain configuration presets and named terrain sets.

Slim port of mjlab/terrains/config.py — keeps only the 7 sub-terrains used by
ROUGH_TERRAINS_CFG and the curriculum stairs preset.

To add a new terrain, define a function decorated with @terrain_preset::

    @terrain_preset
    def my_new_terrain(**overrides: Any) -> SomeTerrainCfg:
        defaults: dict[str, Any] = dict(...)
        defaults.update(overrides)
        return SomeTerrainCfg(**defaults)

It will be auto-included in ALL_TERRAIN_PRESETS.
"""

from collections.abc import Callable
from typing import Any, TypeVar

from unilab.terrains.heightfield_terrains import (
    HfFlatTerrainCfg,
    HfInvertedPyramidStairsTerrainCfg,
    HfPyramidSlopedTerrainCfg,
    HfPyramidStairsTerrainCfg,
    HfRandomUniformTerrainCfg,
    HfWaveTerrainCfg,
)
from unilab.terrains.terrain_generator import SubTerrainCfg, TerrainGeneratorCfg

# Preset registry.

ALL_TERRAIN_PRESETS: dict[str, Callable[..., SubTerrainCfg]] = {}

_F = TypeVar("_F", bound=Callable[..., SubTerrainCfg])


[docs] def terrain_preset(fn: _F) -> _F: """Register a terrain preset into ALL_TERRAIN_PRESETS.""" ALL_TERRAIN_PRESETS[fn.__name__] = fn return fn
# Terrain presets.
[docs] @terrain_preset def flat(**overrides: Any) -> HfFlatTerrainCfg: return HfFlatTerrainCfg(**overrides)
[docs] @terrain_preset def pyramid_stairs(**overrides: Any) -> HfPyramidStairsTerrainCfg: defaults: dict[str, Any] = dict( step_height_range=(0.0, 0.2), step_width=0.3, platform_width=3.0, border_width=1.0, ) defaults.update(overrides) return HfPyramidStairsTerrainCfg(**defaults)
[docs] @terrain_preset def pyramid_stairs_inv(**overrides: Any) -> HfInvertedPyramidStairsTerrainCfg: defaults: dict[str, Any] = dict( step_height_range=(0.0, 0.2), step_width=0.3, platform_width=3.0, border_width=1.0, ) defaults.update(overrides) return HfInvertedPyramidStairsTerrainCfg(**defaults)
[docs] @terrain_preset def hf_pyramid_slope(**overrides: Any) -> HfPyramidSlopedTerrainCfg: defaults: dict[str, Any] = dict( slope_range=(0.0, 0.7), platform_width=2.0, border_width=0.25, ) defaults.update(overrides) return HfPyramidSlopedTerrainCfg(**defaults)
[docs] @terrain_preset def hf_pyramid_slope_inv(**overrides: Any) -> HfPyramidSlopedTerrainCfg: defaults: dict[str, Any] = dict( slope_range=(0.0, 0.7), platform_width=2.0, border_width=0.25, inverted=True, ) defaults.update(overrides) return HfPyramidSlopedTerrainCfg(**defaults)
[docs] @terrain_preset def random_rough(**overrides: Any) -> HfRandomUniformTerrainCfg: defaults: dict[str, Any] = dict( noise_range=(0.02, 0.10), noise_step=0.02, border_width=0.25, ) defaults.update(overrides) return HfRandomUniformTerrainCfg(**defaults)
[docs] @terrain_preset def wave_terrain(**overrides: Any) -> HfWaveTerrainCfg: defaults: dict[str, Any] = dict( amplitude_range=(0.0, 0.2), num_waves=4, border_width=0.25, ) defaults.update(overrides) return HfWaveTerrainCfg(**defaults)
# Named terrain sets. ROUGH_TERRAINS_CFG = TerrainGeneratorCfg( size=(8.0, 8.0), border_width=20.0, num_rows=10, num_cols=20, sub_terrains={ "flat": flat(proportion=0.2), "pyramid_stairs": pyramid_stairs(proportion=0.2, step_height_range=(0.0, 0.1)), "pyramid_stairs_inv": pyramid_stairs_inv(proportion=0.2, step_height_range=(0.0, 0.1)), "hf_pyramid_slope": hf_pyramid_slope(proportion=0.1, slope_range=(0.0, 1.0)), "hf_pyramid_slope_inv": hf_pyramid_slope_inv(proportion=0.1, slope_range=(0.0, 1.0)), "random_rough": random_rough(proportion=0.1), "wave_terrain": wave_terrain(proportion=0.1), }, add_lights=True, ) STAIRS_TERRAINS_CFG = TerrainGeneratorCfg( size=(8.0, 8.0), border_width=20.0, num_rows=10, num_cols=4, curriculum=True, sub_terrains={ "flat": flat(proportion=0.25), "easy_stairs": pyramid_stairs( proportion=0.35, step_height_range=(0.02, 0.05), step_width=0.40, ), "moderate_stairs": pyramid_stairs( proportion=0.25, step_height_range=(0.05, 0.08), step_width=0.35, platform_width=2.5, border_width=0.8, ), "challenging_stairs": pyramid_stairs( proportion=0.15, step_height_range=(0.08, 0.10), step_width=0.30, platform_width=2.0, border_width=0.5, ), }, add_lights=True, )