Indoor Exploration Competition
13 Aug: Optional Feedback Submission and Preliminary Rankings27 Aug: Final Submission3 Sept: Competition Results ReleasedAll deadlines are at 23:59 AoE (Anywhere on Earth)
Competition GitHub RepoOverview
Multi-robot (and single-robot) indoor exploration and relaying under communication constraints. Robots explore an unknown environment using only local sensing and limited peer-to-peer communication, and must get what they've learned back to a fixed base station. What you write is the policy - exploration strategy, and optionally relay strategy too. Everything else (sensing, motion, communication, the environment) is provided and identical for every submission.
Tracks
Submissions are scored on two tracks:
- Single-agent —
num_robots: 1 - Multi-agent —
num_robots: 2, 3, 4, 5
You write one Policy; it's evaluated across both. Official scoring also runs across environments grouped by size, each with its own timestep budgetmax_steps— single-agent gets a larger budget than multi-agent on the same environment:
| Size | Released examples | Single-agent max_steps | Multi-agent max_steps |
|---|---|---|---|
| Small | env1, env2 | 1000 | 500 |
| Medium | env3, env4, env5 | 1500 | 1000 |
| Large | env6, env7 | 2000 | 1500 |
(See Stages below — Stage 2's held-out maps aren'tenv1–env7themselves, but follow this same size-basedmax_stepsscheme.)
Stages
- Stage 1 (preliminary, optional)— submit your policy to us and we'll run it on the released test environments
env1–env7, score it, and post results to a leaderboard along with feedback. - Stage 2 (final) — the actual scored round. You don't need to have submitted to Stage 1 to enter Stage 2, but Stage 2 submissions get no feedback. Scoring runs on a different, held-out set of environments (not
env1–env7), sized and budgeted per the table above.
Scoring
At the end of a run, main.pyprints the final base-station coverage: the fraction of the true map the base station has learned about bymax_steps. This rewards actually getting information home, not just observing it - so both exploration and relay strategy matter for score.

Your goal doesn't have to be frontier-based
Any exploration strategy is allowed (frontier-based, sampling-based, potential-field, learned, etc.) as long as it only usesobs. Returning Nonefrom decide()is a legitimate way to say "no opinion" - the framework falls back to the nearest reachable frontier in that case. But if you return a specific goal, it has to actually be reachable: an unreachable, occupied, out-of-bounds, or malformed goal raisesInvalidGoalErrorand halts the run immediately, rather than being silently patched up for you.
What you implement
You write a Policyclass with up to three decisions, all made per-robot:
- `decide()` (required) - where to explore next.
- `should_relay()` (optional) - when to switch from exploring to relaying info back to base.
- `decide_relay_handoff()`(optional) - while relaying, whether to hand relay duty off to a nearer connected robot, and to whom.
If you don't override should_relay()/decide_relay_handoff(), you get the provided baseline behavior for free, matching the shipped config.
Override should_relay()and/or decide_relay_handoff()to compete on relay strategy as well as exploration.
Map prediction (coming soon)
We'll be releasing training data of floorplans that can be used for map prediction — e.g. inferring the likely layout of still-unknown areas from what's been observed so far, to inform exploration. Not available yet; we'll announce here once it's released. In the meantime, for a sample prediction approach, seeMapEx(github.com/castacks/MapEx).
What the Observation contains
Only what your robot has legitimately sensed or received over communication - never ground truth:
obs.combined_obs_map- your robot's map so far (unknown / free / occupied). Whenever two robots (or a robot and the base station) are in comm range, their maps are automatically fused, so this can include cells a peer observed, not just what your own sensor has seen. Fusion is provided/automatic - identical for every submission - not somethingdecide()controls.obs.pose- your robot's current positionobs.unreported_mask,obs.delegated_mask- bookkeeping on what's been observed but not yet reported to baseobs.pose_lists_of_others,obs.intents_of_others- other robots' trajectories/intents, as last shared over comm (may be stale if out of range)obs.base_pose- the base station's position (always known)obs.connected_robot_ids- robot ids currently (this timestep) in comm range, so entries for them inpose_lists_of_othersare guaranteed fresh, not stale - useful fordecide_relay_handoff()