bam.mjlab ========= .. py:module:: bam.mjlab .. autoapi-nested-parse:: BAM actuator models for mjlab (MuJoCo Warp). Wraps any BAM Model (m1–m6) into mjlab's actuator framework. All friction computations are fully vectorized over the (num_envs, num_joints) batch dimension using PyTorch. Usage example — bundled motor:: from bam.mjlab import make_bam_actuator_cfg actuator_cfg = make_bam_actuator_cfg( motor_name="xl330", model="m6", target_names_expr=(r".*",), ) Usage example — custom JSON path:: actuator_cfg = make_bam_actuator_cfg( json_path="params/xl330/m6.json", target_names_expr=(r".*",), ) Classes ------- .. autoapisummary:: bam.mjlab.BamActuatorCfg bam.mjlab.BamActuator Module Contents --------------- .. py:class:: BamActuatorCfg Bases: :py:obj:`mjlab.actuator.actuator.ActuatorCfg` Configuration for a BAM actuator compatible with mjlab. Specify the model with **one** of two mutually exclusive approaches: * **Bundled motor**: set ``motor_name`` (e.g. "xl330") and ``model`` (e.g. "m6"). The path is resolved automatically from the ``params/`` directory bundled with the library. * **Custom JSON**: set ``json_path`` to a BAM params JSON file produced by ``bam.fit``. :param motor_name: Name of the bundled motor. Currently supported: "xl330", "xl320", "mx106", "mx64", "erob80:50", and "erob80:100". Mutually exclusive with ``json_path``. :param model: Model variant to use with ``motor_name``, one of "m1"–"m6". Mutually exclusive with ``json_path``. :param json_path: Path to a custom BAM params JSON file produced by ``bam.fit``. Mutually exclusive with ``motor_name`` and ``model``. :param target_names_expr: Tuple of regex patterns to match actuated joint names. :param vin: Supply voltage override [V]. ``None`` → uses the value in the JSON. :param kp_fw: Firmware P-gain override. ``None`` → uses the value in the JSON. :param vin_range: If set, a per-env battery voltage is sampled uniformly from this range at startup and held constant across resets. Takes precedence over ``vin``. :param vin_drop_gain_range: If set, a per-env internal-resistance gain [V/Nm] is sampled uniformly from this range at startup. Models the voltage drop V_drop = gain * Σ|τ| due to battery + cable resistance. Gain should be approximately resistance / Kt. Held constant across resets. :param vin_min: Hard lower bound on the effective supply voltage [V] after applying the voltage drop. Ensures ``vin`` never falls below this value regardless of the load. ``None`` → no lower bound. :param max_current: Firmware current limit [A]. If set, the motor current is clipped to ``[-max_current, max_current]`` (equivalently the motor torque is clipped to ``±max_current * kt``), reproducing the firmware-side current saturation of the motor. ``None`` → no current clipping. :param delay_min_lag: Minimum command delay in simulation steps. Models the latency between the policy output and the motor response. ``0`` → no delay. :param delay_max_lag: Maximum command delay in simulation steps. Set greater than ``delay_min_lag`` to randomize the delay across environments. :param delay_hold_prob: Probability of keeping the same lag value at each step. ``0.0`` → lag is resampled every ``delay_update_period`` steps. :param delay_update_period: Number of steps between lag updates. ``0`` → updated every step. :param delay_per_env_phase: Whether each environment starts with an independent delay phase offset. ``True`` → environments are not synchronized. .. py:attribute:: motor_name :type: str | None :value: None .. py:attribute:: model :type: str | None :value: None .. py:attribute:: json_path :type: str | None :value: None .. py:attribute:: vin :type: float | None :value: None .. py:attribute:: kp_fw :type: float | None :value: None .. py:attribute:: vin_range :type: tuple[float, float] | None :value: None .. py:attribute:: vin_drop_gain_range :type: tuple[float, float] | None :value: None .. py:attribute:: vin_min :type: float | None :value: None .. py:attribute:: max_current :type: float | None :value: None .. py:method:: build(entity: mjlab.entity.Entity, target_ids: list[int], target_names: list[str]) -> BamActuator .. py:class:: BamActuator(cfg: BamActuatorCfg, entity: mjlab.entity.Entity, target_ids: list[int], target_names: list[str]) Bases: :py:obj:`mjlab.actuator.actuator.Actuator` BAM actuator for mjlab — fully vectorized over all parallel environments. Implements the BAM torque pipeline: 1. **Voltage control law** — firmware P-controller (position error → duty cycle → voltage). 2. **DC motor torque** — back-EMF equation (voltage → torque). 3. **Friction budget** — BAM m1–m6 friction model (Coulomb, Stribeck, load-dependent, directional, quadratic). 4. **Static friction clipping** — BAM Algorithm 1 (prevents overshoot when the joint is nearly stopped). Per-environment gain scaling is supported via :meth:`set_gains`. .. py:attribute:: cfg :type: BamActuatorCfg .. py:attribute:: vin_tensor :type: torch.Tensor | None :value: None .. py:attribute:: vin_drop_gain :type: torch.Tensor | None :value: None .. py:attribute:: kp_scale :type: torch.Tensor | None :value: None .. py:attribute:: kd_scale :type: torch.Tensor | None :value: None .. py:attribute:: default_kp_scale :type: torch.Tensor | None :value: None .. py:attribute:: default_kd_scale :type: torch.Tensor | None :value: None .. py:method:: edit_spec(spec: mujoco.MjSpec, target_names: list[str]) -> None Convert position actuators to motor mode and zero MuJoCo friction. We handle all friction ourselves inside :meth:`compute`, so MuJoCo's built-in ``frictionloss`` and ``damping`` are zeroed out here. .. py:method:: initialize(mj_model: mujoco.MjModel, model: mujoco_warp.Model, data: mujoco_warp.Data, device: str) -> None .. py:method:: reset(env_ids: torch.Tensor | slice | None = None) -> None .. py:property:: command_field :type: mjlab.actuator.actuator.CommandField .. py:method:: set_gains(env_ids: torch.Tensor | slice, kp_scale: torch.Tensor | None = None, kd_scale: torch.Tensor | None = None) -> None Scale firmware gains for a subset of environments. .. py:method:: reset_gains(env_ids: torch.Tensor | slice) -> None Restore default gains for a subset of environments. .. py:method:: compute(cmd: mjlab.actuator.actuator.ActuatorCmd) -> torch.Tensor Compute output torques for all environments — shape ``(N, J)``.