unilab.base — Core Contracts¶
The shared substrate everything else stands on. If you only read one module in this reference, read this one.
Symbol |
Role |
|---|---|
|
The sole environment and state contract |
|
Abstract backend interface (MuJoCo / Motrix implement it) |
|
Task / backend / algorithm registration and lookup |
|
Cold-path scene materialization |
|
Observation builders & terminal handling |
|
Curriculum schedule primitives |
Environment registry and base classes. |
Selected detail¶
- class unilab.base.torch_env.TorchEnv[source]¶
Bases:
ABEnvBackend-agnostic Torch environment lifecycle.
Concrete owners implement action transformation, tensor state update, and selected-row (
env_ids) reset. The base deliberately rejects NumPy input and never sanitizes non-finite tensors: invalid actions, controls, observations, and rewards fail closed.- Parameters:
cfg (
EnvCfg)backend (
SimBackend)num_envs (
int)
- __init__(cfg, backend, num_envs, *, device='cpu')[source]¶
- Parameters:
cfg (
EnvCfg)backend (
SimBackend)num_envs (
int)
- property backend: SimBackend¶
Public backend owner used by Manager terms and tensor contracts.
- property produces_completion_receipts: bool¶
RL env-contract declaration of the backend’s step receipts.
Truewhen the bound backend publishes an event-backed async completion receipt on everystep(replay CUDA ingress then fails closed without one).Falsefor synchronous producers whose step outputs are already ordered at return, where no receipt exists and none is awaited. This is a cold-path declaration;stepkeeps publishing whatever receipt the backend returns.
- property state: TorchEnvState | None¶
Current environment state (None before first reset)
- reset(env_ids=None)[source]¶
Reset the selected environment rows;
Noneresets all rows.The public selector follows the IsaacLab/mjlab
env_idsrow-index form; the v1.4 fixed-width bool mask form is removed.
- step(actions)[source]¶
Step the environment with owner-declared action carrier.
The abstract base stays runtime-neutral. Concrete owners validate the declared carrier; the Torch lifecycle accepts Torch tensors.
- Parameters:
actions (
Tensor)- Return type:
- init_play_renderer(render_spacing=None, render_offset_mode=None, *, headless=False, capture=False, width=1280, height=720, camera_kwargs=None)[source]¶
Initialize backend-native playback rendering when available.
- resolve_play_render_plan(*, play_render_mode, play_steps, output_video)[source]¶
Resolve high-level playback mode through the concrete backend.
- run_playback(*, initialize, step, num_steps, output_video=None, render_spacing=None, render_offset_mode=None, headless=None, record_video=None, frame_state_getter=None, camera_kwargs=None, debug_overlay_getter=None, on_frame=None)[source]¶
Execute playback through the concrete backend.
- Parameters:
initialize (Callable[[], Any])
step (Callable[[Any], Any])
num_steps (int | None)
output_video (str | PathLike[str] | None)
render_spacing (float | None)
render_offset_mode (str | None)
headless (bool | None)
record_video (bool | None)
frame_state_getter (Callable[[], np.ndarray] | None)
camera_kwargs (CameraCfg | Mapping[str, Any] | None)
debug_overlay_getter (DebugOverlayGetter | None)
on_frame (Callable[[int, np.ndarray], np.ndarray | None] | None)
- Return type:
str | None
- property play_capabilities: EnvPlayCapabilities¶
Return env-facing play/render capabilities.
- render(mode='rgb_array')[source]¶
Render the current state to an RGB array through the play renderer.
- capture_play_video_frame()[source]¶
Capture one detached RGB video frame through the env contract.
- Return type:
- get_physics_state_snapshot()[source]¶
Return a detached physics snapshot for playback/video export.
- Return type:
- get_playback_model(env_index=None)[source]¶
Return the backend playback model for one vectorized environment.
- get_playback_mocap_state(env_index=0)[source]¶
Return detached
(mocap_pos, mocap_quat)playback state.
- get_scene_visual_model_file()[source]¶
Return the backend visual model file on the playback cold path.
- set_nan_guard(guard)[source]¶
Attach the owner-provided diagnostic guard.
Detection stays device-resident. Artifact export occurs only at the guard’s explicit abnormal-diagnostic host boundary.
- get_backend_runtime_diagnostics()[source]¶
Serialize the backend’s tensor runtime diagnostics on the cold path.
This is the collection boundary consumed by training runtimes (the
unilab.rloff-policy collector publishes it into the run manifest). The payload is plain JSON:availableandbackend_typeplus, when available, onediagnosticsentry per backend optimization withrequested/enabled/disable_reason. Backends that declare no optional tensor runtime optimization, or whose diagnostic probe fails, record an explicit unavailable marker instead of a null field.
- abstract apply_action(actions, state)[source]¶
Transform an action tensor into a backend control tensor.
- Parameters:
actions (
Tensor)state (
TorchEnvState)
- Return type:
- abstract update_state(state)[source]¶
Compute tensor observations, reward, and termination state.
- Parameters:
state (
TorchEnvState)- Return type:
- class unisim.backend.base.SimBackend[source]¶
Bases:
ABCUnified simulation backend contract.
- get_scene_layout()[source]¶
Return the immutable materialized public addresses, never native handles.
- Return type:
CompiledSceneLayout
- get_entity_state(entity)[source]¶
Return detached root_pose/root_velocity/joint_positions/joint_velocities.
Root fields follow EntityStatePatch’s link-origin/world-frame contract. Non-root joint fields use the frozen entity joint order and native generalized widths. Unavailable fields must fail, never return old data as if current. State freshness follows the adapter’s declared profile.
- get_entity_default_state(entity, env_ids=None)[source]¶
Detached construction/keyframe defaults in selected environment order.
Fields and frames match get_entity_state. Defaults follow immutable variant assignment and never reflect current reset-time randomization. This query does not reset, step or reparse the scene.
- reset_entities(request)[source]¶
Validate the complete selected-entity request, then commit it once.
Validation failure leaves all state unchanged. A native partial commit failure must fault the backend unless the adapter can actually roll back. Unselected entities/environments and fixed identity remain unchanged.
- Parameters:
request (
SceneResetRequest)- Return type:
- get_import_report()[source]¶
Return a detached construction/materialization configuration snapshot.
This cached report never parses assets, starts workers, or reflects reset-time randomization. Use current-property queries for live values.
- Return type:
ImportReport
- property capability_flags¶
Coarse capability labels for clients that need a cheap feature check.
The detailed contract is expressed by the methods on this class. The labels remain useful for benchmark/conformance metadata and are derived from the mandatory lifecycle methods rather than maintained separately by every adapter.
- get_tensor_execution()[source]¶
Declare the optional tensor lifecycle without discovering SDKs.
- Return type:
TensorExecution
- get_tensor_capabilities()[source]¶
Return fail-closed tensor methods and negotiable state fields.
- Return type:
TensorLifecycleCapabilities
- get_tensor_runtime_diagnostics()[source]¶
Return runtime-selected diagnostics for optional tensor optimizations.
Unlike capability negotiation, these values describe actual cold-path initialization results and may change when a backend falls back or closes. The default empty mapping means the backend declares no optional tensor-runtime optimization.
- get_public_state_widths()[source]¶
Return canonical qpos/qvel widths for packed tensor reset layout.
- Return type:
PublicStateWidths
- bind_host_bridge_io(spec)[source]¶
Compile a persistent transfer plan for a declared host bridge.
- Parameters:
spec (
TensorIOSpec)- Return type:
HostBridgeTransferPlan
- set_mocap_pose_tensor(body_name, env_indices, poses)[source]¶
Write selected mocap poses through the declared tensor lifecycle.
- get_state_views(fields=None, device=None)[source]¶
Return backend-owned state through the declared tensor lifecycle.
Tensor views are Torch tensors. Returned values are logically read-only and mutation is undefined.
DEVICE_RESIDENTadapters return stable live views on the backend’s exact accelerator device;device=Noneselects that device and any other device is rejected.HOST_BRIDGEadapters return explicit copies from authoritative host state;device=Noneselects host CPU and callers pass an explicit accelerator device for H2D copies. Unlike the removed 1.x NumPy snapshot API, successful tensor adapters do not return NumPy arrays. Consume the declared tensor execution mode rather than probing the array implementation.
- get_sensor_view(name, device=None)[source]¶
Return one named sensor view on the declared tensor lifecycle.
- get_tracked_body_views(body_names=None, device=None)[source]¶
Return all tracked-body fields in one public backend read.
body_namesselects and orders the returned body axis.Nonerequests every tracked body in backend insertion order. This aggregate contract avoids one Python projection boundary per body/field sensor.
- step_tensor(ctrl, nsteps=1)[source]¶
Advance physics from a backend-declared accelerator control tensor.
ctrlis a contiguous float32 Torch tensor with shape(num_envs, num_actuators), lives on the adapter-required device, and must be finite. The method consumes it before synchronizing and returning.
- set_state_tensor(env_indices, qpos, qvel, randomization=None)[source]¶
Set selected state through the adapter-declared tensor lifecycle.
env_indicesis a contiguous one-dimensional int64 Torch tensor with unique values in[0, num_envs);qposandqvelare contiguous float32 tensors with shapes(len(env_indices), nq)and(len(env_indices), nv). All three share one adapter-accepted device and must be finite. Adapters may use a bounded synchronization for fail-closed row validation.DEVICE_RESIDENTadapters otherwise avoid a host detour;HOST_BRIDGEadapters make their explicit accelerator-to-host boundary measurable before CPU state is updated. Inputs are consumed before return.randomizationis the unified torch-firstTensorResetRandomizationPayload: every populated field is a dense selected-row Torch tensor table. Tensors ontorch.cpuform the host plane, checked againstDomainRandomizationCapabilities.supported_reset_terms; tensors on any other device form the device plane, checked againstsupported_device_reset_terms(empty by default, so undeclared device support fails closed naming the term). Non-delta terms hold final absolute values applied as selected-row in-place scatters;base_mass_deltaandbase_com_offsethold deltas merged with the adapter baseline. Host adapters convert tensors at their private NumPy boundary throughunisim.dr._host.
- set_state_tensor_mask(reset_mask, qpos, qvel, randomization=None, *, full_refresh=False)[source]¶
Set state selected by a fixed-width boolean mask.
reset_maskis a contiguous one-dimensional boolean Torch tensor with shape(num_envs,).qposandqvelare full-width contiguous float32 tensors with shapes(num_envs, nq)and(num_envs, nv). All three share one accepted Torch device and contain finite values. The adapter changes qpos/qvel/time only for true rows and preserves every false row. It publishes authoritative selected state before returning; any row materialization required by the engine belongs behind this backend boundary.randomizationis the unified torch-firstTensorResetRandomizationPayload(full-width tables on the mask’s plane); the adapter must preserve every false row.full_refresh=Truerequests an eager equivalent full-batch derived-state/publication refresh. It is valid only whereTensorLifecycleCapabilities.mask_selected_reset_full_refreshis declared.
- abstract get_actuator_ctrl_range()[source]¶
Return actuator control ranges.
- Return type:
- Returns:
Array with shape
(num_actuators, 2)and columns[low, high].
- get_actuator_joint_names()[source]¶
Return each actuator’s target single-DoF joint in control-vector order.
Backends must fail closed when an actuator does not target exactly one hinge/slide joint. Manager action terms use this cold-path metadata to map community joint selectors onto the backend control vector without inspecting backend-private model objects.
- get_scene_visual_model_file()[source]¶
Return the scene visual model file on the cold path, when available.
Backends without a separate visual scene model return
None.
- get_terrain_spawn_data()[source]¶
Return backend-materialized terrain metadata on the cold path.
Backends without generated terrain support return
None. Callers should resolve this once during env initialization and cache the returned height-sampling callable for reset/reward hot paths.- Return type:
TerrainSpawnData|None
- abstract get_keyframe_qpos(name)[source]¶
Return the full qpos for a named keyframe, including the floating base.
- get_default_qpos()[source]¶
Return the backend/model default qpos through a stable contract.
- Return type:
- get_default_dof_pos()[source]¶
Return default joint positions in canonical non-root qpos order.
The returned array is detached, one-dimensional, and excludes floating root coordinates. Backends whose DoF view is actuator-indexed must use that same actuator-target order here.
- Return type:
- abstract get_init_qvel()[source]¶
Return a zero-initialized qvel vector compatible with
set_state_tensor.- Return type:
- Returns:
Zero-filled qvel array.
- get_root_state_layout(root_body_name)[source]¶
Resolve one body’s floating-root columns on the cold path.
Backends must verify that
root_body_nameowns a free/floating joint; fixed bodies and runtimes without body-to-root metadata fail closed. Name/model lookup is forbidden on reset and step hot paths, so callers cache either the returned layout or the unsupported result during scene materialization.- Parameters:
root_body_name (
str)- Return type:
RootStateLayout
- abstract get_body_ids(names)[source]¶
Resolve body/link names to backend integer IDs.
- Parameters:
- Return type:
- Returns:
int32array with shape(len(names),).- Raises:
ValueError – If any name is not found.
- get_geom_size(name)[source]¶
Return one geom size vector in backend geom-name order.
get_default_geom_sizesreturns the complete table of default sizes, while this selector resolves one geom by name.
- get_geom_solref()[source]¶
Return default contact reference parameters, shape (ngeom, 2).
- Return type:
- get_geom_solimp()[source]¶
Return default contact impedance parameters, shape (ngeom, 5).
- Return type:
- bind_mocap_pose(body_name)[source]¶
Resolve a mocap body once; unavailable capabilities fail at binding.
- Parameters:
body_name (
str)- Return type:
MocapPoseBinding
- bind_height_scanner(*, hfield_geom_id, offsets, frame_body_id, alignment='yaw', output='height')[source]¶
Create a reusable height-field scanner on the init/cold path.
Backends that support height-field terrain scan must override this method.
- get_body_ipos(env_ids=None)[source]¶
Return body center-of-mass offsets in each body’s local frame, in meters.
body_ipos[b]is the position of bodyb’s center of mass in that body’s own local coordinate frame; it is neither an inertia tensor nor a whole-subtree COM.Without
env_idsthe canonical model default table is returned with shape(nbody, 3)in backend body-id order. It never changes with reset randomization; fixed-variant backends expose their per-environment default baselines throughget_reset_term_default()instead.With
env_idsthe current effective per-environment values are returned with shape(len(env_ids), nbody, 3), inenv_idsorder. The values reflect every reset randomization applied so far, including composition withbase_com_offset; an environment untouched by a partial reset keeps its previous values. Backends that do not track per-environment inertial offsets fail closed withNotImplementedErrorfor this form.
- get_motion_body_ids(names)[source]¶
Resolve body IDs used by motion datasets.
Motion datasets are generated from MuJoCo, so the returned ids follow the MJCF body order with
worldbodyas id 0, regardless of the backend-native indexing used byget_body_ids.
- cleanup_scene_assets()[source]¶
Release cold-path scene artifacts owned by the backend.
- Return type:
- abstract get_joint_range(*, names=None)[source]¶
Return joint position limits, excluding the floating base.
- Parameters:
names (
Sequence[str] |None) – Optional joint names in requested return order. Adapters that support named scalar joints resolve the model mapping internally.- Return type:
- Returns:
Array with shape
(num_dof, 2)and columns[low, high], orNonewhen the backend does not expose limits.When
namesis provided by a supporting adapter, the result has shape(len(names), 2). Hinge limits are radians, slide limits are meters, and joints without enabled limits return infinities.
- set_pre_step_control(fn)[source]¶
Register an env-owned policy-control to physics-control converter.
The callback receives
(backend, ctrl)so owner code can read the backend’s freshly-updated sensor contract before every physics substep. It must return either backend-native actuator control with the same shape, or aPreStepControlOutputcarrying that control plus an optional per-substep body wrench. A returned wrench is recomposed from scratch every substep and cleared when thestep()call finishes. Position-actuator envs leave this unset and keep the direct control path.
- get_capabilities(*, profile='default')[source]¶
Query semantic declarations plus authoritative DR/play/variant support.
This cold-path query does not discover SDKs or verify runtime behavior. Materialized configuration readback is exposed by
get_import_report.- Parameters:
profile (
str)- Return type:
CapabilityReport
- abstract get_dr_capabilities()[source]¶
Return supported domain-randomization capabilities for this backend.
- Return type:
DomainRandomizationCapabilities
- get_reset_term_default(term)[source]¶
Return the authoritative default table for a curated reset term.
Without fixed variants the tail shape is the canonical model table, for example
(nbody,)forbody_mass. With fixed variants the returned table is per-environment, for example(num_envs, nbody). Callers must treat the result as read-only; adapters return detached copies.
- apply_interval_randomization(plan)[source]¶
Apply a scheduled interval randomization plan.
Generic dispatch: each op yielded by
plan.iter_ops()is validated against the builtin term specs (custom terms pass through) and routed to the backend-owned handler table returned by_interval_term_handlers(). Op payloads are torch-first: Torch tensors orTensorIntervalPayloadvalues produced by the caller; host adapters convert tensors at their private boundary throughunisim.dr._host, and a missing producer-sampled payload fails closed. A term without a handler fails closed withNotImplementedErrornaming the backend class and the term. Backends that need per-plan prologue/epilogue semantics (for example clearing staged external forces before the ops accumulate) keep a thin override that calls this base implementation.- Parameters:
plan (
IntervalRandomizationPlan)- Return type:
- apply_body_force(body_ids, force, torque=None)[source]¶
Apply a world-frame force (and optional torque) to bodies for the upcoming step.
- Parameters:
body_ids (
ndarray) – Body ids whose external forces should be perturbed.force (
ndarray) – Force values with shape(num_envs, len(body_ids), 3).torque (
ndarray|None) – Optional world-frame torque values with the same shape. Backends without a torque channel must fail closed when this is notNone.
- Return type:
- Returns:
None. Backends that support this mutate their pending simulation state.
- get_play_capabilities()[source]¶
Return backend-native play/render capabilities.
- Return type:
PlayCapabilities
- resolve_play_render_plan(*, play_render_mode, play_steps, output_video)[source]¶
Resolve high-level playback mode into backend-owned render parameters.
- run_playback(*, env, initialize, step, num_steps, output_video=None, render_spacing=None, render_offset_mode=None, headless=None, record_video=None, frame_state_getter=None, camera_kwargs=None, debug_overlay_getter=None, on_frame=None)[source]¶
Execute backend-owned playback for an env wrapper.
camera_kwargsis normalized intoCameraCfgat this boundary; unknown mapping keys fail closed with an error naming them.debug_overlay_getteris an optional per-frame callback returning a sequence with one entry per environment (len == num_envs); each entry is that env’s sequence ofDebugPrimitive(Noneor empty marks an env without overlay) and returningNonedisables overlays for the frame. Primitive poses are env-local; the renderer applies grid offsets when composing multiple envs. Backends whoseget_play_capabilities().supports_debug_overlayis False fail closed withNotImplementedErrorwhen this is notNone. On the interactive rendering path only backends whosesupports_interactive_debug_overlayis True consume it; the others fail closed withNotImplementedError.on_frameis an optional per-frame video hook called by offline render pipelines before encoding: it receives(frame_index, frame)with the frame an(H, W, 3)uint8 array, and returns a replacement frame of the same shape/dtype orNoneto keep the original. Backends rendering through a native (non-offline) renderer fail closed withNotImplementedErrorwhen this is notNone.Known boundary:
envis the owning env wrapper, not a physics-layer concept. Current playback implementations read env-level configuration (e.g.cfg.scene,cfg.ctrl_dt,cfg.render_spacing) and env-owned playback helpers (get_playback_model,get_physics_state_snapshot) that have no backend-native equivalent yet. The parameter stays on this contract until playback asset/config resolution moves onto backend-owned metadata; backends must only use it on the cold playback path.
- bind_renderer(spacing=1.0, *, offset_mode='grid', headless=False, capture=False, width=1280, height=720, camera_kwargs=None)[source]¶
Initialize a backend-native renderer.
headlesscontrols whether a native window is opened.capturecontrols whethercapture_video_frameis valid for the renderer.camera_kwargsis normalized intoCameraCfgat this boundary; unknown mapping keys fail closed with an error naming them.
- render()[source]¶
Render one frame through a backend-native interactive renderer.
- Raises:
RenderClosedError – If the user closed the render window.
- Return type:
- capture_video_frame()[source]¶
Capture one RGB frame through a backend-native renderer.
- Raises:
RenderClosedError – If the user closed the render window.
- Return type:
- get_physics_state()[source]¶
Return a physics snapshot suitable for offline playback/video export.
Rows use the
[time, qpos, qvel]layout; backends whose model has mocap bodies append[mocap_pos(nmocap*3), mocap_quat(nmocap*4)]so offline rendering can replay mocap-driven geometry at its recorded pose. Consumers must decode snapshots throughget_physics_state_layout().split_staterather than hardcoding column slices.- Return type:
- get_physics_state_layout()[source]¶
Return the contract-level layout of
get_physics_statesnapshots.Backends reporting
get_play_capabilities().supports_physics_state_playbackmust implement this so render frontends can split snapshots without hardcoding the column layout.- Return type:
PhysicsStateLayout
- get_playback_mocap_state(env_index=0)[source]¶
Return copied
(mocap_pos, mocap_quat)arrays for detached playback.Shapes are
(nmocap, 3)and(nmocap, 4)for the selected environment. Backends exposing this declareget_play_capabilities().supports_mocap_playback.
- set_physics_state(state)[source]¶
Restore a snapshot produced by
get_physics_state.Backends implementing this must refresh their host caches so state and sensor getters stay consistent with the restored physics state.
- get_playback_model(env_index=None)[source]¶
Return the playback model for a specific env when variants exist.
- get_joint_dof_indices(names)[source]¶
Resolve joint names to absolute DoF indices in velocity space.
- get_joint_dof_pos_indices(names)[source]¶
Resolve joint names to DoF indices in position space (qpos).
Only single-DoF joints are supported; free joints are excluded.
- get_joint_dof_vel_indices(names)[source]¶
Resolve joint names to joint-section DoF indices in velocity space.
Unlike
get_joint_dof_indices(), the returned indices exclude any root/free-joint velocity columns. They address the same joint section used byget_joint_dof_pos_indices().
- get_joint_state_qpos_indices(names)[source]¶
Resolve single-DoF joints to full
set_state_tensorqpos columns.Unlike
get_joint_dof_pos_indices(), these indices address the complete qpos vector accepted byset_state_tensor(), including any root coordinates. Manager reset transactions resolve them on the cold path.
- get_joint_state_qvel_indices(names)[source]¶
Resolve single-DoF joints to full
set_state_tensorqvel columns.
- get_site_jacobian_w(site_id, dof_indices)[source]¶
Compute world-frame Jacobians for one site and selected DoF columns.