mjlab.terrains

Contents

mjlab.terrains#

Terrain generation and importing.

Classes:

HfDiscreteObstaclesTerrainCfg

HfDiscreteObstaclesTerrainCfg(proportion: 'float' = 1.0, size: 'tuple[float, float]' = (10.0, 10.0), flat_patch_sampling: 'dict[str, FlatPatchSamplingCfg] | None' = None, *, obstacle_height_mode: Literal['choice', 'fixed'] = 'choice', obstacle_width_range: tuple[float, float], obstacle_height_range: tuple[float, float], num_obstacles: int, platform_width: float = 1.0, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0, border_width: float = 0.0, square_obstacles: bool = False, origin_z_offset: float = 0.0)

HfPyramidSlopedTerrainCfg

HfPyramidSlopedTerrainCfg(proportion: 'float' = 1.0, size: 'tuple[float, float]' = (10.0, 10.0), flat_patch_sampling: 'dict[str, FlatPatchSamplingCfg] | None' = None, *, slope_range: tuple[float, float], platform_width: float = 1.0, inverted: bool = False, border_width: float = 0.0, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0)

HfRandomUniformTerrainCfg

HfRandomUniformTerrainCfg(proportion: 'float' = 1.0, size: 'tuple[float, float]' = (10.0, 10.0), flat_patch_sampling: 'dict[str, FlatPatchSamplingCfg] | None' = None, *, noise_range: tuple[float, float], noise_step: float = 0.005, downsampled_scale: float | None = None, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0, border_width: float = 0.0)

HfWaveTerrainCfg

HfWaveTerrainCfg(proportion: 'float' = 1.0, size: 'tuple[float, float]' = (10.0, 10.0), flat_patch_sampling: 'dict[str, FlatPatchSamplingCfg] | None' = None, *, amplitude_range: tuple[float, float], num_waves: int = 1, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 0.25, border_width: float = 0.0)

BoxFlatTerrainCfg

BoxFlatTerrainCfg(proportion: 'float' = 1.0, size: 'tuple[float, float]' = (10.0, 10.0), flat_patch_sampling: 'dict[str, FlatPatchSamplingCfg] | None' = None)

BoxInvertedPyramidStairsTerrainCfg

BoxInvertedPyramidStairsTerrainCfg(proportion: 'float' = 1.0, size: 'tuple[float, float]' = (10.0, 10.0), flat_patch_sampling: 'dict[str, FlatPatchSamplingCfg] | None' = None, *, border_width: 'float' = 0.0, step_height_range: 'tuple[float, float]', step_width: 'float', platform_width: 'float' = 1.0, holes: 'bool' = False)

BoxPyramidStairsTerrainCfg

Configuration for a pyramid stairs terrain.

BoxRandomGridTerrainCfg

BoxRandomGridTerrainCfg(proportion: 'float' = 1.0, size: 'tuple[float, float]' = (10.0, 10.0), flat_patch_sampling: 'dict[str, FlatPatchSamplingCfg] | None' = None, *, grid_width: 'float', grid_height_range: 'tuple[float, float]', platform_width: 'float' = 1.0, holes: 'bool' = False, merge_similar_heights: 'bool' = False, height_merge_threshold: 'float' = 0.05, max_merge_distance: 'int' = 3)

FlatPatchSamplingCfg

Configuration for sampling flat patches on a heightfield surface.

SubTerrainCfg

SubTerrainCfg(proportion: 'float' = 1.0, size: 'tuple[float, float]' = (10.0, 10.0), flat_patch_sampling: 'dict[str, FlatPatchSamplingCfg] | None' = None)

TerrainGenerator

Generates procedural terrain grids with configurable difficulty.

TerrainGeneratorCfg

TerrainGeneratorCfg(*, seed: 'int | None' = None, curriculum: 'bool' = False, size: 'tuple[float, float]', border_width: 'float' = 0.0, border_height: 'float' = 1.0, num_rows: 'int' = 1, num_cols: 'int' = 1, color_scheme: "Literal['height', 'random', 'none']" = 'height', sub_terrains: 'dict[str, SubTerrainCfg]' = <factory>, difficulty_range: 'tuple[float, float]' = (0.0, 1.0), add_lights: 'bool' = False)

