Backend Capability Contract¶
Backend differences are contract boundaries, not script-level special cases. The play/render decision is recorded in ADR-0002 Backend Capability Boundary For Play And Snapshot.
Stable Backend Interface¶
All env-facing backend calls should go through SimBackend in
src/unilab/base/backend/base.py. The interface includes base state, DOF state,
body state in world and baselink frames, named sensors, state reset, physics
stepping, domain-randomization hooks, and optional playback/render methods.
Optional capabilities are explicit:
BackendPlayCapabilitiesreports native interactive rendering, physics-state playback, and native video capture support.BackendHeightScannerandcreate_hfield_scanner(...)expose terrain scan support through a reusable backend-owned object.Domain randomization support is surfaced through
get_dr_capabilities()and the init, reset, and interval randomization methods.Unsupported optional methods raise
NotImplementedErrorfrom the base class.
Rules For New Capability¶
If shared env logic needs a new backend operation, add it to
SimBackendfirst, with a defaultNotImplementedErrorif not every backend can support it immediately.Keep MuJoCo/Motrix differences in backend implementations, env adapters, and owner YAMLs. Do not add hot-path probes of backend private methods in env code.
Asset/XML/model metadata access belongs to cold paths such as scene materialization, backend init, or cache creation.
Evidence In Repo¶
Backend interface and play capabilities:
src/unilab/base/backend/base.pyBackend factory:
src/unilab/base/backend/__init__.pyMuJoCo backend:
src/unilab/base/backend/mujoco/backend.pyMotrix backend:
src/unilab/base/backend/motrix/backend.pyBackend contract tests:
tests/base/test_sim_backend.py,tests/base/test_backend_imports.py,tests/base/test_motrix_backend_options.py