| title | OpenBeni |
|---|---|
| emoji | π |
| colorFrom | blue |
| colorTo | purple |
| sdk | docker |
| app_port | 7860 |
| license | mit |
Canonical source: Mondo-Robotics/open-beni. Development and pull requests belong in this repository; the Hugging Face Space is a deployment of this source.
Play the browser game at Hugging Face Spaces. This repository contains the complete web game, server, training source, robot assets and policies under the MIT license. See the web README for local development, loading checks and deployment.
Build and run the game from source with Docker:
docker build -t open-beni .
docker run --rm -p 7860:7860 open-beniOpen http://localhost:7860. Hugging Face proxies port 7860 to the Space's HTTPS URL; players do not enter a port.
Set MAX_ROOMS=0 to disable multiplayer; the default is 10 rooms.
For a build without a runtime CDN, pass --build-arg VITE_ASSET_BASE_URL=.
Flat-terrain velocity tracking, recovery and jumping for the BENI robot, built on mjlab and MuJoCo Warp.
- Linux x86_64.
- Python 3.12.
- An NVIDIA GPU (at least 8 GB memory) with a driver compatible with CUDA 12.8 for training. CPU execution is available for small runs.
- uv for Python and dependency management.
Install dependencies from the repository root:
uv sync --lockedTrain the BENI robot for 15,000 PPO iterations:
uv run python -m beni_rl.train Beni-Jump-Flat --env.scene.num-envs 4096 --agent.max-iterations 15000 --agent.seed 42Run a small training check that automatically uses CPU when CUDA is unavailable:
uv run python -m beni_rl.train Beni-Jump-Flat \
--env.scene.num-envs 4 --agent.max-iterations 10CPU runs use the same MuJoCo Warp backend and are slower than GPU training.
Checkpoints and TensorBoard logs are saved under logs/rsl_rl/beni_jump_flat/.
Inspect all training options with uv run python -m beni_rl.train Beni-Jump-Flat --help.
python -m beni_rl.train automatically uses all visible CUDA devices, up to eight.
--gpu-ids '[0,1]' selects indices within CUDA_VISIBLE_DEVICES; --gpu-ids None
selects CPU.
Resume a checkpoint with additional PPO updates:
uv run --locked python -m beni_rl.train Beni-Jump-Flat \
--agent.resume True --agent.load-run '<run>' --agent.load-checkpoint model_4000.pt \
--agent.max-iterations 3000Resume restores the stage, sampling progress, difficult-state membership and learning-rate ceiling.
Play the policy in the browser using Viser, from the repository root:
uv run play Beni-Jump-Flat --checkpoint-file "assets/models/policy.pt" --num-envs 1 --viewer viserOnce Viser is ready, play automatically opens the default browser in a new window
(or a tab, depending on browser settings). The default address is
http://localhost:8080; if that port is occupied, the browser opens the port Viser
actually selects. If no browser is available, use the URL printed in the terminal.
Open Controls β Commands β Twist and check Enable to control the selected robot with the sliders. When unchecked, commands are sampled automatically.
| Control | Range | Requested behavior |
|---|---|---|
lin_vel_x |
β2 to 2 m/s | Forward for positive values, backward for negative values. |
lin_vel_y |
Fixed at 0 | Lateral motion is disabled. |
ang_vel_z |
β5 to 5 rad/s | Left turn for positive values, right turn for negative values, viewed from above. |
base_pitch (rad) |
β0.1 to 0.1 rad | Requested forward/backward body tilt (pitch). |
base_roll (rad) |
β0.1 to 0.1 rad | Requested left/right body tilt (roll). |
base_height (m) |
0.10 to 0.12 m | Requested body height; larger values request a taller stance, with 0.11 m at the midpoint. |
For example, set lin_vel_x = 0.5 and ang_vel_z = 0 to drive forward, or set
lin_vel_x = 0 and ang_vel_z = 1 to request a left turn in place. Set both to
zero to request standing still; keep Enable checked. Combining forward speed
and yaw rate requests a curved path. These are policy commands, so the actual
motion and pose depend on the trained policy's tracking ability.
Open Controls β Commands β Jump (the folder shows the fixed reference height)
and click Request one jump to trigger a single jump for the selected robot.
Jumps are triggered manually during play. To try a standing jump, keep Twist
Enable checked, set both velocity commands and body tilt to zero, and set
base_height (m) = 0.11. Wait for Measured state to show ready=True before
clicking. You can also request a jump while driving forward once the robot is
balanced. Training, play and the BENI web profile use a fixed 0.18 m jump reference,
measured as base rise above the nominal standing height, with a matching height
command. Checkpoint settings and uploaded model fingerprints do not change this
reference; actual wheel clearance depends on the trained policy. The original
trajectory file is retained as an archive; earlier policies require their matching
source revision to reproduce their behavior.
The robot must meet the balance and wheel-support conditions continuously for
0.2 seconds before a request can be accepted. Last request shows accepted
or a rejection reason: not ready, cooldown, busy or disabled. Before
requesting another jump, let the robot recover its balance and wait for both
the 1-second cooldown and the previous jump's landing monitoring to finish.
busy can remain visible for several seconds after landing; wait and click
again to submit a new request.
Use Simulation β Pause to freeze the simulation, or Reset Environment to reset the robot after a fall. Jump requests made while paused are processed after resuming the simulation.
Play a trained policy, replacing <run> with a saved checkpoint:
uv run play Beni-Jump-Flat \
--checkpoint-file "logs/rsl_rl/beni_jump_flat/<run>/model_best.pt" \
--num-envs 1 \
--viewer viserTo inspect the robot without a checkpoint:
uv run play Beni-Jump-Flat \
--agent zero \
--num-envs 1 \
--viewer viserExport a checkpoint on CPU:
uv run --locked --group export python -m beni_rl.headless_export \
--run_dir "logs/rsl_rl/beni_jump_flat/<run>" \
--checkpoint model_best.ptOmit --checkpoint to select the highest-numbered model_*.pt in the run.
The command performs .pt β ONNX β MNN and writes both deployment artifacts
under <checkpoint-dir>/exported/<checkpoint-stem>/:
| File | Deployment use |
|---|---|
policy.onnx |
Policy for ONNX Runtime and the browser viewer. |
policy.mnn |
Policy for MNN deployed on the robot. |
The browser MuJoCo + ONNX game lives in web/. Build from a
full repository checkout with Node.js 22.13+ and Python 3.9+ available as
python3; no training dependencies are needed.
cd web
npm ci
npm run build
npm startOpen http://localhost:3000/. The Node server listens on 0.0.0.0:3000 and
enables Multiplayer by default; use npm run dev for development. Serving
web/dist/ alone supports Single Player only. Public Multiplayer deployment
needs the Node server on the same origin.
Key files and directories:
.
βββ assets/
β βββ beni_base/
β β βββ meshes/ # Robot visual meshes (OBJ)
β β βββ mjcf/beni.xml # MuJoCo robot model
β β βββ textures/ # Robot textures
β β βββ urdf/beni.urdf # URDF robot model
β βββ models/
β β βββ policy.pt # Checkpoint for play
β β βββ policy.onnx # ONNX policy
β β βββ policy.mnn # MNN policy
β β βββ policy_best.pt # Local best checkpoint
β β βββ policy_best.onnx # Local best ONNX policy
β βββ motions/
β βββ base_jump_h0.18.npz # Current Jump reference trajectory
β βββ base_jump_h0.25.npz # Retained original Jump reference
β βββ recovery_initial_states_train.npz # Original recovery library
β βββ recovery_contact_states_train.npz # Contact-stratified training states
β βββ recovery_contact_states_heldout.npz # Independent recovery assessment states
βββ python/beni_rl/
β βββ __init__.py # Task registration
β βββ _viser_logging.py # Viser WebSocket log filtering
β βββ actuator.py # Motor and passive spring models
β βββ beni_jump_env_cfg.py # Jump training and play environment
β βββ beni_robot.py # Robot and actuator configuration
β βββ beni_velocity_flat_env_cfg.py # Velocity tracking environment
β βββ distributed.py # Shared multi-GPU normalization
β βββ headless_export.py # ONNX/MNN exporter
β βββ jump.py # Jump commands, measurements and rewards
β βββ jump_evaluation.py # Jump trials for best-checkpoint selection
β βββ mdp.py # Shared observations, rewards and events
β βββ play.py # Play entry point and browser launch
β βββ recovery.py # Recovery rewards and state restoration
β βββ recovery_bank.py # Bank validation and physical strata
β βββ recovery_curriculum.py # Recovery sampling and curriculum
β βββ recovery_evaluation.py # Independent locomotion checks
β βββ recovery_gate.py # Recovery checks before Jump training
β βββ recovery_sampling.py # Adaptive sampling of difficult recovery states
β βββ rl_cfg.py # PPO configuration and training runner
β βββ train.py # Training entry point
β βββ velocity_command.py # Velocity, pose and gimbal commands
β βββ wheel_safety.py # Wheel overspeed termination and diagnostics
βββ web/
β βββ app/ # Browser UI
β βββ client/ # Game session and input handling
β βββ components/ # UI components
β βββ game/ # Browser simulation and rendering
β βββ hooks/ # React hooks
β βββ lib/ # Shared UI utilities
β βββ public/ # Static config and generated runtime assets
β βββ scripts/ # Asset and runtime preparation
β βββ server/ # Multiplayer server
β βββ shared/ # Client/server race rules and protocol
β βββ tools/ # Demo recorder and verification tools
β βββ README.md # Web development instructions
βββ pyproject.toml # Python package and dependencies
βββ uv.lock # Locked Python dependencies
βββ LICENSE
βββ README.md
OpenBENI is licensed under the MIT License. Dependencies, including mjlab, retain their own licenses.
Built with mjlab and MuJoCo Warp.