Tasks and limits#
Differential inverse kinematics computes a velocity \(v = \Delta q / \mathrm{d}t\) that reduces weighted task errors. Each task defines a residual \(e(q) \in \mathbb{R}^k\) driven toward zero and a Jacobian \(J(q)\) such that \(J \Delta q \approx -\alpha e\) at first order (see Notation).
mink-warp uses the same tasks vs limits split as Mink:
Weighted least-squares terms stacked into \(W, e\). Can conflict; the solver minimises combined error.
FrameTask— frame poseRelativeFrameTask— pose relative to another framePostureTask— nominal configurationComTask— center of massEqualityConstraintTask— MuJoCo equality rows (connect, weld, …)DampingTask— velocity regularizationJointLimitTask— soft limit penalty
Enforced by ConstrainedSolver via ADMM on the
same \(H, c\) as DLS. Mink’s G Δq ≤ h form; two GPU paths (box /
general inequality).
ConfigurationLimit— joint boundsVelocityLimit— per-step velocity capCollisionAvoidanceLimit— geom-pair normal velocityLinearInequalityLimit— constant half-spaces
Frame task#
task = mw.FrameTask(
"attachment_site", "site",
position_cost=1.0,
orientation_cost=1.0,
gain=0.8,
lm_damping=1.0,
)
task.set_target_from_configuration(cfg)
Posture and damping#
Regularize redundant dofs and avoid drift:
posture = mw.PostureTask(model, cost=1e-2)
posture.set_target_from_configuration(cfg)
damping = mw.DampingTask(model, cost=1e-3)
Center of mass#
com = mw.ComTask(cost=np.array([1.0, 1.0, 0.1]))
com.set_target_from_configuration(cfg)
Relative frame#
Regulate a frame pose in another frame’s coordinates (e.g. hand relative to torso):
rel = mw.RelativeFrameTask(
"left_palm", "site",
"torso_link", "body",
position_cost=5.0, orientation_cost=0.5,
)
rel.set_target_from_configuration(cfg)
Equality constraints#
Regulate MuJoCo equality rows (closed chains). Uses host mj_forward per world:
eq = mw.EqualityConstraintTask(model, cost=500.0, gain=0.5)
tasks = [frame, posture, eq]
Collision avoidance#
Configuration-dependent inequalities G Δq ≤ h (forces the general ADMM path):
limits = [
mw.ConfigurationLimit(model),
mw.CollisionAvoidanceLimit(
model,
geom_pairs=[(["wrist_3_link"], ["floor", "wall"])],
),
]
v = mw.solve_ik(cfg, tasks, dt, limits=limits)
Soft vs hard joint limits#
Soft (penalty in the task stack, unconstrained DLS):
soft = mw.JointLimitTask(model, cost=10.0)
Hard (never violate bounds — Mink limits=None default):
v = mw.solve_ik(cfg, tasks, dt, limits=None) # default ConfigurationLimit
# or explicit
v = mw.solve_ik(cfg, tasks, dt, limits=[mw.ConfigurationLimit(model)])
Hard velocity cap#
limits = [
mw.ConfigurationLimit(model),
mw.VelocityLimit(model, 3.0),
]
v = mw.solve_ik(cfg, tasks, dt, limits=limits)
General inequalities#
For half-spaces or coupled bounds that are not a per-dof box, use
LinearInequalityLimit or subclass
Limit.
See Constrained IK (hard limits) for the box vs general ADMM paths and tuning.
Typical stack#
tasks = [frame, posture, mw.DampingTask(model, cost=1e-3)]
limits = [mw.ConfigurationLimit(model)]
solver = mw.ConstrainedSolver(cfg, limits=limits)
solver.solve_and_integrate(tasks, dt=0.01)
See Solver backends, Constrained IK (hard limits), and Tasks for full API details.
Examples#
Runnable mjviser demos (numbered by complexity):
# |
Script |
Uses |
|---|---|---|
01 |
|
|
02 |
|
|
03 |
|
|
04 |
|
Self-collision |
05 |
|
|
See Examples.