Mink API parity#

mink-warp mirrors Mink [Mink] where it helps porting examples and tests. The implementation differs: Mink solves a QP on CPU with qpsolvers; mink-warp assembles normal equations on GPU and uses Warp linear solvers.

What matches#

Mink

mink-warp

Configuration

Configuration(model, nworld=…) — batched; q is wp.array

FrameTask, RelativeFrameTask, PostureTask, ComTask, DampingTask, EqualityConstraintTask

FrameTask, RelativeFrameTask, PostureTask, ComTask, DampingTask, EqualityConstraintTask — body-frame Jacobian convention

CollisionAvoidanceLimit

CollisionAvoidanceLimit (host distance query per world)

ConfigurationLimit / joint-limit task

JointLimitTask / ConfigurationLimitTask (soft) + ConfigurationLimit (hard)

VelocityLimit

VelocityLimit (hard, box + dense rows)

Custom Limit.compute_qp_inequalities (Mink)

scatter_inequalities + LinearInequalityLimit; subclass for q-dependent rows

SE3, SO3

SE3, SO3 — host Lie helpers for targets; device ops in lie/wp_ops

solve_ik(configuration, tasks, dt)

solve_ik() — same call shape; returns wp.array velocity

Residual form \(H = W^T W\), \(c = -W^T e\)

Same stacking in compute_residual

What differs#

Batching. Every buffer is leading-dimension nworld. Targets are wp.array (nworld, …) or broadcast from a single pose.

Device types. Hot-path arrays are wp.array. Use .numpy(), to_wp(), or *_numpy / *_se3 helpers at boundaries.

Solvers. Mink selects a QP backend ("daqp", etc.). mink-warp uses DLSSolver by default; LM / L-BFGS / constrained backends are GPU-native (see Solver backends).

Limits. Mink enforces hard limits inside the QP (G Δq h). mink-warp offers:

Box limits use a fast box-ADMM path; general rows use reduced OSQP-ADMM (see Constrained IK (hard limits)). solve_ik(..., limits=None) matches Mink’s default ConfigurationLimit.

Integration. Both use MuJoCo’s position integrator semantics; mink-warp routes through mjwarp and uses out-of-place qpos writes for CUDA graphs.

Porting checklist#

  1. Replace Configuration(model) with Configuration(model, nworld=B).

  2. Upload targets once: task.set_target(wp.array(...)) or set from configuration.

  3. Replace solve_ik(..., "daqp") with solve_ik(...) (unconstrained) or solve_ik(..., limits=None) (Mink default joint limit).

  4. Keep integrate_inplace in the loop unless using solve_and_integrate.

  5. Run parity tests: uv run pytest tests/ -k mink (requires mink extra).