OpenEnv RL environment for origami folding. Add one crease at a time, get per-step geometry rewards, build up to the target shape.
Multi-step episodes: each crease is scored immediately for progress, flat-foldability (Kawasaki, Maekawa, BLB), and economy. Complete within max_folds to unlock a 10× bonus.
How It Works
1
Reset
Pick a task → get empty paper + anchor points
2
Add Crease
Submit {"from":[x,y], "to":[x,y], "assignment":"M"|"V"}
3
Per-step Reward
Progress + geometry theorems scored after every crease
4
Complete
Finish within max_folds to unlock 10× completion bonus
Action
from
[x, y]
Start point — must be a listed anchor pointrequired
to
[x, y]
End point — must be a listed anchor pointrequired
assignment
"M" | "V"
Mountain or valley foldrequired
Reward Breakdown
progress
0–1
Fraction of target creases geometrically covered
delta
0–1
Coverage improvement from this step alone
kawasaki
0–1
Flat-foldability: alternating sector angles sum to 180°
maekawa
0–1
Flat-foldability: |M−V| = 2 at interior vertices
blb
0–1
Big-Little-Big lemma compliance
economy
0–1
Penalty for excess creases
completion
0 | 10
Bonus when progress > 0.9 and geometry valid
API Reference
WebSocket
WS
/ws
Persistent connection
Send: Reset
{"type": "reset", "data": {"task_name": "triangle"}}
Send: Step
{"type": "step", "data": {"fold_data": {...}}}
Receive: Observation
{"type": "observation", "data": {"reward": 20.0, "done": true, ...}}
REST
POST
/sessions
Create session
POST
/sessions/{id}/reset
Reset with task_name
POST
/sessions/{id}/step
Submit fold action
GET
/tasks
List all tasks
GET
/tasks/{name}
Task detail + target fold
Quick Start
import requests
SERVER = "http://localhost:8000"
# Create session + reset
sid = requests.post(f"{SERVER}/sessions").json()["session_id"]
obs = requests.post(f"{SERVER}/sessions/{sid}/reset",
json={"task_name": "triangle"}).json()["observation"]
print("anchor points:", obs["anchor_points"])
# Add creases one at a time
creases = [
{"from": [0, 0], "to": [1, 1], "assignment": "V"},
]
for crease in creases:
result = requests.post(f"{SERVER}/sessions/{sid}/step",
json={"crease": crease}).json()["observation"]
print(f"step {result['step_count']}: reward={result['reward']:.3f}")
print(f" breakdown: {result['reward_breakdown']}")
if result["done"]:
print("Episode complete!")
break