Numerical Inverse Kinematics
The Kinematics chapter gives a closed-form inverse for a two-joint planar arm. That tidy result does not generalize well: with more joints the arm is usually redundant, near straight postures the endpoint Jacobian can become singular, and targets may be outside the workspace. Numerical inverse kinematics (IK) handles all three cases by iterating from a seed configuration and driving the endpoint residual down.
This chapter is the basis for the numerical IK helper
compute_inverse_kinematics in skelarm. It uses the endpoint Jacobian from
Differential Kinematics and follows the
Levenberg-Marquardt damping argument in Sugihara (2009),
"Solvability-unconcerned inverse kinematics based on Levenberg-Marquardt method
with robust damping".
1. Problem statement
For the current planar library, the task is endpoint position IK. Let
The exact IK problem is
For an arm with \(n\) movable joints, \(q \in \mathbb{R}^{n}\), \(e \in \mathbb{R}^{2}\), and the endpoint Jacobian is
Because \(e = p^\ast - p(q)\), its derivative is \(-J(q)\). A first-order expansion around the current iterate \(q_k\) is therefore
where \(e_k = e(q_k)\) and \(J_k = J(q_k)\). Every solver below chooses a joint step \(\Delta q_k\) that makes the linearized residual smaller, then updates
with a step scale \(\alpha_k \in (0, 1]\). The solver uses \(\alpha_k = 1\) by
default (the step_scale option); line search can be added later if needed.
2. Newton-Raphson method
Newton-Raphson attacks the exact nonlinear equation \(e(q)=0\). In the square, non-singular case, the linearized equation
gives
This is the direct Jacobian iteration:
- Compute forward kinematics at \(q_k\).
- Compute \(e_k = p^\ast - p(q_k)\).
- Compute \(J_k\).
- Solve \(J_k \Delta q_k = e_k\).
- Set \(q_{k+1} = q_k + \alpha_k \Delta q_k\).
Newton-Raphson is attractive because convergence is fast when the seed is close to a regular solution. Its assumptions are also strict:
- the number of independent constraints must equal the number of unknowns;
- \(J_k\) must be square and full rank;
- an exact solution must exist;
- the initial guess must lie in the basin of attraction of that solution.
For skelarm, this direct method is mainly useful as a reference path for
two-joint endpoint IK. For \(n > 2\), the linear system is underdetermined. At a
singularity, the solve becomes ill-conditioned. For an unreachable target, the
equation has no zero and Newton-Raphson has no meaningful exact root to find.
3. Pseudoinverse and Gauss-Newton steps
When \(J_k\) is not square, the linearized equation is better viewed as a least squares problem:
For a redundant planar arm (\(J_k \in \mathbb{R}^{2 \times n}\) with \(n>2\)) and full row rank, the minimum-joint-motion solution is
This is the Moore-Penrose pseudoinverse step. It chooses the smallest \(\lVert\Delta q_k\rVert\) among all steps that satisfy the linearized endpoint equation.
A weighted form is useful once the solver supports more task components. Define the objective
where \(W_e\) is a positive diagonal task-weight matrix. For the current endpoint task, \(W_e = I_2\) is the natural default, while non-uniform weights could prioritize \(x\) or \(y\) accuracy. Omitting second-derivative terms in the Hessian of \(E\) gives the Gauss-Newton normal equation
The right-hand side
is the negative gradient direction written with the residual convention \(e = p^\ast - p(q)\). Gauss-Newton is the optimization counterpart of the pseudoinverse iteration, but it still inherits the singularity problem: if \(J_k^{T} W_e J_k\) loses rank, the normal equation is not safely invertible.
4. Singularity-robust inverse
The singularity-robust inverse (SR inverse) of Nakamura and Hanafusa adds a positive damping term to the pseudoinverse solve. For the unweighted endpoint case,
Equivalently, in the joint-space normal-equation form,
The two forms are algebraically equivalent for scalar damping; the first solves a \(2 \times 2\) task-space system, while the second matches the Levenberg-Marquardt form used later.
The SR inverse replaces each singular-direction gain \(1/\sigma_i\) with
Thus very small singular values no longer create huge joint steps. The price is that the linearized residual is not driven to zero in one step: the solver accepts a small task error in exchange for bounded joint motion and numerical stability.
The practical weakness is choosing \(\mu\). Too small behaves like the unstable pseudoinverse near singularities. Too large makes the solver slow and overly conservative even in well-conditioned poses.
5. Levenberg-Marquardt method
Levenberg-Marquardt (LM) applies the same damping idea to the weighted nonlinear least-squares objective \(E(q)\). At each iteration, solve
with
\(W_n\) is a positive diagonal joint-space damping matrix. Because \(W_n\) is positive definite, \(H_k\) is positive definite even when \(J_k\) is rank deficient, so the step is well-defined.
LM also has a useful local minimization interpretation. The step minimizes
The first term asks the linearized endpoint error to be small. The second term penalizes large joint changes. This is why LM behaves well for redundant arms: among steps with similar task error, it favors smaller joint displacement.
With \(W_e = I\) and \(W_n = \mu I\), LM reduces to the SR inverse / damped least-squares update. The distinction is mostly one of viewpoint:
- SR inverse emphasizes regularizing the Jacobian inverse near singularities.
- LM emphasizes minimizing a nonlinear residual with a trust-region-like penalty on the joint step.
6. Sugihara's robust damping weight
Sugihara's key proposal is to make the LM damping depend on the current residual energy:
where \(\overline{W}_n\) is a small positive diagonal bias. A simple default is
Sugihara's fuller treatment (Sugihara 2011, see References) does not
give one universal dimensionless default: the recommended bias is
link-scale-dependent, on the order of \(10^{-1}\) down to \(10^{-3}\,l^2\) for a
characteristic link length \(l\), because joint units, link scales, and task weights
set the numerical scale of \(J^TJ\). skelarm's damping option (default
\(10^{-3}\)) is a Sugihara-inspired endpoint specialization adapted to this
library's meter-scale planar arms — tune it with the arm's dimensions rather than
treating it as a universal constant.
The conditioning argument is easiest to see from the singular value decomposition of the weighted Jacobian. For the redundant case, use a full right-singular-vector matrix \(V \in \mathbb{R}^{n \times n}\) and a padded diagonal matrix \(D \in \mathbb{R}^{n \times n}\) whose diagonal entries are the squared singular values of \(W_e^{1/2}J_k\), with zeros in any null-space directions:
where \(r = \operatorname{rank}(J_k)\) and the nonzero singular values are ordered \(\sigma_1 \ge \dots \ge \sigma_r > 0\).
For scalar bias \(\overline{W}_n = \bar{w}I_n\),
so the condition number is
where \(\sigma_{\min}\) is the smallest padded singular value. For redundant endpoint IK, \(\sigma_{\min}=0\) whenever the arm has a Jacobian null space.
This explains the behavior Sugihara wanted:
- Solvable target, regular solution. As the iterate approaches the solution, \(E_k \to 0\), so the damping approaches the small bias \(\overline{W}_n\). The method behaves like lightly damped Gauss-Newton / LM and can converge quickly.
- Solvable target near a singularity. The bias \(\overline{W}_n\) keeps \(H_k\) from degenerating even when \(\sigma_{\min} \approx 0\). Since \(g_k \approx 0\) near a solution, a small positive bias is usually enough to prevent unstable steps without blocking convergence.
- Unreachable target. The residual cannot vanish, so \(E_k\) stays positive. Larger residuals automatically produce stronger damping. As \(E_k\) dominates the singular values, \(\kappa(H_k)\) moves toward \(1\), and the step magnitude is suppressed instead of exploding.
This is why Sugihara calls the method "solvability-unconcerned": the same iteration can be used whether the exact equation is solvable, redundant, singular, or unreachable. If the target is reachable, the residual should go to zero. If it is unreachable, the solver settles at the best configuration it finds — a local stationary point of the weighted residual (the projected iteration has no line search or global optimizer, and may stall at a joint limit), while keeping joint deviations small.
Sugihara notes that a line search is the formal way to strengthen global
convergence. His experiments found the residual-based damping reliable even
without one. skelarm's solver omits line search for now and instead reports
enough status information (iteration count, residual, status) to add it later.
7. The skelarm solver
skelarm implements this as compute_inverse_kinematics, which takes a method
argument selecting the step rule. The default is "lm_sugihara" (Sugihara-style
LM) because it handles the largest set of practical cases.
Available methods:
| Method | Step equation | Use |
|---|---|---|
"nr" |
\(J\Delta q=e\) | Square, full-rank Newton-Raphson reference path for two-joint IK |
"pseudoinverse" |
\(J^{T}(JJ^{T})^{-1}e\) | Redundant, well-conditioned reference path |
"sr_inverse" |
\(J^{T}(JJ^{T}+\mu I)^{-1}e\) | Damped least-squares baseline |
"lm" |
\((J^{T}W_eJ+W_n)\Delta q=J^{T}W_e e\) | General weighted LM |
"lm_sugihara" |
LM with \(W_n=E_kI+\overline{W}_n\) | Recommended default |
The solver loop is:
- Copy or set the seed \(q_0\) (clamped into the joint limits).
- Run
compute_forward_kinematics(skeleton). - Read the endpoint from
skeleton.links[-1].xe, skeleton.links[-1].ye. - Compute \(e_k = p^\ast - p(q_k)\) and \(E_k = \frac{1}{2}e_k^TW_e e_k\).
- Stop with
"converged"if \(\lVert e_k\rVert \le \varepsilon_e\). - Build \(J_k\) with
compute_jacobian(skeleton). - Compute \(\Delta q_k\) with the selected method; a singular linear solve stops
with
"singular". - Apply \(q_{k+1}=\operatorname{clip}(q_k+\alpha_k\Delta q_k)\), clamping each
joint into its
[qmin, qmax](recordingjoint_limits_hit). Steps are only ever clamped, never rejected. - Stop with
"stalled"if the post-clamp step \(\lVert q_{k+1}-q_k\rVert \le \varepsilon_q\). - Repeat until convergence, stall, singularity, or
max_iterations.
The solver returns an IKResult with:
q— final joint angles;position— final endpoint position;residualandresidual_norm— final residual vector and its norm;iterations— number of iterations performed;status— one of"converged","stalled","singular", or"max_iterations";joint_limits_hit— whether any step was clamped to a joint limit;success— whether the residual reached the position tolerance.
8. Joint limits and unreachable targets
Joint limits make the optimization constrained. The solver clamps each proposed
step into [qmin, qmax] (with np.clip) and records joint_limits_hit. Because
clamping changes the actual step and can cause stagnation at a limit, the solver
checks the post-clamp step size and reports "stalled" instead of looping
indefinitely. This is a projected iteration, not an active-set method, so it
can stop at a slightly suboptimal pose when a limit is active.
success has one strict meaning: the final residual norm is within the
position tolerance (\(\lVert e\rVert \le \varepsilon_e\)), evaluated on the pose the
solver ends at regardless of status. An unreachable target therefore always ends
with success=False — typically status="stalled" at a nonzero-residual pose
where the iteration stagnates (a local stationary point, or a joint-limit-clamped
configuration near one). The best-effort pose is still written back
to the skeleton, so callers that can use a nearest-approach configuration should
branch on success (or residual_norm) rather than assume the target was hit.
(The reference builder ik_joint_reference does exactly that: it keeps the
best-effort poses and emits one aggregated warning when samples deviate from the
task path.)
Sugihara-style LM is useful here because the damping grows with residual energy instead of relying on the caller to know in advance whether the target is inside the workspace.
9. Tests
The solver was developed test-first; tests/test_inverse_kinematics.py covers:
- a two-joint reachable target is reached within tolerance;
- redundant arms (3, 4, and 6 DOF) reach the same endpoint from different seeds with small residuals;
- a fully stretched (singular-Jacobian) seed still converges with the SR inverse
and LM, while the undamped pseudoinverse reports
"singular"; - an unreachable target terminates with a nonzero residual and
"stalled"; - joint limits are respected after every accepted step (
joint_limits_hit); - for targets generated from random valid configurations,
FK(IK(FK(q)))returns the original endpoint within tolerance.
References
- Sugihara, T. (2009), "Solvability-unconcerned inverse kinematics based on Levenberg-Marquardt method with robust damping", IEEE-RAS International Conference on Humanoid Robots — the residual-energy damping argument followed by §6.
- Sugihara, T. (2011), "Solvability-Unconcerned Inverse Kinematics by the Levenberg-Marquardt Method", Journal of the Robotics Society of Japan 29(3) — the fuller treatment, including the link-scale-dependent bias range.
skelarm's solver is a Sugihara-inspired endpoint specialization: the damping
scheme follows the papers, while the projected joint-limit clamping, the stall
criterion, and the default \(\bar{w}\) are adaptations of this library.