TerrainImporter

Builds a MuJoCo spec with terrain geometry and maps environments to spawn origins.

TerrainImporterCfg

Configuration for terrain import and environment placement.

class mjlab.terrains.HfDiscreteObstaclesTerrainCfg[source]#

Bases: SubTerrainCfg

HfDiscreteObstaclesTerrainCfg(proportion: ‘float’ = 1.0, size: ‘tuple[float, float]’ = (10.0, 10.0), flat_patch_sampling: ‘dict[str, FlatPatchSamplingCfg] | None’ = None, *, obstacle_height_mode: Literal[‘choice’, ‘fixed’] = ‘choice’, obstacle_width_range: tuple[float, float], obstacle_height_range: tuple[float, float], num_obstacles: int, platform_width: float = 1.0, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0, border_width: float = 0.0, square_obstacles: bool = False, origin_z_offset: float = 0.0)

Methods:

__init__([proportion, size, ...])

function(difficulty, spec, rng)

Generate terrain geometry.

Attributes:

obstacle_height_mode

How obstacle heights are chosen.

obstacle_width_range

Min and max obstacle width, in meters.

obstacle_height_range

Min and max obstacle height, in meters.

num_obstacles

Number of obstacles to place on the terrain.

platform_width

Side length of the obstacle-free flat square at the terrain center, in meters.

horizontal_scale

Heightfield grid resolution along x and y, in meters per cell.

vertical_scale

Heightfield height resolution, in meters per integer unit of the noise array.

base_thickness_ratio

Ratio of the heightfield base thickness to its maximum surface height.

border_width

Width of the flat border around the terrain edges, in meters.

square_obstacles

If True, obstacles have equal width and length.

origin_z_offset

Vertical offset added to spawn origin height (meters).

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None, *, obstacle_height_mode: Literal['choice', 'fixed'] = 'choice', obstacle_width_range: tuple[float, float], obstacle_height_range: tuple[float, float], num_obstacles: int, platform_width: float = 1.0, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0, border_width: float = 0.0, square_obstacles: bool = False, origin_z_offset: float = 0.0) None#
obstacle_height_mode: Literal['choice', 'fixed'] = 'choice'#

How obstacle heights are chosen. “choice” randomly picks from [-h, -h/2, h/2, h] (mix of pits and bumps); “fixed” uses h for all obstacles.

obstacle_width_range: tuple[float, float]#

Min and max obstacle width, in meters.

obstacle_height_range: tuple[float, float]#

Min and max obstacle height, in meters. Interpolated by difficulty.

num_obstacles: int#

Number of obstacles to place on the terrain.

platform_width: float = 1.0#

Side length of the obstacle-free flat square at the terrain center, in meters.

horizontal_scale: float = 0.1#

Heightfield grid resolution along x and y, in meters per cell.

vertical_scale: float = 0.005#

Heightfield height resolution, in meters per integer unit of the noise array.

base_thickness_ratio: float = 1.0#

Ratio of the heightfield base thickness to its maximum surface height.

border_width: float = 0.0#

Width of the flat border around the terrain edges, in meters. Must be >= horizontal_scale if non-zero.

square_obstacles: bool = False#

If True, obstacles have equal width and length. If False, each dimension is sampled independently.

origin_z_offset: float = 0.0#

Vertical offset added to spawn origin height (meters).

Useful to prevent robot feet from clipping through terrain when spawning at the origin.

function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

class mjlab.terrains.HfPyramidSlopedTerrainCfg[source]#

Bases: SubTerrainCfg

HfPyramidSlopedTerrainCfg(proportion: ‘float’ = 1.0, size: ‘tuple[float, float]’ = (10.0, 10.0), flat_patch_sampling: ‘dict[str, FlatPatchSamplingCfg] | None’ = None, *, slope_range: tuple[float, float], platform_width: float = 1.0, inverted: bool = False, border_width: float = 0.0, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0)

Attributes:

slope_range

Range of slope gradients (rise / run), interpolated by difficulty.

platform_width

Side length of the flat square platform at the terrain center, in meters.

inverted

If True, the pyramid is inverted so the platform is at the bottom.

border_width

Width of the flat border around the terrain edges, in meters.

