Skip to content

generators

generators

Trajectory generators for synthetic multimodal benchmark tasks.

Each task produces episodes with controlled multimodality in [0, 1]x[0, 1] Cartesian space. Actions are fixed delta positions: action[t] = position[t+1] - position[t].

generate_task_episodes

generate_task_episodes(task_name=value, num_episodes=DEFAULT_NUM_EPISODES, seed=DEFAULT_SEED, image_size=DEFAULT_IMAGE_SIZE, num_modes=MULTIPATH_DEFAULT_NUM_MODES, trajectory_length=MULTIPATH_DEFAULT_TRAJECTORY_LENGTH, noise_std=MULTIPATH_DEFAULT_NOISE_STD, num_styles=CORRIDOR_DEFAULT_NUM_STYLES, mode_weights=None)

Generate synthetic episodes for a given task.

Parameters:

Name Type Description Default
task_name str

SyntheticTaskName.value string identifying which multimodal navigation task to generate.

value
num_episodes int

Total number of episodes to generate, balanced equally across all behavioral modes.

DEFAULT_NUM_EPISODES
seed int

Random seed for reproducible generation.

DEFAULT_SEED
image_size int

Side length in pixels of the rendered top-down RGB images (square).

DEFAULT_IMAGE_SIZE
num_modes int

Number of distinct behavioral modes for tasks that accept a variable mode count (radial, corridor_navigation).

MULTIPATH_DEFAULT_NUM_MODES
trajectory_length int

Number of timesteps per episode.

MULTIPATH_DEFAULT_TRAJECTORY_LENGTH
noise_std float

Standard deviation of Gaussian noise added to trajectory positions for intra-mode variance.

MULTIPATH_DEFAULT_NOISE_STD
num_styles int

Number of sinusoidal trajectory styles per corridor (corridor_navigation task only).

CORRIDOR_DEFAULT_NUM_STYLES
mode_weights list[float] | None

Relative weights per mode for imbalanced generation. None for uniform distribution across modes.

None

Returns:

Type Description
list[dict[str, ndarray]]

List of episode dicts. Each dict contains: "image": rendered top-down RGB, shape (T, image_size, image_size, 3), uint8 "position": Cartesian (x, y) states, shape (T, 2), float32 "action": delta (dx, dy) commands, shape (T, 2), float32 "mode_id": ground-truth mode label, shape (T, 1), uint8 "context": conditioning context vector, shape (T, C), float32

Source code in src/versatil/data/synthetic/generators.py
def generate_task_episodes(
    task_name: str = SyntheticTaskName.CIRCLE.value,
    num_episodes: int = DEFAULT_NUM_EPISODES,
    seed: int = DEFAULT_SEED,
    image_size: int = DEFAULT_IMAGE_SIZE,
    num_modes: int = MULTIPATH_DEFAULT_NUM_MODES,
    trajectory_length: int = MULTIPATH_DEFAULT_TRAJECTORY_LENGTH,
    noise_std: float = MULTIPATH_DEFAULT_NOISE_STD,
    num_styles: int = CORRIDOR_DEFAULT_NUM_STYLES,
    mode_weights: list[float] | None = None,
) -> list[dict[str, np.ndarray]]:
    """Generate synthetic episodes for a given task.

    Args:
        task_name: SyntheticTaskName.value string identifying which
            multimodal navigation task to generate.
        num_episodes: Total number of episodes to generate, balanced
            equally across all behavioral modes.
        seed: Random seed for reproducible generation.
        image_size: Side length in pixels of the rendered top-down RGB
            images (square).
        num_modes: Number of distinct behavioral modes for tasks that
            accept a variable mode count (radial, corridor_navigation).
        trajectory_length: Number of timesteps per episode.
        noise_std: Standard deviation of Gaussian noise added to
            trajectory positions for intra-mode variance.
        num_styles: Number of sinusoidal trajectory styles per corridor
            (corridor_navigation task only).
        mode_weights: Relative weights per mode for imbalanced generation.
            None for uniform distribution across modes.

    Returns:
        List of episode dicts. Each dict contains:
            "image": rendered top-down RGB, shape (T, image_size, image_size, 3), uint8
            "position": Cartesian (x, y) states, shape (T, 2), float32
            "action": delta (dx, dy) commands, shape (T, 2), float32
            "mode_id": ground-truth mode label, shape (T, 1), uint8
            "context": conditioning context vector, shape (T, C), float32
    """
    random_generator = np.random.default_rng(seed)
    match task_name:
        case SyntheticTaskName.CIRCLE.value:
            return _generate_circle(
                num_episodes=num_episodes,
                random_generator=random_generator,
                image_size=image_size,
                trajectory_length=trajectory_length,
                noise_std=noise_std,
                mode_weights=mode_weights,
            )
        case SyntheticTaskName.CONDITIONAL_CIRCLE.value:
            return _generate_conditional_circle(
                num_episodes=num_episodes,
                random_generator=random_generator,
                image_size=image_size,
                trajectory_length=trajectory_length,
                noise_std=noise_std,
                mode_weights=mode_weights,
            )
        case SyntheticTaskName.SEQUENTIAL_DECISION.value:
            return _generate_sequential_decision(
                num_episodes=num_episodes,
                random_generator=random_generator,
                image_size=image_size,
                trajectory_length=trajectory_length,
                noise_std=noise_std,
                mode_weights=mode_weights,
            )
        case SyntheticTaskName.RADIAL.value:
            return _generate_radial(
                num_episodes=num_episodes,
                random_generator=random_generator,
                image_size=image_size,
                num_modes=num_modes,
                trajectory_length=trajectory_length,
                noise_std=noise_std,
                mode_weights=mode_weights,
            )
        case SyntheticTaskName.CORRIDOR_NAVIGATION.value:
            return _generate_corridor_navigation(
                num_episodes=num_episodes,
                random_generator=random_generator,
                image_size=image_size,
                num_modes=num_modes,
                num_styles=num_styles,
                trajectory_length=trajectory_length,
                noise_std=noise_std,
                mode_weights=mode_weights,
            )
        case _:
            raise ValueError(f"Unknown synthetic task: {task_name}")