Skip to content

task_layout

task_layout

Task layout metadata for synthetic benchmark visualization and rendering.

SyntheticTaskLayout dataclass

SyntheticTaskLayout(start, goals, obstacles, num_modes)

Task-specific layout data for rendering and visualization.

Attributes:

Name Type Description
start ndarray

Start position in [0, 1]x[0, 1] Cartesian space. Shape (2,).

goals ndarray | None

Expert goal positions used during data generation, shape (num_goals, 2), or None for tasks with no fixed goal.

obstacles list[tuple[float, float, float, float]]

List of (x_min, y_min, x_max, y_max) rectangles.

num_modes int

Number of behavioral modes for this task.

get_task_layout

get_task_layout(task_name, num_modes=None, num_styles=None, noise_std=MULTIPATH_DEFAULT_NOISE_STD)

Return the layout data (start, goal, obstacles, num_modes) for a task.

For radial and corridor tasks, obstacles depend on the number of modes and are generated dynamically.

Parameters:

Name Type Description Default
task_name str

SyntheticTaskName.value string.

required
num_modes int | None

Number of modes for tasks with variable mode count (radial, corridor_navigation). Uses task defaults when None.

None
num_styles int | None

Number of styles per corridor for corridor_navigation. Uses task default when None.

None
noise_std float

Trajectory noise std. Passed to obstacle sizing so a 3-sigma noise margin is kept between trajectory and obstacle.

MULTIPATH_DEFAULT_NOISE_STD

Returns:

Type Description
SyntheticTaskLayout

SyntheticTaskLayout with the task-specific geometry.

Raises:

Type Description
ValueError

If task_name is not a recognized synthetic task.

Source code in src/versatil/data/synthetic/task_layout.py
def get_task_layout(
    task_name: str,
    num_modes: int | None = None,
    num_styles: int | None = None,
    noise_std: float = MULTIPATH_DEFAULT_NOISE_STD,
) -> SyntheticTaskLayout:
    """Return the layout data (start, goal, obstacles, num_modes) for a task.

    For radial and corridor tasks, obstacles depend on the number of modes
    and are generated dynamically.

    Args:
        task_name: SyntheticTaskName.value string.
        num_modes: Number of modes for tasks with variable mode count
            (radial, corridor_navigation). Uses task defaults when None.
        num_styles: Number of styles per corridor for corridor_navigation.
            Uses task default when None.
        noise_std: Trajectory noise std. Passed to obstacle sizing so a
            3-sigma noise margin is kept between trajectory and obstacle.

    Returns:
        SyntheticTaskLayout with the task-specific geometry.

    Raises:
        ValueError: If task_name is not a recognized synthetic task.
    """
    match task_name:
        case SyntheticTaskName.CIRCLE.value:
            return SyntheticTaskLayout(
                start=CIRCLE_START,
                goals=None,
                obstacles=CIRCLE_OBSTACLES,
                num_modes=CIRCLE_DEFAULT_NUM_MODES,
            )
        case SyntheticTaskName.CONDITIONAL_CIRCLE.value:
            return SyntheticTaskLayout(
                start=CIRCLE_START,
                goals=None,
                obstacles=CIRCLE_OBSTACLES,
                num_modes=CIRCLE_DEFAULT_NUM_MODES,
            )
        case SyntheticTaskName.SEQUENTIAL_DECISION.value:
            return SyntheticTaskLayout(
                start=SEQUENTIAL_START,
                goals=_compute_sequential_goals(),
                obstacles=SEQUENTIAL_OBSTACLES,
                num_modes=SEQUENTIAL_NUM_COMPOUND_MODES,
            )
        case SyntheticTaskName.RADIAL.value:
            resolved_modes = (
                num_modes if num_modes is not None else RADIAL_DEFAULT_NUM_MODES
            )
            return SyntheticTaskLayout(
                start=RADIAL_CENTER,
                goals=_compute_radial_goals(num_modes=resolved_modes),
                obstacles=_generate_radial_obstacles(
                    num_modes=resolved_modes, noise_std=noise_std
                ),
                num_modes=resolved_modes,
            )
        case SyntheticTaskName.CORRIDOR_NAVIGATION.value:
            resolved_modes = (
                num_modes if num_modes is not None else CORRIDOR_DEFAULT_NUM_MODES
            )
            resolved_styles = (
                num_styles if num_styles is not None else CORRIDOR_DEFAULT_NUM_STYLES
            )
            gap_centers = _compute_corridor_gap_centers(num_gaps=resolved_modes)
            return SyntheticTaskLayout(
                start=CORRIDOR_START,
                goals=CORRIDOR_GOAL[np.newaxis, :].astype(np.float32),
                obstacles=_generate_corridor_obstacles(gap_centers=gap_centers),
                num_modes=resolved_modes * resolved_styles,
            )
        case _:
            raise ValueError(f"Unknown synthetic task: {task_name}")