From Workshop Prototype to Reusable Research Infrastructure
2026-07-13
Studying trust and workload needs a task you can control — and repeat.
Real disasters aren’t reproducible. Field studies can’t isolate one variable at a time, and they definitely can’t be replayed frame-by-frame in analysis.
We needed a SAR task that was hard enough to matter, controllable enough to manipulate, and instrumented enough to measure.
So we built Rescue-Grid.

Everything from Part 1 is a config parameter or a log field here.
build_sar_env() argumentsPart 1 asked what to measure. Rescue-Grid is where you measure it.
A building on fire. Real victims. Fake ones too.
Built on MiniGrid + Gymnasium — so it’s RL-ready from day one.
It’s a standard Gymnasium environment underneath.
reset() / step() / render() — nothing exotic. Drop in your own policy, or drive it by hand.
If you know Gymnasium, you already know Rescue-Grid.
from game.sar.env import build_sar_env
env = build_sar_env(
screen_size=800,
num_rows=2, num_cols=2,
num_real_victims=3,
num_fake_victims=3,
lava_per_room=2,
)
obs, info = env.reset(seed=42)
for _ in range(200):
action = env.action_space.sample()
obs, reward, terminated, truncated, info = env.step(action)
if terminated or truncated:
obs, info = env.reset()Every frame follows the same path — input to pixels.
build_sar_env() assembles a fully configured mission from a few parametersSARLevelGen defines level-gen hooks; subclass it for a new level typeVictimPlacer / LavaPlacer swap placement logic without touching the engineChange the scenario, not the source code.
ixp Talk to Each OtherTwo independent streams. One shared clock.
replay.py
ixp?Behavioral experiments have a shape: setup, tasks, sensors, teardown.
ixp is iHuman Lab’s experiment engine — an Experiment runs a sequence of Tasks, each broken into Blocks of Trials, predefined or randomized order.
Sensors record in parallel with tasks via Ray, and everything streams to a synchronized LSL clock — no manual timestamp alignment.
Rescue-Grid didn’t reinvent this — it just registered as a Task.
ixpixp orchestrates the session — Rescue-Grid just plugs in.
ixp.Experiment runs an ordered sequence of Tasks, calibrates sensors, and drives everything to completion. Rescue-Grid supplies one Task (SARGame) whose trials stream to their own LSL outlet.
Your sensor could be the next one registered.
class SARGame(Task):
def get_data_signature(self):
return {
"name": "SARGame",
"type": "GameState",
"channel_format": "string",
"source_id": "rescue-grid-sar-game",
}
class SARGameTrial(LSLTrial):
def read_data(self):
state = {**self.gui.user.obs,
"action": self.gui.user.last_action,
"reward": self.gui.user.last_reward}
return [ujson.dumps(state)]Two entry points, depending on how deep you want to go.
Just the environment — for a scripted study or RL training, no ixp required.
Full experiment — wire in your own sensor (EEG, GSR, whatever you’re measuring) exactly the way Tobii is wired in today.
# (a) minimal — no ixp, just Gymnasium
from game.sar.env import build_sar_env
env = build_sar_env(num_rows=3, num_cols=3)
obs, info = env.reset()
# plug in your own policy or logging here
# (b) full ixp experiment
from ixp.experiment import Experiment
from experiment.game import SARGame
experiment = Experiment(config)
experiment.register_sensor(
"MyEEG", sensor_cls=MyEEGSensor, sensor_config={}
)
experiment.add_task(
name="main_game", task_cls=SARGame,
task_config={"config": config["game"]}, order=1,
)
experiment.run()LLM guidance changed where people looked — not just how well they did.
IEEE SMC 2026 — Oveisi & Manjunatha

Same platform, a different question — see you at the session.

Fork It. Build Your Study.
github.com/iHuman-Lab/rescue-grid
Questions?
hemanth.manjunatha@okstate.edu

iHuman Lab · Oklahoma State University