newton.controllers.ControllerDifferentialIK#

class newton.controllers.ControllerDifferentialIK(model, *, articulations=None, joints=None, tool_sites, axis_weight=None, bandwidth, damping, ik_method=DifferentialIKMethod.DAMPED_LEAST_SQUARES, adaptive_damping_min=None, adaptive_damping_max=None, adaptive_damping_threshold=None, truncated_svd_threshold=None, use_joint_limit_avoidance=False, joint_limit_avoidance_gain=0.0, joint_limit_avoidance_margin=0.0, joint_pos_lower=None, joint_pos_upper=None, use_null_space_posture_control=False, null_space_stiffness=None, null_space_damping=None, null_space_axes=None)[source]#

Bases: ControllerBase

Differential-kinematics (Jacobian-based) controller with internally computed kinematics.

Implements a differential-kinematics control law, selectable per instance via DifferentialIKMethod (damped least squares by default). This model-based variant computes the tool pose and tool-point Jacobian itself: it evaluates forward kinematics and newton.eval_jacobian() from model on every step(), so the caller supplies only joint positions/velocities plus the desired tool pose.

model is borrowed, not owned — it is never written to, and changes to it are visible to the controller immediately.

Joint selection. articulations and joints select which DOFs become the tool Jacobian’s columns, following Label Matching: each is a list of model indices and/or label patterns (or a single pattern), matched against articulation_label and the leaf component of joint_label respectively. Only joints spanning a single coordinate and a single DOF can be controlled.

Tool selection. tool_sites selects one Newton site per robot that ends up with controlled joints — the point on the robot whose pose is controlled. It follows the same list[index/pattern] | index | pattern shape as joints, matched against the leaf component of each site’s label. Every controlled robot must match exactly one site.

Each articulation in model is one robot. Supports heterogeneous robot fleets — robots may have different controlled-DOF counts, and a robot may be left uncontrolled entirely by omitting it from articulations.

See also ControllerDifferentialIKModelFree, which takes the tool pose and Jacobian as inputs instead of computing them from a Model.