horizontal_scale

Heightfield grid resolution along x and y, in meters per cell.

vertical_scale

Heightfield height resolution, in meters per integer unit of the noise array.

base_thickness_ratio

Ratio of the heightfield base thickness to its maximum surface height.

Methods:

function(difficulty, spec, rng)

Generate terrain geometry.

__init__([proportion, size, ...])

slope_range: tuple[float, float]#

Range of slope gradients (rise / run), interpolated by difficulty.

platform_width: float = 1.0#

Side length of the flat square platform at the terrain center, in meters.

inverted: bool = False#

If True, the pyramid is inverted so the platform is at the bottom.

border_width: float = 0.0#

Width of the flat border around the terrain edges, in meters. Must be >= horizontal_scale if non-zero.

horizontal_scale: float = 0.1#

Heightfield grid resolution along x and y, in meters per cell.

vertical_scale: float = 0.005#

Heightfield height resolution, in meters per integer unit of the noise array.

base_thickness_ratio: float = 1.0#

Ratio of the heightfield base thickness to its maximum surface height.

function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None, *, slope_range: tuple[float, float], platform_width: float = 1.0, inverted: bool = False, border_width: float = 0.0, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0) None#
class mjlab.terrains.HfRandomUniformTerrainCfg[source]#

Bases: SubTerrainCfg

HfRandomUniformTerrainCfg(proportion: ‘float’ = 1.0, size: ‘tuple[float, float]’ = (10.0, 10.0), flat_patch_sampling: ‘dict[str, FlatPatchSamplingCfg] | None’ = None, *, noise_range: tuple[float, float], noise_step: float = 0.005, downsampled_scale: float | None = None, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0, border_width: float = 0.0)

Attributes:

noise_range

Min and max height noise, in meters.

noise_step

Height quantization step, in meters.

downsampled_scale

Spacing between randomly sampled height points before interpolation, in meters.

horizontal_scale

Heightfield grid resolution along x and y, in meters per cell.

vertical_scale

Heightfield height resolution, in meters per integer unit of the noise array.

base_thickness_ratio

Ratio of the heightfield base thickness to its maximum surface height.

border_width

Width of the flat border around the terrain edges, in meters.

Methods:

function(difficulty, spec, rng)

Generate terrain geometry.

__init__([proportion, size, ...])

noise_range: tuple[float, float]#

Min and max height noise, in meters.

noise_step: float = 0.005#

Height quantization step, in meters. Sampled heights are multiples of this value within noise_range.

downsampled_scale: float | None = None#

Spacing between randomly sampled height points before interpolation, in meters. If None, uses horizontal_scale. Must be >= horizontal_scale.

horizontal_scale: float = 0.1#

Heightfield grid resolution along x and y, in meters per cell.

vertical_scale: float = 0.005#

Heightfield height resolution, in meters per integer unit of the noise array.

base_thickness_ratio: float = 1.0#

Ratio of the heightfield base thickness to its maximum surface height.

border_width: float = 0.0#

Width of the flat border around the terrain edges, in meters. Must be >= horizontal_scale if non-zero.

function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None, *, noise_range: tuple[float, float], noise_step: float = 0.005, downsampled_scale: float | None = None, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 1.0, border_width: float = 0.0) None#
class mjlab.terrains.HfWaveTerrainCfg[source]#

Bases: SubTerrainCfg

HfWaveTerrainCfg(proportion: ‘float’ = 1.0, size: ‘tuple[float, float]’ = (10.0, 10.0), flat_patch_sampling: ‘dict[str, FlatPatchSamplingCfg] | None’ = None, *, amplitude_range: tuple[float, float], num_waves: int = 1, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 0.25, border_width: float = 0.0)

Attributes:

amplitude_range

Min and max wave amplitude, in meters.

num_waves

Number of complete wave cycles along the terrain length.

horizontal_scale

Heightfield grid resolution along x and y, in meters per cell.

vertical_scale

Heightfield height resolution, in meters per integer unit of the noise array.

base_thickness_ratio

Ratio of the heightfield base thickness to its maximum surface height.

border_width

Width of the flat border around the terrain edges, in meters.

Methods:

__init__([proportion, size, ...])

function(difficulty, spec, rng)

