newton.actuators.JointSpaceResponse#
- class newton.actuators.JointSpaceResponse(model)[source]#
Bases:
objectEffective inverse-mass response for each articulation.
inverse_blocksholdsH_a^{-1}for each articulation [1/kg or 1/(kg·m²)], indexed by articulation-local DOF. Articulations with no entry have a zero response.refresh()computes it from a mass matrix it assembles itself.refresh_from_solve()reuses the solver’s own inertia, which is more faithful to the dynamics the effort is fed into. Both run entirely in device kernels.- __init__(model)#
Initialize the response and its scratch buffers for a model.
- refresh(state)#
Recompute
inverse_blocksfor state.Reads state without modifying it. Includes
joint_armature. Joint damping, joint limits, friction, contacts, constraint regularization and kinematic loop closures are absent, so the response comes out larger than anticipated and the solve yields a smaller effort than it otherwise would. Userefresh_from_solve()for a solver-faithful response; loop closures are missing from that path too, since a solver enforces them as constraints rather than folding them into its inertia.- Parameters:
state (newton.State) – Simulation state providing
joint_q/joint_qd.
- refresh_from_solve(solve_inverse, dof_map=None)#
Recompute
inverse_blocksfrom a solver’s own joint-space inertia.Prefer this over
refresh()when the solver can apply its inertia: the response then carries what the solver folds in (armature, tendon armature). The inertia never has to be materialized, so factorized solvers work too – the inverse is recovered one column at a time by back-substituting unit vectors.That is one solve per DOF, all on device, so this is CUDA-graph capturable if solve_inverse is. Call it once outside capture when dof_map has a different width than the model’s DOF layout; that first call resizes the scratch buffers.
With
SolverMuJoCo, which factorizes its inertia each step:def solve_inverse(x, y): mujoco_warp.solve_m(solver.mjw_model, solver.mjw_data, x, y) # Simulation loop response.refresh_from_solve(solve_inverse, dof_map=solver.mjc_dof_to_newton_dof)
- Parameters:
solve_inverse (Callable[[wp.array2d[wp.float32], wp.array2d[wp.float32]], None]) – Callable
(x, y)writingx = M^-1 y, both shaped[world_count, dof_count]in the solver’s own DOF order.dof_map (wp.array2d[wp.int32] | None) – Mapping from solver
[world, dof]to Newton DOF index, negative where a solver DOF has no Newton counterpart. IfNone, the solver is assumed to use Newton DOF order with the same DOF count in every world.
- property inverse_blocks: wp.array3d[wp.float32]#
Read-only per-articulation inverse mass blocks, shape [art_count, max_dofs, max_dofs].
inverse_blocks[a, i, j]is the(i, j)entry of articulationa’s inverse mass matrixH_a^{-1}(indices local to the articulation, 0-padded beyond its DOF count). The implicit effort mode uses the submatrix indexed by the actuator group’s DOFs.Update it through
refresh()orrefresh_from_solve(). Writing into the array directly is not supported: the padding beyond each articulation’s DOF count is assumed zero by the solve, and a partial write leaves no way to tell a stale response from a fresh one.