newton.actuators.Actuator#

class newton.actuators.Actuator(indices, drive=None, delay=None, clamping=None, pos_indices=None, target_pos_indices=None, effort_indices=None, state_pos_attr='joint_q', state_vel_attr='joint_qd', control_target_pos_attr='joint_target_q', control_target_vel_attr='joint_target_qd', control_feedforward_attr='joint_act', control_output_attr='joint_f', control_computed_output_attr=None, requires_grad=False, *, input_processors=None, motor=None, actuator_indices=None, control_supply_voltage_attr='actuator_supply_voltage', control_supply_current_attr='actuator_supply_current')[source]#

Bases: object

Composed actuator: input processors → drive → clamping → motor.

An actuator reads from simulation state/control arrays, optionally transforms them with input processors (e.g. a command delay), computes effort via a drive, applies clamping (effort limits, saturation, etc.), optionally turns it into the effort of a motor, and accumulates the result into the output array (scatter-add). The caller must zero the output array before stepping actuators.

Usage:

actuator = Actuator(
    indices=indices,
    drive=DrivePD(kp=kp, kd=kd),
    input_processors=[InputProcessorDelay(delay_steps=wp.array([5, 5], dtype=wp.int32), max_delay=5)],
    clamping=[ClampingMaxEffort(max_effort=max_effort)],
)

# Simulation loop
actuator.step(sim_state, sim_control, state_a, state_b, dt=0.01)

Effort is computed explicitly by default (control law evaluated at the current state, zero-order hold over the step).

class ImplicitOptions(max_iters=8, residual_tol=1e-05, update_tol=1e-05, fd_epsilon=0.0001, derivative_floor=1e-08, warm_start=WarmStart.EXPLICIT, ls_iterations=8)#

Bases: object

Configuration for implicit actuation; see Actuator.set_effort_mode_implicit().

class WarmStart(*values)#

Bases: StrEnum

Initial impulse guess for the Newton solve.

EXPLICIT = 'explicit'#

Start from the clamped explicit force impulse.

ZERO = 'zero'#

Start from zero impulse.

__init__(max_iters=8, residual_tol=1e-05, update_tol=1e-05, fd_epsilon=0.0001, derivative_floor=1e-08, warm_start=WarmStart.EXPLICIT, ls_iterations=8)#
derivative_floor: float = 1e-08#

Smallest Jacobian pivot used during elimination and back-substitution (dimensionless: the Jacobian is d(impulse)/d(impulse)).

fd_epsilon: float = 0.0001#

Relative forward finite-difference step in velocity space (dimensionless).

ls_iterations: int = 8#

Maximum step lengths tried per Newton iteration, halving each time, until the residual drops. Each try evaluates the residual once. 0 always takes the full Newton step.

max_iters: int = 8#

Maximum Newton iterations per articulation group.

residual_tol: float = 1e-05#

Stop when the residual vector norm falls below this [N·s or N·m·s].

update_tol: float = 1e-05#

Stop when the impulse-update vector norm falls below this [N·s or N·m·s].

warm_start: WarmStart = 'explicit'#

Initial impulse guess.

__init__(indices, drive=None, delay=None, clamping=None, pos_indices=None, target_pos_indices=None, effort_indices=None, state_pos_attr='joint_q', state_vel_attr='joint_qd', control_target_pos_attr='joint_target_q', control_target_vel_attr='joint_target_qd', control_feedforward_attr='joint_act', control_output_attr='joint_f', control_computed_output_attr=None, requires_grad=False, *, input_processors=None, motor=None, actuator_indices=None, control_supply_voltage_attr='actuator_supply_voltage', control_supply_current_attr='actuator_supply_current')#

Initialize actuator.

Parameters:
  • indices (wp.array[wp.uint32]) – DOF indices into velocity-shaped arrays (velocities, velocity targets, feedforward, effort output). Shape (N,).

  • drive (DriveBase | None) – Drive that computes effort without a motor, or duty with a motor.

  • delay (InputProcessorDelay | None) – Deprecated in Newton 1.9; pass the delay in input_processors instead.

  • clamping (list[ClampingBase] | None) – Clamps applied in list order. Their input_space must match the drive output: EFFORT without a motor, DUTY with one.

  • pos_indices (wp.array[wp.uint32] | None) – Indices into coordinate-shaped arrays (positions = state.joint_q). Defaults to indices. Differs from indices when position and velocity arrays have different layouts (e.g. floating-base or ball-joint articulations).

  • target_pos_indices (wp.array[wp.uint32] | None) – Indices into control.joint_target_q. Defaults to pos_indices. Override for custom target buffers with a different index mapping.

  • effort_indices (wp.array[wp.uint32] | None) – DOF indices into effort output arrays. Defaults to indices. Differs from indices for coupled transmissions or tendon-driven joints.

  • state_pos_attr (str) – Attribute on sim_state for positions.

  • state_vel_attr (str) – Attribute on sim_state for velocities.

  • control_target_pos_attr (str | None) – Attribute on sim_control for target positions. None selects the default "joint_target_q".

  • control_target_vel_attr (str | None) – Attribute on sim_control for target velocities. None selects the default "joint_target_qd".

  • control_feedforward_attr (str | None) – Attribute on sim_control for feedforward effort. None to skip.

  • control_output_attr (str) – Attribute on sim_control for clamped output effort.

  • control_computed_output_attr (str | None) – Attribute on sim_control for raw (pre-clamp) effort. With a motor, this is achieved motor effort after duty limiting and voltage conversion. None to skip writing it.

  • requires_grad (bool) – Allocate intermediate arrays with gradient support for differentiable simulation.

  • input_processors (list[InputProcessorBase] | None) – Input processors applied in list order to the state and command inputs before the drive (e.g. InputProcessorDelay).

  • motor (MotorDC | None) – Optional motor, applied after the clamping (e.g. MotorDC). With a motor, the drive computes signed duty. The actuator converts duty to motor voltage using the actual supply voltage.

  • actuator_indices (wp.array[wp.uint32] | None) – Index of each actuator into per-actuator arrays, i.e. arrays with one entry per actuator of the model rather than per DOF. Required when the motor draws from a battery.

  • control_supply_voltage_attr (str) – Attribute on sim_control for the per-actuator supply voltage the motor reads from its battery.

  • control_supply_current_attr (str) – Attribute on sim_control for the per-actuator current the motor draws from its battery.