Parameters:
  • model (Model) – Model whose articulations are the robots. model.requires_grad=True is not supported at this time.

  • articulations (list[int | str | re.Pattern[str]] | str | re.Pattern[str] | None) – Articulation indices or label patterns to control, as a list or as a single pattern. None selects every articulation in model.

  • joints (list[int | str | re.Pattern[str]] | str | re.Pattern[str] | None) – Model joint indices or label patterns whose DOFs become the tool Jacobian’s columns, within the selected articulations, as a list or as a single pattern. None selects every joint spanning exactly one coordinate and one DOF in each selected articulation; any other joint is left uncontrolled instead of rejected. A joint named explicitly is not filtered this way and still raises ValueError if it is not 1-coordinate/1-DOF.

  • tool_sites (list[int | str | re.Pattern[str]] | str | re.Pattern[str]) – Site indices or label patterns selecting each controlled robot’s controlled point, as a list or as a single pattern. Required — there is no default tool site. Raises if a controlled robot matches zero or more than one site.

  • axis_weight (wp.array[wp.spatial_vector] | wp.spatial_vector | None) – Non-negative per-axis weight for each of the 6 canonical task axes (position x, y, z, then orientation x, y, z), diag(w) applied to both the Jacobian and the pose error for that axis before the solve (J_w = diag(w) @ J, e_w = diag(w) @ e) — a genuine soft weight for any nonzero value. An axis weighted exactly 0 is different in kind, not just degree: it is excluded from the solve structurally (its error and Jacobian rows never enter it at all), not merely driven toward zero by a very small weight — this also shrinks the task’s own dimension, so a robot with fewer than 6 controlled DOFs can still be redundant if enough axes are zeroed. Any combination of active axes is allowed, not just a leading prefix. Pass a single wp.spatial_vector to apply the same weights to every robot, or an array of shape [controlled_robot_count] to set them per robot. None (the default) means every axis is weighted 1 for every robot — full, equally-trusted 6D pose.

  • bandwidth (wp.array[wp.float32] | float | None) – Output velocity scale gain, applied per controlled DOF after the Jacobian solve. Must be non-negative, since a negative value would flip the output velocity’s direction. Pass a scalar to apply the same gain to every controlled DOF, an array of shape [total_controlled_dofs] to set them individually, or None to read inputs.bandwidth each step.

  • damping (wp.array[wp.float32] | float | None) – Damped-least-squares regularization λ, applied per robot to the task-space normal-equations matrix. Pass a scalar to apply the same damping to every robot, an array of shape [controlled_robot_count] to set them individually, or None to read inputs.damping each step. Only meaningful when ik_method=DifferentialIKMethod.DAMPED_LEAST_SQUARES (the default); must be None for every other DifferentialIKMethod, which has no λ to set.

  • ik_method (DifferentialIKMethod) – Inverse-Jacobian solve method, a DifferentialIKMethod. Defaults to DifferentialIKMethod.DAMPED_LEAST_SQUARES.

  • adaptive_damping_min (float | None) – λ used when the smallest singular value of the task Jacobian is at or above adaptive_damping_threshold. Required (and must be non-negative) when ik_method=DifferentialIKMethod.ADAPTIVE_DAMPING; must be None otherwise.

  • adaptive_damping_max (float | None) – λ used at a full singularity (smallest singular value zero), ramping down to adaptive_damping_min as the smallest singular value rises to adaptive_damping_threshold. Required (and must exceed adaptive_damping_min) when ik_method=DifferentialIKMethod.ADAPTIVE_DAMPING; must be None otherwise.

  • adaptive_damping_threshold (float | None) – Smallest-singular-value threshold below which damping starts ramping from adaptive_damping_min toward adaptive_damping_max. Required (and must be positive) when ik_method=DifferentialIKMethod.ADAPTIVE_DAMPING; must be None otherwise.

  • truncated_svd_threshold (float | None) – Per-direction singular-value threshold — a task-space direction with singular value above this is inverted exactly, one at or below it is dropped from the solve entirely. Required (and must be positive) when ik_method=DifferentialIKMethod.TRUNCATED_SVD; must be None otherwise.

  • use_joint_limit_avoidance (bool) – Project a joint-limit-avoidance bias through the null-space projector. Requires joint_limit_avoidance_gain, joint_limit_avoidance_margin, joint_pos_lower, and joint_pos_upper.

  • joint_limit_avoidance_gain (float) – Joint-centering gain, applied once a DOF comes within joint_limit_avoidance_margin of either limit. Required (and must be positive) when use_joint_limit_avoidance=True.

  • joint_limit_avoidance_margin (float) – Distance from either limit at which the avoidance bias starts ramping in [m or rad], same units as joint_pos_lower/joint_pos_upper. Required (and must be positive) when use_joint_limit_avoidance=True.

  • joint_pos_lower (wp.array[wp.float32] | None) – Lower joint position limit per controlled DOF [m or rad], shape [total_controlled_dofs]. Required when use_joint_limit_avoidance=True; baked at construction, not a live port.

  • joint_pos_upper (wp.array[wp.float32] | None) – Upper joint position limit per controlled DOF [m or rad], shape [total_controlled_dofs]. Required when use_joint_limit_avoidance=True; baked at construction, not a live port.

  • use_null_space_posture_control (bool) – Project a proportional pull toward inputs.q_des_null through the null-space projector. Enables null_space_stiffness.

  • null_space_stiffness (wp.array[wp.float32] | float | None) – Posture-control proportional gain, applied per controlled DOF. Must be non-negative. Pass a scalar to apply the same gain to every controlled DOF, an array of shape [total_controlled_dofs] to set them individually, or None to read inputs.null_space_stiffness each step. Must be None when use_null_space_posture_control=False.

  • null_space_damping (wp.array[wp.float32] | float | None) – Damping λ_null for the null-space projector’s own (JJᵀ + λ_null²I)⁻¹, independent of the primary task’s damping. Must be non-negative. Only meaningful when use_joint_limit_avoidance or use_null_space_posture_control is enabled — pass a scalar or an array of shape [controlled_robot_count] to bake a value, or leave it None to read inputs.null_space_damping each step (the default, and the only valid value when both are disabled). Unlike the primary damping, λ_null = 0 is only safe when every robot has at least as many controlled DOFs as its own task dimension (the number of nonzero null_space_axes entries) — otherwise the projector’s own JJᵀ is rank-deficient. That stronger, per-robot requirement is checked at construction only when baked; a live value is the caller’s responsibility there.

  • null_space_axes (wp.array[wp.spatial_vector] | wp.spatial_vector | None) – Which of the 6 canonical axes the null-space projector guarantees the secondary objective (joint-limit avoidance/posture control) won’t disturb — zero leaves that axis unprotected, nonzero protects it; only the sign matters, unlike axis_weight’s own soft magnitude. Defaults to axis_weight (every solved axis protected), but the two are independent: an axis can be softly solved for yet left unprotected, e.g. an under-actuated arm with too few DOFs to protect every solved axis and still have a usable null space left over. Unlike axis_weight, an all-zero row is legal — it protects no axes, so the secondary objective is free to move all of them. Only meaningful when use_joint_limit_avoidance or use_null_space_posture_control is enabled.

class Inputs#

Bases: object

Input struct returned by input().

