Skip to content

arena_planners

Subprocess-isolated DRL planner bridge for Arena-Rosnav. Each planner runs in its own venv (own torch/gym/numpy versions), communicates with Arena over msgpack-on-ZMQ, and is driven by a single step(features) -> [v, omega] contract (or a discrete forward/left/right command, or a chunk of waypoints or twists).

Layout

arena_planners/
├── arena_planners/      # SDK: bridge, observations pipeline, resolver
├── planners/            # submodules, one per planner (drlvo, crowdnav, ...)
└── pyproject.toml
  • The SDK lives in arena_planners/arena_planners/. Install with pip install git+https://github.com/arena-planners/arena_planners.git.
  • Each planner is its own submodule under planners/, registered in this repo's .gitmodules. See planners/README.md for the per-planner contract.

Use from Arena

arena launch robot.mobile:=drl robot.mobile.planner:=drlvo

The robot.mobile:=drl adapter (in Arena's task_generator) spawns the planner subprocess, pipes observations to it via the bridge, and routes the returned action to cmd_vel. Optional global plan via robot.mobile.global_planner:=nav2/navfn (or any registered <family>/<kind>). Planners that declare goal_inputs in planner.yaml are VLA planners: they run under robot.mobile:=vla, which robot.planner:=<name> selects automatically, and robot.mobile.goal:=pose|instruction|pose+instruction sets which goal inputs a run reveals. A planner that lists signals: [arrived] can end goto phases that set signal: arrived (the VLN convention): the phase ends when the planner signals, judged against the phase's tolerance at that moment. robot.mobile.config.<key>:=<value> overrides a key of the manifest's config block. robot.mobile.rate:=<hz> sets the planner tick (else drl.rate in the robot's caps/mobile.yaml, else the manifest's rate_hz, else 10), snapped to whole physics steps under lockstep. Planner subprocesses get OMP_NUM_THREADS/MKL_NUM_THREADS/OPENBLAS_NUM_THREADS=4 and OMP_WAIT_POLICY=PASSIVE unless already set in the environment. robot.mobile.deadline:=<s> caps how long the bridge waits for the planner to connect, ack a cancel or reset, or answer an observation before declaring it dead. The default 0 waits forever with periodic warnings, so a planner is only dead once its process exits. The quick checks (arena planners test --preflight, the quicktest_map_empty suite) set 30.

Adding a planner

  1. Create a submodule under planners/<name>/ matching the contract in planners/README.md.
  2. Register it in this repo's .gitmodules with a planner = <name> tag.
  3. From Arena: arena feature planners add <name> initializes the submodule and fetches and verifies the weights declared in weights.yaml, if present. For a gated Hugging Face repo the fetch names the page where the terms are accepted and stops for that planner. Accept them, log in with hf auth login (or set HF_TOKEN) and run the command again.

MCP domain

arena_planners/arena_planners/mcp.py contributes the planners domain to the Arena MCP server (python3 -m arena_mcp ls planners lists its tools). It reads the same registry and resolver as the CLI: every registry planner with its kind, submodule status, planner.yaml summary and weights presence, the full manifest with its resolution, and the structured arena feature planners check verdict plus sha256 verification of weights.yaml. The rosnav_rl agents and nav2 controllers the resolver accepts come with the listing. Adding, installing, updating and removing planner submodules and fetching weights run the real CLI verbs as jobs, polled with jobs_status and stopped with jobs_cancel. The preflight soak belongs to the evaluation domain.

License

MIT. Per-planner submodules carry their own upstream licenses (drlvo: GPL-3.0, crowdnav: MIT).