Generate terrain geometry.

amplitude_range: tuple[float, float]#

Min and max wave amplitude, in meters. Interpolated by difficulty.

num_waves: int = 1#

Number of complete wave cycles along the terrain length.

horizontal_scale: float = 0.1#

Heightfield grid resolution along x and y, in meters per cell.

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None, *, amplitude_range: tuple[float, float], num_waves: int = 1, horizontal_scale: float = 0.1, vertical_scale: float = 0.005, base_thickness_ratio: float = 0.25, border_width: float = 0.0) None#
vertical_scale: float = 0.005#

Heightfield height resolution, in meters per integer unit of the noise array.

base_thickness_ratio: float = 0.25#

Ratio of the heightfield base thickness to its maximum surface height.

border_width: float = 0.0#

Width of the flat border around the terrain edges, in meters. Must be >= horizontal_scale if non-zero.

function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

class mjlab.terrains.BoxFlatTerrainCfg[source]#

Bases: SubTerrainCfg

BoxFlatTerrainCfg(proportion: ‘float’ = 1.0, size: ‘tuple[float, float]’ = (10.0, 10.0), flat_patch_sampling: ‘dict[str, FlatPatchSamplingCfg] | None’ = None)

Methods:

function(difficulty, spec, rng)

Generate terrain geometry.

__init__([proportion, size, flat_patch_sampling])

function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None) None#
class mjlab.terrains.BoxInvertedPyramidStairsTerrainCfg[source]#

Bases: BoxPyramidStairsTerrainCfg

BoxInvertedPyramidStairsTerrainCfg(proportion: ‘float’ = 1.0, size: ‘tuple[float, float]’ = (10.0, 10.0), flat_patch_sampling: ‘dict[str, FlatPatchSamplingCfg] | None’ = None, *, border_width: ‘float’ = 0.0, step_height_range: ‘tuple[float, float]’, step_width: ‘float’, platform_width: ‘float’ = 1.0, holes: ‘bool’ = False)

Methods:

function(difficulty, spec, rng)

Generate terrain geometry.

__init__([proportion, size, ...])

function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None, *, border_width: float = 0.0, step_height_range: tuple[float, float], step_width: float, platform_width: float = 1.0, holes: bool = False) None#
class mjlab.terrains.BoxPyramidStairsTerrainCfg[source]#

Bases: SubTerrainCfg

Configuration for a pyramid stairs terrain.

Attributes:

border_width

Width of the flat border frame around the staircase, in meters.

step_height_range

Min and max step height, in meters.

step_width

Depth (run) of each step, in meters.

platform_width

Side length of the flat square platform at the top of the staircase, in meters.

holes

If True, steps form a cross pattern with empty gaps in the corners.

Methods:

function(difficulty, spec, rng)

Generate terrain geometry.

__init__([proportion, size, ...])

border_width: float = 0.0#

Width of the flat border frame around the staircase, in meters. Ignored when holes is True.

step_height_range: tuple[float, float]#

Min and max step height, in meters. Interpolated by difficulty.

step_width: float#

Depth (run) of each step, in meters.

platform_width: float = 1.0#

Side length of the flat square platform at the top of the staircase, in meters.

holes: bool = False#

If True, steps form a cross pattern with empty gaps in the corners.

function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None, *, border_width: float = 0.0, step_height_range: tuple[float, float], step_width: float, platform_width: float = 1.0, holes: bool = False) None#
class mjlab.terrains.BoxRandomGridTerrainCfg[source]#

Bases: SubTerrainCfg

BoxRandomGridTerrainCfg(proportion: ‘float’ = 1.0, size: ‘tuple[float, float]’ = (10.0, 10.0), flat_patch_sampling: ‘dict[str, FlatPatchSamplingCfg] | None’ = None, *, grid_width: ‘float’, grid_height_range: ‘tuple[float, float]’, platform_width: ‘float’ = 1.0, holes: ‘bool’ = False, merge_similar_heights: ‘bool’ = False, height_merge_threshold: ‘float’ = 0.05, max_merge_distance: ‘int’ = 3)

Attributes:

grid_width

Side length of each square grid cell, in meters.

grid_height_range

Min and max grid cell height bound, in meters.

