Inverse kinematics: iterative (Jacobian-based) methods
When closed-form IK doesn't exist (7+ DOF, redundant arms), you iterate. Damped least squares, null-space projection, and the practical recipes that make Jacobian-based IK actually converge.
For a 7-DOF arm (Franka, Kinova, Sawyer), closed-form IK doesn't exist in the general case. The extra DOF gives a "self-motion manifold" of valid solutions for any reachable target. You don't pick the right answer analytically — you iterate from the current configuration toward one. Jacobian-based IK is what every modern arm controller uses for redundant manipulators.
The setup
Forward kinematics maps joints to pose: . Differentiating both sides:
is the 6×n Jacobian. To move the end-effector at velocity , you need joint velocities that satisfy this. Solving for is the IK step.
The naive approach: pseudoinverse
is the Moore-Penrose pseudoinverse. For a tall (more rows than columns, fewer DOF than 6), it solves the least-squares problem. For a wide (more DOF than 6, redundant), it picks the minimum-norm solution.
Wrap this in a loop:
for step in range(max_steps):
x = forward_kinematics(q)
error = target - x
if np.linalg.norm(error) < tol:
return q
J = compute_jacobian(q)
dq = np.linalg.pinv(J) @ error
q = q + alpha * dq
return None # didn't converge
Twenty lines. Works on simple cases. Fails on hard ones.
Why pseudoinverse fails near singularities
At a singularity, J loses rank. blows up — small Cartesian errors require huge joint velocities. The arm flails. Singularities happen at workspace boundaries, fully-extended configurations, and certain joint alignments.
Fix: damped least squares (DLS):
The damping bounds the magnitude of joint velocities even when is near-singular. Trade-off: small (e.g., 0.001) — accurate but unstable near singularities; large (e.g., 0.1) — stable but inaccurate.
Practical pattern: variable damping. Start with small. If the smallest singular value of drops below a threshold, increase . Standard in IKFast and TRAC-IK.
Newton-Raphson with line search
Pseudoinverse gives the descent direction; the magnitude is uncertain. Use a line search to ensure each step actually reduces the error:
for step in range(max_steps):
x = forward_kinematics(q)
error = target - x
if np.linalg.norm(error) < tol: return q
J = compute_jacobian(q)
dq = damped_pseudoinverse(J, lambda_=0.01) @ error
# Line search
alpha = 1.0
while alpha > 0.01:
q_new = q + alpha * dq
new_error = target - forward_kinematics(q_new)
if np.linalg.norm(new_error) < np.linalg.norm(error):
q = q_new
break
alpha *= 0.5
else:
return None # stuck
Slower per iteration but converges from worse initial guesses. Used by ROS's kdl_kinematics_plugin.
Null-space projection: the redundancy bonus
For redundant arms (n > 6 DOF), there's a null space of joint velocities that don't affect the end-effector. Use it to satisfy secondary objectives — joint-limit avoidance, manipulability maximization, obstacle avoidance — while still tracking the primary task.
Where is your secondary motion (gradient of a cost function). The projection keeps it from disturbing the primary task.
Concrete example: keep joint 4 near zero while moving the end-effector:
q_secondary = np.zeros(7)
q_secondary[3] = -k * (q[3] - q4_target) # pull joint 4 toward target
N = np.eye(7) - np.linalg.pinv(J) @ J
dq = np.linalg.pinv(J) @ error + N @ q_secondary
The arm tracks the goal AND obeys the secondary preference. Magic.
Practical solver options
- KDL (Orocos Kinematics & Dynamics Library): the legacy default. Pseudoinverse-based; works but stalls near singularities.
- TRAC-IK: combines KDL with sequential quadratic programming for joint-limit handling. Default for many production setups.
- BiotIK / IK-Geometric: closed-form when possible, iterative fallback. Used in ROS for 6-DOF spherical-wrist arms.
- BIO-IK: meta-heuristic / genetic algorithm; handles obstacles + multi-objective in one solve. Slower but more flexible.
- cuRobo: NVIDIA's GPU-accelerated IK (and motion planning). 100×+ speedup on hard problems.
The convergence checklist
If your iterative IK isn't converging, in order:
- Is the target reachable? Check workspace bounds.
- Is the initial guess reasonable? Far guesses → far convergence; warm-start from the previous solution.
- Is the Jacobian numerically correct? Compare analytical to finite-difference Jacobian on a test case.
- Are step sizes small enough? Reduce learning rate.
- Is damping large enough? Try increasing .
- Are joint limits binding? Add penalty for exceeding limits.
Skip steps and you're guessing. Run them in order and you find the cause.
When iterative IK doesn't work
- Discontinuous solutions: small task changes lead to large joint reconfigurations. Pure iterative IK can flip; add a continuity constraint or use trajectory-aware IK.
- Hard joint-limit constraints: pseudoinverse can't enforce limits cleanly. Use SQP-based solvers (TRAC-IK, BiotIK).
- Real-time-critical paths: IK at 1 kHz with full optimization is hard. Cache previous solutions; do incremental updates only.
- Avoiding obstacles in arm space: classical IK ignores arm-link collisions. Add it as a secondary cost or use Bio_IK.
What modern IK looks like in 2026
The state-of-the-art is no longer one algorithm. Production stacks combine:
- Analytical IK when the arm geometry has a closed form (most 6-DOF spherical-wrist).
- Damped Jacobian iteration as a fallback or for redundant arms.
- Sampling + optimization for hard collision-aware problems.
- Learned IK (neural network warm-starts an iterative solver). Recent research; not yet production-default.
For 95% of work, pick TRAC-IK or KDL and move on. Reach for cuRobo or BIO-IK only when you hit specific limitations.
Exercise
For a 6-DOF arm in MuJoCo, implement the damped pseudoinverse IK solver above. Generate 100 random reachable target poses; measure success rate, mean iterations, max iterations. Then implement the null-space-projection version that pulls each joint toward zero while reaching the target. Watch the arm prefer "natural" configurations even when redundancy lets it.
Next
The Jacobian itself — the matrix you've been using. What it is, how to compute it, and what its singular values tell you.
Comments
Sign in to post a comment.