Some checks failed
nightly / Test against latest dependencies (py3.10) (push) Has been cancelled
nightly / Test against latest dependencies (py3.13) (push) Has been cancelled
tests / tests (3.13, locked) (push) Has been cancelled
tests / tests (3.13, unlocked) (push) Has been cancelled
tests / pyright (3.10) (push) Has been cancelled
tests / lint-format (push) Has been cancelled
tests / tests (3.10, locked) (push) Has been cancelled
tests / tests (3.11, locked) (push) Has been cancelled
tests / tests (3.12, locked) (push) Has been cancelled
tests / pyright (3.11) (push) Has been cancelled
tests / pyright (3.12) (push) Has been cancelled
tests / pyright (3.13) (push) Has been cancelled
tests / ty-check (3.10) (push) Has been cancelled
tests / ty-check (3.11) (push) Has been cancelled
tests / ty-check (3.12) (push) Has been cancelled
tests / ty-check (3.13) (push) Has been cancelled
tests / stubs (push) Has been cancelled
tests / smoke-test (push) Has been cancelled
Docker / check_paths (push) Has been cancelled
docs / build (push) Has been cancelled
Docker / build (push) Has been cancelled
Upstream: https://github.com/michaelgillett/mjlab Upstream-Commit: c19f713c415a699a79d71cd96aa13c3104a05047 Upstream-Branch: main
383 lines
12 KiB
ReStructuredText
383 lines
12 KiB
ReStructuredText
.. _terrain:
|
|
|
|
Terrain
|
|
=======
|
|
|
|
The terrain is the shared ground surface for all environments in a scene.
|
|
mjlab supports two modes: a flat ground plane for tasks that do not need
|
|
varying terrain, and a procedural terrain generator that assembles a grid
|
|
of sub-terrain patches with configurable difficulty. Procedural terrain
|
|
is particularly useful for training locomotion policies, where a
|
|
curriculum of increasing ground difficulty drives robust walking and
|
|
climbing behaviors.
|
|
|
|
Terrain is configured through ``TerrainEntityCfg`` and passed to the
|
|
scene via the ``terrain`` field of ``SceneCfg``. See :ref:`scene` for
|
|
how the terrain integrates with the rest of the scene.
|
|
|
|
|
|
Flat terrain
|
|
------------
|
|
|
|
The default mode. A single ground plane modeled as a MuJoCo plane geom
|
|
with no procedural geometry. Environments are arranged in a regular grid
|
|
with spacing controlled by ``env_spacing`` on ``SceneCfg``.
|
|
|
|
.. code-block:: python
|
|
|
|
from mjlab.terrains import TerrainEntityCfg
|
|
|
|
terrain = TerrainEntityCfg(terrain_type="plane")
|
|
|
|
|
|
Procedural terrain
|
|
------------------
|
|
|
|
For tasks that benefit from terrain variety (locomotion, navigation),
|
|
``TerrainGeneratorCfg`` assembles a rectangular grid of sub-terrain
|
|
patches. Each patch is generated from a ``SubTerrainCfg`` that defines
|
|
the geometry and how it scales with difficulty.
|
|
|
|
.. code-block:: python
|
|
|
|
from mjlab.terrains import TerrainEntityCfg
|
|
from mjlab.terrains.terrain_generator import TerrainGeneratorCfg
|
|
import mjlab.terrains as terrain_gen
|
|
|
|
terrain = TerrainEntityCfg(
|
|
terrain_type="generator",
|
|
terrain_generator=TerrainGeneratorCfg(
|
|
size=(8.0, 8.0),
|
|
num_rows=10,
|
|
border_width=20.0,
|
|
curriculum=True,
|
|
sub_terrains={
|
|
"flat": terrain_gen.BoxFlatTerrainCfg(proportion=0.2),
|
|
"stairs": terrain_gen.BoxPyramidStairsTerrainCfg(
|
|
proportion=0.4,
|
|
step_height_range=(0.0, 0.15),
|
|
step_width=0.3,
|
|
platform_width=2.0,
|
|
),
|
|
"rough": terrain_gen.HfRandomUniformTerrainCfg(
|
|
proportion=0.4,
|
|
noise_range=(0.02, 0.10),
|
|
noise_step=0.02,
|
|
),
|
|
},
|
|
),
|
|
max_init_terrain_level=5,
|
|
)
|
|
|
|
The generator creates a grid of patches sized ``num_rows`` by either
|
|
``num_cols`` (random mode) or ``len(sub_terrains)`` (curriculum mode,
|
|
where ``num_cols`` is ignored). The ``sub_terrains`` dictionary maps
|
|
names to ``SubTerrainCfg`` instances; each sub-terrain's ``proportion``
|
|
controls robot spawning distribution across columns in curriculum mode,
|
|
or per-patch sampling probability in random mode.
|
|
|
|
|
|
Grid layout
|
|
^^^^^^^^^^^
|
|
|
|
Two generation modes control how terrain types are distributed across
|
|
the grid:
|
|
|
|
**Curriculum mode** (``curriculum=True``). Each terrain type gets exactly
|
|
one column; the generator uses ``len(sub_terrains)`` columns regardless of
|
|
``num_cols``. All patches in a column share the same terrain type, and
|
|
difficulty increases from row 0 (easiest) to row ``num_rows - 1``
|
|
(hardest). The ``proportion`` field controls how robots are distributed
|
|
across columns at spawn time, not column count. This structured layout
|
|
is what enables the curriculum system to advance environments to harder
|
|
rows as performance improves.
|
|
|
|
**Random mode** (``curriculum=False``). Every patch independently samples
|
|
a terrain type weighted by ``proportion`` and a difficulty from
|
|
``difficulty_range``. ``num_cols`` is honored. This provides maximum
|
|
variety but no structured difficulty progression.
|
|
|
|
|
|
The difficulty parameter
|
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Each sub-terrain's generation function receives a ``difficulty`` value
|
|
that linearly interpolates the terrain's configurable ranges. For
|
|
example, a ``BoxPyramidStairsTerrainCfg`` with
|
|
``step_height_range=(0.0, 0.2)`` produces flat ground at difficulty 0
|
|
and 20 cm steps at difficulty 1.
|
|
|
|
In curriculum mode, difficulty is determined by the row:
|
|
``difficulty = lower + (upper - lower) * row / max(num_rows - 1, 1)``,
|
|
where ``(lower, upper) = difficulty_range``. Row 0 is exactly
|
|
``lower``, row ``num_rows - 1`` is exactly ``upper``, and intermediate
|
|
rows are evenly spaced between them. All columns in a given row share
|
|
the same difficulty scalar; the visible variation across columns comes
|
|
from each sub-terrain type generating different geometry at the same
|
|
difficulty.
|
|
|
|
.. note::
|
|
|
|
With ``num_rows=1`` and ``curriculum=True``, every patch is generated
|
|
at ``difficulty = lower`` (the easiest configured difficulty). Use
|
|
``curriculum=False`` if you want a single grid of randomly sampled
|
|
difficulties instead.
|
|
|
|
In random mode, difficulty is sampled uniformly from
|
|
``difficulty_range`` independently for every patch.
|
|
|
|
|
|
Sub-terrain types
|
|
-----------------
|
|
|
|
mjlab provides two families of sub-terrain types: **primitive terrains**
|
|
built from box geoms, and **heightfield terrains** built from continuous
|
|
elevation grids. All types inherit from ``SubTerrainCfg`` and accept a
|
|
``proportion`` weight and optional ``flat_patch_sampling`` configuration.
|
|
|
|
|
|
Primitive terrains
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
Procedural patches built entirely from box geoms. The discrete geometry
|
|
makes them well suited for staircases, stepping stones, and other
|
|
structured obstacles. Most primitive types share common parameters:
|
|
``platform_width`` (central flat area), ``border_width`` (flat margin),
|
|
and one or more difficulty-scaled ranges.
|
|
|
|
.. grid:: 3
|
|
|
|
.. grid-item-card:: Flat
|
|
|
|
.. image:: _static/terrains/box_flat.png
|
|
|
|
Flat box patch. Useful as an easy baseline in a curriculum grid.
|
|
|
|
.. grid-item-card:: Pyramid Stairs
|
|
|
|
.. image:: _static/terrains/box_pyramid_stairs.png
|
|
|
|
Pyramid staircase with steps descending inward toward a central
|
|
platform.
|
|
|
|
.. grid-item-card:: Inverted Pyramid Stairs
|
|
|
|
.. image:: _static/terrains/box_inverted_pyramid_stairs.png
|
|
|
|
Inverted pyramid with steps ascending from the outside inward.
|
|
|
|
.. grid-item-card:: Random Stairs
|
|
|
|
.. image:: _static/terrains/box_random_stairs.png
|
|
|
|
Pyramid staircase with random per-step heights.
|
|
|
|
.. grid-item-card:: Open Stairs
|
|
|
|
.. image:: _static/terrains/box_open_stairs.png
|
|
|
|
Concentric step rings. Can be a bowl or pyramid depending on the
|
|
``inverted`` flag.
|
|
|
|
.. grid-item-card:: Random Grid
|
|
|
|
.. image:: _static/terrains/box_random_grid.png
|
|
|
|
Grid of boxes at randomly sampled heights.
|
|
|
|
.. grid-item-card:: Random Spread
|
|
|
|
.. image:: _static/terrains/box_random_spread.png
|
|
|
|
Randomly positioned and rotated boxes of varying sizes scattered
|
|
across the patch.
|
|
|
|
.. grid-item-card:: Stepping Stones
|
|
|
|
.. image:: _static/terrains/box_stepping_stones.png
|
|
|
|
Stepping-stone columns rising from a deep pit.
|
|
|
|
.. grid-item-card:: Narrow Beams
|
|
|
|
.. image:: _static/terrains/box_narrow_beams.png
|
|
|
|
Radial beams extending outward from a central platform above a
|
|
pit.
|
|
|
|
.. grid-item-card:: Tilted Grid
|
|
|
|
.. image:: _static/terrains/box_tilted_grid.png
|
|
|
|
Grid of independently tilted mesh tiles.
|
|
|
|
.. grid-item-card:: Nested Rings
|
|
|
|
.. image:: _static/terrains/box_nested_rings.png
|
|
|
|
Concentric ring structures at random heights.
|
|
|
|
|
|
Heightfield terrains
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Continuous terrain profiles built from MuJoCo heightfield geoms. The
|
|
surface is a dense grid of elevation samples, producing smooth slopes
|
|
and undulating ground that box geoms cannot represent.
|
|
|
|
.. grid:: 3
|
|
|
|
.. grid-item-card:: Pyramid Slope
|
|
|
|
.. image:: _static/terrains/hf_pyramid_slope.png
|
|
|
|
Smooth pyramid slope with a flat platform at the peak.
|
|
``inverted=True`` places the platform at the bottom.
|
|
|
|
.. grid-item-card:: Random Uniform
|
|
|
|
.. image:: _static/terrains/hf_random_uniform.png
|
|
|
|
Random uniform noise, optionally downsampled and interpolated to
|
|
control feature size.
|
|
|
|
.. grid-item-card:: Wave
|
|
|
|
.. image:: _static/terrains/hf_wave.png
|
|
|
|
Sinusoidal wave profile.
|
|
|
|
.. grid-item-card:: Discrete Obstacles
|
|
|
|
.. image:: _static/terrains/hf_discrete_obstacles.png
|
|
|
|
Rectangular bumps and pits scattered across a flat base.
|
|
|
|
.. grid-item-card:: Perlin Noise
|
|
|
|
.. image:: _static/terrains/hf_perlin_noise.png
|
|
|
|
Fractal Perlin noise producing natural terrain undulation.
|
|
|
|
|
|
Preset configurations
|
|
---------------------
|
|
|
|
mjlab ships three ready-made ``TerrainGeneratorCfg`` presets in
|
|
``mjlab.terrains.config``:
|
|
|
|
``ROUGH_TERRAINS_CFG``
|
|
A 10x20 random-mode grid with seven terrain types (flat, stairs,
|
|
inverted stairs, slopes, inverted slopes, random rough, waves).
|
|
Designed for locomotion training with a moderate difficulty range.
|
|
Set ``curriculum=True`` via ``dataclasses.replace`` to use it as a
|
|
curriculum grid (one column per terrain type).
|
|
|
|
``STAIRS_TERRAINS_CFG``
|
|
A 10-row curriculum grid focused on stair traversal: flat plus
|
|
three pyramid-stair variants of increasing difficulty.
|
|
|
|
``ALL_TERRAINS_CFG``
|
|
A 10-row random-mode grid covering all available terrain types at
|
|
equal proportion. Useful for training on maximum terrain variety.
|
|
|
|
Both can be used directly or customized with ``dataclasses.replace()``:
|
|
|
|
.. code-block:: python
|
|
|
|
from dataclasses import replace
|
|
from mjlab.terrains.config import ROUGH_TERRAINS_CFG
|
|
|
|
my_terrains = replace(ROUGH_TERRAINS_CFG, num_rows=5)
|
|
|
|
|
|
Terrain curriculum
|
|
------------------
|
|
|
|
In curriculum mode the terrain grid provides a natural axis for
|
|
progressive training: rows represent difficulty levels, and the
|
|
curriculum system moves environments up or down the grid based on
|
|
performance. See :ref:`curriculum` for full details on configuring
|
|
curriculum terms.
|
|
|
|
The key concepts:
|
|
|
|
- Each environment tracks a ``terrain_level`` (row index) and
|
|
``terrain_type`` (column index).
|
|
- ``TerrainEntityCfg.max_init_terrain_level`` controls how high
|
|
environments can start at their first reset. Setting it to 5 means
|
|
environments begin on rows 0 through 5.
|
|
- The built-in ``terrain_levels_vel`` curriculum term promotes
|
|
environments that track commanded velocity well and demotes
|
|
environments that fall or fail to make progress.
|
|
- When an environment is promoted past the hardest row, it is randomly
|
|
reassigned to any row in ``[0, num_rows)`` to prevent the policy from
|
|
collapsing to a single difficulty level.
|
|
|
|
|
|
Flat patch detection
|
|
--------------------
|
|
|
|
Heightfield terrains can pre-compute flat regions on their surface during
|
|
generation. These flat patches are useful as safe spawn points for tasks
|
|
that require the robot to start on level ground, even on otherwise rough
|
|
terrain.
|
|
|
|
Flat patch detection is configured per sub-terrain via the
|
|
``flat_patch_sampling`` field on ``SubTerrainCfg``:
|
|
|
|
.. code-block:: python
|
|
|
|
from mjlab.terrains.terrain_generator import FlatPatchSamplingCfg
|
|
|
|
rough = terrain_gen.HfRandomUniformTerrainCfg(
|
|
proportion=0.5,
|
|
noise_range=(0.02, 0.10),
|
|
flat_patch_sampling={
|
|
"spawn": FlatPatchSamplingCfg(
|
|
num_patches=10,
|
|
patch_radius=0.5,
|
|
max_height_diff=0.05,
|
|
),
|
|
},
|
|
)
|
|
|
|
The detection algorithm uses morphological filtering to find circular
|
|
regions where height variation stays within ``max_height_diff``. Detected
|
|
patches are accessible at runtime through
|
|
``scene.terrain.flat_patches["spawn"]``.
|
|
|
|
To spawn robots on detected patches instead of at the sub-terrain center,
|
|
use ``reset_root_state_from_flat_patches`` as the reset event term. See
|
|
:ref:`events` for details.
|
|
|
|
.. note::
|
|
|
|
Only heightfield (``Hf*``) terrains support flat patch detection.
|
|
Primitive (``Box*``) terrains do not have heightfield data to analyze.
|
|
If any sub-terrain in the grid configures ``flat_patch_sampling``,
|
|
the flat patches array is allocated for all cells; sub-terrains
|
|
without patches have their slots filled with the sub-terrain's spawn
|
|
origin so that the reset event always receives valid positions.
|
|
|
|
|
|
Debug visualization
|
|
-------------------
|
|
|
|
The terrain entity adds debug sites to three geom groups that can be
|
|
toggled in the MuJoCo native viewer or Viser viewer:
|
|
|
|
- **Group 3**: flat patch sites (yellow boxes marking safe spawn regions)
|
|
- **Group 4**: environment origin sites (green spheres at each
|
|
environment's position)
|
|
- **Group 5**: terrain origin sites (blue spheres at each sub-terrain
|
|
patch center)
|
|
|
|
.. figure:: _static/terrains/flat_patch_group.png
|
|
:width: 100%
|
|
:align: center
|
|
:alt: Flat patch visualization
|
|
|
|
Flat patches (group 3) overlaid on a procedural terrain grid in the
|
|
Viser viewer.
|