Spaces:
Running
Running
File size: 3,780 Bytes
1e49495 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | """
Task pool and curriculum for the origami RL environment.
7 tasks across 4 difficulty levels.
"""
from __future__ import annotations
import random
from typing import Optional
TASKS: dict[str, dict] = {
"half_fold": {
"name": "half_fold",
"description": "Fold a 1x1 paper sheet in half along the horizontal midline.",
"width": 1.0,
"height": 1.0,
"material": "paper",
"target_ratio": 0.50,
"max_folds": 3,
"target_box": [1.0, 0.5, 0.02],
"must_deploy": False,
"difficulty": 1,
},
"quarter_fold": {
"name": "quarter_fold",
"description": "Fold a 1x1 paper sheet into quarters using two perpendicular folds.",
"width": 1.0,
"height": 1.0,
"material": "paper",
"target_ratio": 0.25,
"max_folds": 5,
"target_box": [0.5, 0.5, 0.04],
"must_deploy": False,
"difficulty": 1,
},
"letter_fold": {
"name": "letter_fold",
"description": "Fold a 1x1 paper into thirds (letter fold) using two parallel folds.",
"width": 1.0,
"height": 1.0,
"material": "paper",
"target_ratio": 0.33,
"max_folds": 5,
"target_box": [1.0, 0.34, 0.03],
"must_deploy": False,
"difficulty": 2,
},
"map_fold": {
"name": "map_fold",
"description": "Fold a 1x1 paper into eighths using a grid fold pattern. Must be re-deployable.",
"width": 1.0,
"height": 1.0,
"material": "paper",
"target_ratio": 0.125,
"max_folds": 8,
"target_box": [0.5, 0.25, 0.08],
"must_deploy": True,
"difficulty": 2,
},
"solar_panel": {
"name": "solar_panel",
"description": "Pack a 1x1 Mylar solar panel into a compact configuration using a Miura-ori style fold. Must deploy.",
"width": 1.0,
"height": 1.0,
"material": "mylar",
"target_ratio": 0.05,
"max_folds": 20,
"target_box": [0.25, 0.25, 0.05],
"must_deploy": True,
"difficulty": 3,
},
"shelter_wall": {
"name": "shelter_wall",
"description": "Fold a 1x1 aluminum sheet into a compact structural panel within strain limits.",
"width": 1.0,
"height": 1.0,
"material": "aluminum",
"target_ratio": 0.10,
"max_folds": 15,
"target_box": [0.5, 0.25, 0.1],
"must_deploy": False,
"difficulty": 3,
},
"stent": {
"name": "stent",
"description": "Fold a 0.5x1.5 nitinol sheet into a compact tube configuration for a medical stent. Superelastic material.",
"width": 0.5,
"height": 1.5,
"material": "nitinol",
"target_ratio": 0.09,
"max_folds": 25,
"target_box": [0.1, 0.1, 0.15],
"must_deploy": True,
"difficulty": 4,
},
}
def get_task_by_name(name: str) -> Optional[dict]:
"""Return task dict by name, or None if not found."""
return TASKS.get(name)
def sample_task(seed: Optional[int] = None, difficulty: Optional[int] = None) -> dict:
"""Sample a random task, optionally filtered by difficulty level."""
rng = random.Random(seed)
pool = list(TASKS.values())
if difficulty is not None:
pool = [t for t in pool if t["difficulty"] == difficulty]
if not pool:
pool = list(TASKS.values())
return dict(rng.choice(pool))
def get_tasks_by_difficulty(level: int) -> list[dict]:
"""Return all tasks at a given difficulty level."""
return [dict(t) for t in TASKS.values() if t["difficulty"] == level]
def available_task_names() -> list[str]:
"""Return sorted list of all task names."""
return sorted(TASKS.keys())
|