platform_width

Side length of the flat square platform at the grid center, in meters.

holes

If True, only the cross-shaped region around the center platform has grid cells.

merge_similar_heights

If True, adjacent cells with similar heights are merged into larger boxes to reduce geom count.

height_merge_threshold

Maximum height difference between cells that can be merged, in meters.

max_merge_distance

Maximum number of grid cells that can be merged in each direction.

Methods:

__init__([proportion, size, ...])

function(difficulty, spec, rng)

Generate terrain geometry.

grid_width: float#

Side length of each square grid cell, in meters.

grid_height_range: tuple[float, float]#

Min and max grid cell height bound, in meters. Interpolated by difficulty. At a given difficulty, cell heights are sampled uniformly from [-bound, +bound].

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None, *, grid_width: float, grid_height_range: tuple[float, float], platform_width: float = 1.0, holes: bool = False, merge_similar_heights: bool = False, height_merge_threshold: float = 0.05, max_merge_distance: int = 3) None#
platform_width: float = 1.0#

Side length of the flat square platform at the grid center, in meters.

holes: bool = False#

If True, only the cross-shaped region around the center platform has grid cells.

merge_similar_heights: bool = False#

If True, adjacent cells with similar heights are merged into larger boxes to reduce geom count.

height_merge_threshold: float = 0.05#

Maximum height difference between cells that can be merged, in meters.

max_merge_distance: int = 3#

Maximum number of grid cells that can be merged in each direction.

function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

class mjlab.terrains.FlatPatchSamplingCfg[source]#

Bases: object

Configuration for sampling flat patches on a heightfield surface.

Attributes:

num_patches

Number of flat patches to sample per sub-terrain.

patch_radius

Radius of the circular footprint used to test flatness, in meters.

max_height_diff

Maximum allowed height variation within the patch footprint, in meters.

x_range

Allowed range of x coordinates for sampled patches, in meters.

y_range

Allowed range of y coordinates for sampled patches, in meters.

z_range

Allowed range of z coordinates (world height) for sampled patches, in meters.

grid_resolution

Resolution of the grid used for flat-patch detection, in meters.

Methods:

__init__([num_patches, patch_radius, ...])

num_patches: int = 10#

Number of flat patches to sample per sub-terrain.

patch_radius: float = 0.5#

Radius of the circular footprint used to test flatness, in meters.

max_height_diff: float = 0.05#

Maximum allowed height variation within the patch footprint, in meters.

x_range: tuple[float, float] = (-1000000.0, 1000000.0)#

Allowed range of x coordinates for sampled patches, in meters.

y_range: tuple[float, float] = (-1000000.0, 1000000.0)#

Allowed range of y coordinates for sampled patches, in meters.

z_range: tuple[float, float] = (-1000000.0, 1000000.0)#

Allowed range of z coordinates (world height) for sampled patches, in meters.

grid_resolution: float | None = None#

Resolution of the grid used for flat-patch detection, in meters. When None (default), the terrain’s own horizontal_scale is used. Set to a smaller value (e.g. 0.025) for finer boundary precision at the cost of a larger intermediate grid.

__init__(num_patches: int = 10, patch_radius: float = 0.5, max_height_diff: float = 0.05, x_range: tuple[float, float] = (-1000000.0, 1000000.0), y_range: tuple[float, float] = (-1000000.0, 1000000.0), z_range: tuple[float, float] = (-1000000.0, 1000000.0), grid_resolution: float | None = None) None#
class mjlab.terrains.SubTerrainCfg[source]#

Bases: ABC

SubTerrainCfg(proportion: ‘float’ = 1.0, size: ‘tuple[float, float]’ = (10.0, 10.0), flat_patch_sampling: ‘dict[str, FlatPatchSamplingCfg] | None’ = None)

Attributes:

proportion

Terrain type allocation weight (behavior depends on curriculum mode):

size

Width and length of the terrain patch, in meters.

flat_patch_sampling

Named flat-patch sampling configurations, or None to disable.

Methods:

function(difficulty, spec, rng)

Generate terrain geometry.

__init__([proportion, size, flat_patch_sampling])

proportion: float = 1.0#

