Inverse kinematics#
- mink.solve_ik.solve_ik(configuration: Configuration, tasks: Sequence[BaseTask], dt: float, solver: str, damping: float = 1e-12, safety_break: bool = False, limits: Sequence[Limit] | None = None, constraints: Sequence[Task | Elastic] | None = None, **kwargs) ndarray#
Solve the differential inverse kinematics problem.
Computes a velocity tangent to the current robot configuration. The computed velocity satisfies at (weighted) best the set of provided kinematic tasks.
Elasticconstraints are first held exactly. If every multiplier satisfies \(|\lambda_i| < \rho_i\), that solution is also the elastic one. Otherwise the penalized problem ofbuild_ik()is solved, as in the elastic mode of [SNOPT]. A step therefore costs one QP while the elastic constraints hold and two while one yields.- Parameters:
configuration (Configuration) – Robot configuration.
tasks (Sequence[BaseTask]) – List of kinematic tasks.
dt (float) – Integration timestep in [s].
solver (str) – Backend quadratic programming (QP) solver.
damping (float) – Levenberg-Marquardt damping applied to all tasks. Higher values improve numerical stability but slow down task convergence. This value applies to all dofs, including floating-base coordinates.
safety_break (bool) – If True, stop execution and raise an exception if the current configuration is outside limits. If False, print a warning and continue execution.
limits (Sequence[Limit] | None) – List of limits to enforce. Set to empty list to disable. If None, defaults to a configuration limit.
constraints (Sequence[Task | Elastic] | None) – List of tasks to enforce as equality constraints. These tasks will be satisfied exactly rather than in a least-squares sense. Wrap a task in
Elasticto let it yield when it cannot be met.kwargs – Keyword arguments to forward to the backend QP solver.
- Raises:
NotWithinConfigurationLimits – If the current configuration is outside the joint limits and safety_break is True.
NoSolutionFound – If the QP solver fails to find a solution.
- Returns:
Velocity \(v\) in tangent space.
- Return type:
ndarray
- mink.solve_ik.build_ik(configuration: Configuration, tasks: Sequence[BaseTask], dt: float, damping: float = 1e-12, limits: Sequence[Limit] | None = None, constraints: Sequence[Task | Elastic] | None = None) Problem#
Build the quadratic program given the current configuration and tasks.
The quadratic program is defined as:
\[\begin{split}\begin{align*} \min_{\Delta q} & \frac{1}{2} \Delta q^T H \Delta q + c^T \Delta q \\ \text{s.t.} \quad & G \Delta q \leq h \\ & A \Delta q = b \end{align*}\end{split}\]where \(v = \Delta q / dt\) is the velocity in tangent space.
Each penalized component \(i\) of an
Elasticconstraint, with residual \(r_i = J_i \Delta q + \alpha e_i\) and penalty \(\rho_i\), adds a slack \(s_i\) with cost \(\rho_i^{1/2} s_i\) and the rows \(-s_i \leq \rho_i^{1/2} r_i \leq s_i\). At the optimum \(s_i = \rho_i^{1/2} |r_i|\), so the added cost is the \(\ell_1\) penalty \(\rho_i |r_i|\). The decision variable is then \(x = [\Delta q; s]\). The penalty is linear in \(\Delta q\) away from \(r_i = 0\), so the objective also gains the trust region \(\tfrac{1}{2} \max(\rho) \|\Delta q\|^2\). Without it, a yielding component would step to the edge of the feasible set and chatter near singularities.- Parameters:
configuration (Configuration) – Robot configuration.
tasks (Sequence[BaseTask]) – List of kinematic tasks.
dt (float) – Integration timestep in [s].
damping (float) – Levenberg-Marquardt damping. Higher values improve numerical stability but slow down task convergence. This value applies to all dofs, including floating-base coordinates.
limits (Sequence[Limit] | None) – List of limits to enforce. Set to empty list to disable. If None, defaults to a configuration limit.
constraints (Sequence[Task | Elastic] | None) – List of tasks to enforce as equality constraints. These tasks will be satisfied exactly rather than in a least-squares sense. Wrap a task in
Elasticto let it yield when it cannot be met.
- Returns:
Quadratic program of the inverse kinematics problem. With elastic constraints, its first \(n_v\) variables are \(\Delta q\).
- Return type:
Problem
Elastic constraints#
- class mink.elastic.Elastic#
Equality constraint that yields instead of making the QP infeasible.
Passed through
constraintslike a plain task, it enforces \(J \Delta q = -\alpha e\) through the exact \(\ell_1\) penalty\[\rho^T \left| J \Delta q + \alpha e \right|,\]with \(|\cdot|\) taken componentwise. Let \(\lambda\) be the multiplier the task would have as a hard constraint. If \(|\lambda_i| < \rho_i\) for every component, the solution is that of the hard constraint [SoftConstraintsMPC]. A component that would need more force yields, pulling with constant force \(\rho_i\), and the QP stays feasible.
As with hard constraints, the task’s
costandlm_dampingare ignored. The penalty is the only per-component scale. A zero penalty leaves that component unconstrained. Penalties carry the units of the task error, so aFrameTaskusually takes a lower orientation penalty, letting orientation give way first.Example:
frame_task = FrameTask("attachment_site", "site", 1.0, 1.0) solve_ik( configuration, [posture_task], dt, "daqp", limits=limits, constraints=[Elastic(frame_task, penalty=[1e3] * 3 + [1e1] * 3)], )
- task#
The constrained task.
- penalty#
Per-component \(\ell_1\) penalty \(\rho\), a scalar or a vector with the dimension of the task error.