Skip to content

base

Base class for external-backend dynamics adapters.

A DynamicsAdapter is the easy on-ramp for users who want to plug an external physics backend (MuJoCo MJX, Brax, Drake, ...) into OpenSCvx without manually constructing State/Control objects with matching shapes or routing raw JAX callables through the expert byof channel.

The intended call site is::

dyn = ox.MjxDynamics(mjx_model)
problem = ox.Problem(
    dynamics=dyn,
    states=dyn.states,
    controls=dyn.controls,
    ...
)

Internally, Problem detects the adapter, calls DynamicsAdapter.expand, and merges the resulting BYOF callables into the user's byof dict (if any). Everything downstream sees ordinary dynamics and byof dicts.

DynamicsAdapter

Bases: ABC

Abstract base class for external-backend dynamics adapters.

Subclasses describe the State/Control objects they synthesize on .states / .controls and implement expand to return the two-channel (dynamics_dict, byof_dict) representation consumed by Problem.

The split mirrors the existing two-channel API: dynamics_dict carries symbolic Expr entries (e.g. {"qpos": qvel}) while byof_dict carries raw JAX callables under the "dynamics" key. Either or both may be empty, but expand() should never silently produce overlapping keys.

Source code in openscvx/integrations/base.py
class DynamicsAdapter(ABC):
    """Abstract base class for external-backend dynamics adapters.

    Subclasses describe the State/Control objects they synthesize on
    ``.states`` / ``.controls`` and implement `expand` to return the
    two-channel ``(dynamics_dict, byof_dict)`` representation consumed by
    `Problem`.

    The split mirrors the existing two-channel API: ``dynamics_dict`` carries
    symbolic Expr entries (e.g. ``{"qpos": qvel}``) while ``byof_dict`` carries
    raw JAX callables under the ``"dynamics"`` key. Either or both may be
    empty, but ``expand()`` should never silently produce overlapping keys.
    """

    states: list["State"]
    controls: list["Control"]

    @abstractmethod
    def expand(self) -> Tuple[dict, dict]:
        """Return ``(dynamics_dict, byof_dict)`` in OpenSCvx's internal form.

        ``dynamics_dict`` maps state names to symbolic ``Expr`` derivatives
        (the same shape as the ``dynamics=`` argument to ``Problem``).
        ``byof_dict`` has the same shape as the ``byof=`` argument: its
        ``"dynamics"`` key (if present) maps state names to raw JAX callables.
        """
expand() -> Tuple[dict, dict] abstractmethod

Return (dynamics_dict, byof_dict) in OpenSCvx's internal form.

dynamics_dict maps state names to symbolic Expr derivatives (the same shape as the dynamics= argument to Problem). byof_dict has the same shape as the byof= argument: its "dynamics" key (if present) maps state names to raw JAX callables.

Source code in openscvx/integrations/base.py
@abstractmethod
def expand(self) -> Tuple[dict, dict]:
    """Return ``(dynamics_dict, byof_dict)`` in OpenSCvx's internal form.

    ``dynamics_dict`` maps state names to symbolic ``Expr`` derivatives
    (the same shape as the ``dynamics=`` argument to ``Problem``).
    ``byof_dict`` has the same shape as the ``byof=`` argument: its
    ``"dynamics"`` key (if present) maps state names to raw JAX callables.
    """