Terrain type allocation weight (behavior depends on curriculum mode):

  • curriculum=True: Controls column allocation. Normalized proportions determine how many columns each terrain type occupies via cumulative distribution. Example: proportions [0.5, 0.5] with num_cols=2 gives one terrain per column.

  • curriculum=False: Sampling probability for each patch. Each patch independently samples a terrain type weighted by normalized proportions.

size: tuple[float, float] = (10.0, 10.0)#

Width and length of the terrain patch, in meters.

flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None#

Named flat-patch sampling configurations, or None to disable.

abstractmethod function(difficulty: float, spec: MjSpec, rng: Generator) TerrainOutput[source]#

Generate terrain geometry.

Returns:

TerrainOutput containing spawn origin and list of geometries.

__init__(proportion: float = 1.0, size: tuple[float, float] = (10.0, 10.0), flat_patch_sampling: dict[str, FlatPatchSamplingCfg] | None = None) None#
class mjlab.terrains.TerrainGenerator[source]#

Bases: object

Generates procedural terrain grids with configurable difficulty.

Creates a grid of terrain patches where each patch can be a different terrain type. Supports two modes:

  • Random mode (curriculum=False): Every patch independently samples a terrain type weighted by proportions. Results in random variety across all patches.

  • Curriculum mode (curriculum=True): Columns are deterministically assigned to terrain types based on proportions. All patches in a column share the same terrain type, with difficulty increasing along rows. Use this to ensure each terrain type occupies specific column(s).

Terrain types are weighted by proportion and their geometry is generated based on a difficulty value in the configured range. The grid is centered at the world origin. A border can be added around the entire grid along with optional overhead lighting.

Methods:

__init__(cfg[, device])

compile(spec)

__init__(cfg: TerrainGeneratorCfg, device: str = 'cpu') None[source]#
compile(spec: MjSpec) None[source]#
class mjlab.terrains.TerrainGeneratorCfg[source]#

Bases: object

TerrainGeneratorCfg(*, seed: ‘int | None’ = None, curriculum: ‘bool’ = False, size: ‘tuple[float, float]’, border_width: ‘float’ = 0.0, border_height: ‘float’ = 1.0, num_rows: ‘int’ = 1, num_cols: ‘int’ = 1, color_scheme: “Literal[‘height’, ‘random’, ‘none’]” = ‘height’, sub_terrains: ‘dict[str, SubTerrainCfg]’ = <factory>, difficulty_range: ‘tuple[float, float]’ = (0.0, 1.0), add_lights: ‘bool’ = False)

Attributes:

seed

Random seed for terrain generation.

curriculum

Controls terrain allocation mode:

size

Width and length of each sub-terrain patch, in meters.

border_width

Width of the flat border around the entire terrain grid, in meters.

border_height

Height of the border wall around the terrain grid, in meters.

num_rows

Number of sub-terrain rows in the grid.

num_cols

Number of sub-terrain columns in the grid.

color_scheme

Coloring strategy for terrain geometry.

sub_terrains

Named sub-terrain configurations to populate the grid.

difficulty_range

Min and max difficulty values used when generating sub-terrains.

add_lights

If True, adds a directional light above the terrain grid.

Methods:

__init__(*[, seed, curriculum, ...])

seed: int | None = None#

Random seed for terrain generation. None uses a random seed.

curriculum: bool = False#

Controls terrain allocation mode:

  • curriculum=True: Each column gets ONE terrain type (deterministic allocation). Difficulty increases along rows. Use this to ensure each terrain type occupies its own column(s).

  • curriculum=False: Every patch is randomly sampled from all terrain types. Proportions control sampling probability. Use this for random variety.

Example: With 2 terrain types and num_cols=2, curriculum=True gives one terrain per column. curriculum=False gives a random mix of both types in all patches.

size: tuple[float, float]#

Width and length of each sub-terrain patch, in meters.

border_width: float = 0.0#

Width of the flat border around the entire terrain grid, in meters.

border_height: float = 1.0#

Height of the border wall around the terrain grid, in meters.