is_graphable()#

Return True if all components can be captured in a CUDA graph.

With requires_grad, each step allocates fresh buffers, so capture also needs allocation during capture (Warp’s CUDA memory pool).

is_stateful()#

Return True if an input processor or the drive maintains internal state.

register_custom_attributes(builder)#

Register drive inputs and battery arrays as custom Newton Control attributes.

ModelBuilder calls this method automatically while finalizing its actuators. Every input declared by the drive is registered as a wp.float32 joint-DOF array on Control. When the motor draws from a battery, control_supply_voltage_attr and control_supply_current_attr are registered as per-actuator arrays (ACTUATOR frequency). Registration allocates the arrays but does not populate or clear them; the caller must update the declared inputs before each actuator evaluation.

This method is a Newton convenience. Other simulation engines should provide arrays with the same names through their sim_control adapter instead.

Parameters:

builder (ModelBuilder) – Newton model builder on which to register the attributes.

set_effort_mode_explicit()#

Switch effort computation back to the default explicit mode.

set_effort_mode_implicit(response, options=None)#

Switch effort computation to implicit mode.

The control law is solved against the predicted end-of-step state before the solver runs. See Effort Modes for details on the computation of effort in the implicit mode, its caveats, and its expected use.

Parameters:
Raises:

NotImplementedError – The actuator was built with requires_grad=True, as the implicit solve is not differentiable, or has a motor, which the implicit solve does not model.

Warns:

NewtonWarning – The actuator has an InputProcessorEncoder. The solve uses the motor-side response only, so it is inaccurate while the output joint is not at its limit.

sim_control()#

Return an empty container with the fields this actuator reads from sim_control.

Target arrays must be long enough for target_pos_indices and indices, and output arrays for effort_indices; their lengths are not checked.

Returns:

Container whose slots are the required sim_control attributes, with a get_attribute_frequency(name) method like Control.get_attribute_frequency().

Return type:

Any

Note

Leaving the feedforward field unassigned means no feedforward term.

sim_state()#

Return an empty container with the fields this actuator reads from sim_state.

Every field is None until assigned; the caller owns the arrays. Fields hold references, so re-point them whenever the simulation swaps states. Re-pointing has no effect on an already-captured CUDA graph, which holds the pointers bound at capture time.

Assigned arrays must be long enough for pos_indices and indices; their lengths are not checked.

Returns:

Container whose slots are the required sim_state attributes, with a get_attribute_frequency(name) method like Model.get_attribute_frequency().

Return type:

Any

state()#

Return a new composed state, or None if fully stateless.

step(sim_state, sim_control, current_act_state=None, next_act_state=None, dt=None, *, bias_force=None)#

Execute one control step.

  1. Input processors — transform the state and command inputs in list order (e.g. read delayed targets from current_state), and write each processor’s next_state (e.g. push the current targets into the delay buffer).

  2. Supply voltage — the motor selects fixed or battery voltage for duty clamping and conversion to motor voltage.

  3. Drive — raw effort into _computed_forces (explicit control law, or the implicit end-of-step solve). With a motor, the drive writes signed duty into _drive_output.

  4. Clamping — bounded effort into _applied_forces. Explicit clamps after the drive law; implicit enforces them inside the solve.

  5. Motor — convert duty to motor voltage, then compute effort. A motor that draws from a battery writes the current it draws.

  6. Scatter-add — accumulate applied (and optionally computed) effort into the output array. The caller must zero the output (e.g. control.joint_f.zero_()) before looping over actuators.

  7. Drive state update — write the drive’s next_state.

Parameters:
  • sim_state (Any) – Object or mapping carrying the arrays named by state_pos_attr and state_vel_attr. Build one with sim_state().

  • sim_control (Any) – Object or mapping carrying the target and output arrays, plus the drive’s custom inputs and the battery arrays of the motor. Build one with sim_control().

  • current_act_state (State | None) – Current composed state (None if stateless).

  • next_act_state (State | None) – Next composed state (None if stateless).

  • dt (float | None) – Timestep [s].

  • bias_force (wp.array[wp.float32] | None) – Optional per-DOF bias force C qd + g of the manipulator equation tau = M qdd + bias_force, indexed like joint_qd [N or N·m, depending on joint type]: the force the joints need to hold still against Coriolis and gravity. The step itself applies -bias_force. For example gravity_force + coriolis_force from eval_inverse_dynamics_passive(). Used only in implicit mode, where the predicted end-of-step velocity becomes qd + A (p - dt bias_force). Explicit mode ignores it. None (default) leaves the prediction qd + A p. For free and distance joints the entries are a wrench at the child CoM in the world frame, like joint_f. The step rotates it into the joint’s parent frame, the frame of A, using sim_state.body_q.

actuator_indices#

Index of each actuator into per-actuator arrays, or None.

controller#

Data descriptor that turns a removed attribute into a hard error naming its replacement.

property delay: InputProcessorDelay | None#

Deprecated alias for the first InputProcessorDelay in input_processors.

Deprecated since version 1.9: Use input_processors instead.

input_processors#

Input processors, applied in list order before the drive.

motor#

Motor applied after the clamping, or None.