joint_q/joint_qd cover the whole model, since forward kinematics depends on uncontrolled joints too; every other field is either per-robot or compact (one entry per controlled DOF). Optional fields are None when the corresponding feature is disabled at construction.

bandwidth: wp.array[wp.float32] | wp.indexedarray[wp.float32] | None#

Output velocity scale gain, shape [total_controlled_dofs]. None when baked at construction.

damping: wp.array[wp.float32] | wp.indexedarray[wp.float32] | None#

Damped-least-squares regularization λ, shape [controlled_robot_count]. None when baked at construction.

desired_tool_pose_world: wp.array[wp.transformf] | wp.indexedarray[wp.transformf]#

Desired tool pose [m, unitless quaternion], world frame, shape [controlled_robot_count].

joint_q: wp.array[wp.float32] | wp.indexedarray[wp.float32]#

Current joint positions [m or rad], shape [model.joint_coord_count].

joint_qd: wp.array[wp.float32] | wp.indexedarray[wp.float32]#

Current joint velocities [m/s or rad/s], shape [model.joint_dof_count].

null_space_damping: wp.array[wp.float32] | wp.indexedarray[wp.float32] | None#

Null-space projector damping λ_null, shape [controlled_robot_count]. None when both secondary objectives are disabled, or when baked at construction.

null_space_stiffness: wp.array[wp.float32] | wp.indexedarray[wp.float32] | None#

Posture-control proportional gain, shape [total_controlled_dofs]. None when disabled, or when baked at construction.

q_des_null: wp.array[wp.float32] | wp.indexedarray[wp.float32] | None#

Null-space posture target [m or rad], shape [total_controlled_dofs]. None unless use_null_space_posture_control=True.

class Outputs#

Bases: object

Output struct returned by output().

joint_q_target: wp.array[wp.float32] | wp.indexedarray[wp.float32]#

One-step-ahead target joint position [m or rad], shape [total_controlled_dofs] = joint_q + joint_qd_target * dt.

joint_qd_target: wp.array[wp.float32] | wp.indexedarray[wp.float32]#

Target joint velocity [m/s or rad/s], shape [total_controlled_dofs].

__init__(model, *, articulations=None, joints=None, tool_sites, axis_weight=None, bandwidth, damping, ik_method=DifferentialIKMethod.DAMPED_LEAST_SQUARES, adaptive_damping_min=None, adaptive_damping_max=None, adaptive_damping_threshold=None, truncated_svd_threshold=None, use_joint_limit_avoidance=False, joint_limit_avoidance_gain=0.0, joint_limit_avoidance_margin=0.0, joint_pos_lower=None, joint_pos_upper=None, use_null_space_posture_control=False, null_space_stiffness=None, null_space_damping=None, null_space_axes=None)#
input()#

Return a pre-allocated Inputs with zero-initialised arrays.

is_graphable()#
output()#

Return a pre-allocated Outputs with compact velocity/position arrays.

set_joint_limits(*, joint_pos_lower, joint_pos_upper)#

Update the joint position limits used by joint-limit avoidance, in place.

Parameters:
  • joint_pos_lower (wp.array[wp.float32]) – Lower joint position limit per controlled DOF [m or rad], shape [total_controlled_dofs].

  • joint_pos_upper (wp.array[wp.float32]) – Upper joint position limit per controlled DOF [m or rad], shape [total_controlled_dofs].

step(*, inputs, outputs, dt)#

Run one differential-kinematics step.

Computes forward kinematics and the tool-point Jacobian from model, then delegates the control law to the inner ControllerDifferentialIKModelFree.

Parameters:
  • inputs (Inputs) – Populated Inputs struct.

  • outputs (Outputs) – Outputs struct to write into.

  • dt (float | wp.array[wp.float32]) – Step duration [s], used to integrate joint_qd_target into joint_q_target.

property controlled_robot_count: int#

Number of robots with at least one controlled DOF.

property max_controlled_dofs: int#

Largest controlled-DOF count over the controlled robots.

property model_robot_count: int#

Number of articulations in model, controlled or not.

property q_start: wp.array[wp.int32]#

Model coordinate index of each controlled joint, shape [total_controlled_dofs].

property qd_start: wp.array[wp.int32]#

Model DOF index of each controlled joint, shape [total_controlled_dofs].

property tool_body: wp.array[wp.int32]#

Body index of each controlled robot’s tool site, shape [controlled_robot_count].

property tool_pose_world: wp.array[wp.transformf]#

World pose [m, unitless quaternion] of each controlled robot’s tool site as of the latest step(), shape [controlled_robot_count].

property tool_transform_body: wp.array[wp.transformf]#

Tool site’s transform [m, unitless quaternion] relative to its body, shape [controlled_robot_count].

property total_controlled_dofs: int#

Total controlled-DOF count across all robots, the length of every compact port.