__init__(*, seed: int | None = None, curriculum: bool = False, size: tuple[float, float], border_width: float = 0.0, border_height: float = 1.0, num_rows: int = 1, num_cols: int = 1, color_scheme: ~typing.Literal['height', 'random', 'none'] = 'height', sub_terrains: dict[str, ~mjlab.terrains.terrain_generator.SubTerrainCfg] = <factory>, difficulty_range: tuple[float, float] = (0.0, 1.0), add_lights: bool = False) None#
num_rows: int = 1#

Number of sub-terrain rows in the grid. Represents difficulty levels in curriculum mode. Note: Environments are randomly assigned to rows, so multiple envs can share the same patch.

num_cols: int = 1#

Number of sub-terrain columns in the grid. Represents terrain type variants. Note: Environments are evenly distributed across columns (not random).

color_scheme: Literal['height', 'random', 'none'] = 'height'#

Coloring strategy for terrain geometry. “height” colors by elevation, “random” assigns random colors, “none” uses uniform gray.

sub_terrains: dict[str, SubTerrainCfg]#

Named sub-terrain configurations to populate the grid.

difficulty_range: tuple[float, float] = (0.0, 1.0)#

Min and max difficulty values used when generating sub-terrains.

add_lights: bool = False#

If True, adds a directional light above the terrain grid.

class mjlab.terrains.TerrainImporter[source]#

Bases: object

Builds a MuJoCo spec with terrain geometry and maps environments to spawn origins.

The terrain is a grid of sub-terrain patches (num_rows x num_cols), each with a spawn origin. When num_envs exceeds the number of patches, environment origins are sampled from the sub-terrain origins.

Note

Environment allocation for procedural terrain: Columns (terrain types) are evenly distributed across environments, but rows (difficulty levels) are randomly sampled. This means multiple environments can spawn on the same (row, col) patch, leaving others unoccupied, even when num_envs > num_patches.

See FAQ: “How does env_origins determine robot layout?”

Methods:

__init__(cfg, device)

import_ground_plane(name)

configure_env_origins([origins])

Configure the origins of the environments based on the added terrain.

update_env_origins(env_ids, move_up, move_down)

Update the environment origins based on the terrain levels.

randomize_env_origins(env_ids)

Randomize the environment origins to random sub-terrains.

Attributes:

__init__(cfg: TerrainImporterCfg, device: str) None[source]#
property spec: MjSpec#
property flat_patches: dict[str, Tensor]#
import_ground_plane(name: str) None[source]#
configure_env_origins(origins: ndarray | Tensor | None = None)[source]#

Configure the origins of the environments based on the added terrain.

update_env_origins(env_ids: Tensor, move_up: Tensor, move_down: Tensor)[source]#

Update the environment origins based on the terrain levels.

randomize_env_origins(env_ids: Tensor) None[source]#

Randomize the environment origins to random sub-terrains.

This randomizes both the terrain level (row) and terrain type (column), useful for play/evaluation mode where you want to test on varied terrains.

class mjlab.terrains.TerrainImporterCfg[source]#

Bases: object

Configuration for terrain import and environment placement.

Attributes:

terrain_type

Type of terrain to generate.

terrain_generator

Configuration for procedural terrain generation.

env_spacing

Distance between environment origins when using grid layout.

max_init_terrain_level

Maximum initial difficulty level (row index) for environment placement in curriculum mode.

num_envs

Number of parallel environments to create.

Methods:

__init__([terrain_type, terrain_generator, ...])

terrain_type: Literal['generator', 'plane'] = 'plane'#

Type of terrain to generate. “generator” uses procedural terrain with sub-terrain grid, “plane” creates a flat ground plane.

terrain_generator: TerrainGeneratorCfg | None = None#

Configuration for procedural terrain generation. Required when terrain_type is “generator”.

env_spacing: float | None = 2.0#

Distance between environment origins when using grid layout. Required for “plane” terrain or when no sub-terrain origins exist.

max_init_terrain_level: int | None = None#

Maximum initial difficulty level (row index) for environment placement in curriculum mode. None uses all available rows.

num_envs: int = 1#

Number of parallel environments to create. This will get overridden by the scene configuration if specified there.

__init__(terrain_type: Literal['generator', 'plane'] = 'plane', terrain_generator: TerrainGeneratorCfg | None = None, env_spacing: float | None = 2.0, max_init_terrain_level: int | None = None, num_envs: int = 1) None#