Source code for unisim.backend.mujoco.state_commit
"""Prepared writes consumed by the single MuJoCo native state submitter.
These adapter-local values describe an already validated transaction. They
do not inspect assets, call the engine, or impose an entity layout on model-file
models with arbitrary valid MuJoCo topology and transmissions.
"""
from __future__ import annotations
from dataclasses import dataclass
import numpy as np
[docs]
@dataclass(frozen=True)
class ModelWrite:
field: str
values: np.ndarray
column: int | None = None
[docs]
@dataclass(frozen=True)
class MocapWrite:
index: int
poses: np.ndarray
[docs]
@dataclass(frozen=True)
class StateCommitPlan:
"""Owned prepared rows; public callers never submit this internal value.
``reset_world`` preserves the historical full-reset lifecycle; false
preserves every unspecified entity/environment channel. ``defaults`` is
used only by the explicit reset-to-initial-state entry point.
"""
rows: np.ndarray
qpos: np.ndarray
qvel: np.ndarray
qpos_columns: tuple[int, ...]
qvel_columns: tuple[int, ...]
reset_world: bool = False
mocap: tuple[MocapWrite, ...] = ()
control_clear: tuple[int, ...] = ()
activation_clear: tuple[int, ...] = ()
force_dof_clear: tuple[int, ...] = ()
force_body_clear: tuple[int, ...] = ()
model_writes: tuple[ModelWrite, ...] = ()
defaults: tuple[tuple[str, np.ndarray], ...] = ()
control_values: np.ndarray | None = None
activation_values: np.ndarray | None = None
[docs]
def selected_rows(value: np.ndarray, num_envs: int) -> np.ndarray:
rows = np.asarray(value)
if rows.ndim != 1 or rows.dtype.kind not in "iu":
raise ValueError("env_indices must be a one-dimensional integer array")
if np.any(rows < 0) or np.any(rows >= num_envs):
raise ValueError("env_indices must be in range")
if len(np.unique(rows)) != rows.size:
raise ValueError("env_indices must be unique")
return rows.astype(np.int32, copy=True)
[docs]
def state_values(value: np.ndarray, shape: tuple[int, ...], dtype, name: str) -> np.ndarray:
values = np.asarray(value)
if values.shape != shape:
raise ValueError(f"{name} must have shape {shape}, got {values.shape}")
if values.dtype.kind not in "fi" or not np.isfinite(values).all():
raise ValueError(f"{name} must contain finite real values")
limit = np.finfo(dtype).max
if np.any(values > limit) or np.any(values < -limit):
raise ValueError(f"{name} values exceed {np.dtype(dtype)} range")
return values.astype(dtype, copy=True)