Inverse Kinematics: Analytical & Numerical Solutions

Which joint angles put the tool where we want? Learn the inverse kinematics (IK) problem, existence (workspace) and multiplicity of solutions (elbow up/down, wrist flip, shoulder left/right), the analytical 2R solution with the law of cosines and atan2, kinematic decoupling for 6-axis arms with spherical wrists, numerical IK (Newton–Raphson with the Jacobian, gradient descent, damped least squares/Levenberg–Marquardt), joint limits, redundancy and null-space optimisation — with NumPy code comparing the analytical and numerical solutions of a 2R arm.

Tasks are specified in Cartesian space (put the gripper here, oriented like this), but motors are commanded in joint space. Inverse kinematics bridges the two, and it's harder than FK: there may be no solution, several, or infinitely many.

Analytical solutions are fast and give all solutions; numerical solvers handle any geometry, redundancy and constraints.

An analogy

IK is like reaching for a cup: your brain chooses shoulder and elbow angles to put your hand on it. You could reach with the elbow down or awkwardly up — both work (multiple solutions); if the cup is too far, no posture works (outside the workspace).

Solvability

A solution exists only if the target is inside the workspace (reachable positions) and dexterous workspace (reachable with the required orientation). A 6-DOF arm typically has up to 8 (sometimes 16) solutions for one pose. Joint limits and obstacles remove some; continuity with the current posture selects one.

Analytical IK

Closed-form approaches:

Numerical IK

Iteratively reduce the error e between desired and current pose: Newton–Raphson with J⁻¹ (fast near the solution, unstable near singularities), Jacobian transpose (simple, slow), damped least squares (robust, most used), or optimisation with constraints (joint limits, collision) as in TRAC-IK, KDL, MoveIt. Results depend on the initial guess — seed with the current joint state for continuity.

Redundancy

Robots with more DOF than the task needs (7-DOF arms, mobile manipulators, humanoids) have infinitely many solutions. The pseudo-inverse J⁺ gives the minimum-norm solution; the null-space term (I − J⁺J)z optimises secondary objectives (avoid joint limits, obstacles and singularities, maximise manipulability) without disturbing the task. Task-priority and whole-body controllers stack multiple objectives.

Formulas

Worked example: Reachability

Given: 2R arm 0.4/0.3, target (0.8, 0)

Find: Solvable?

Answer: No — outside workspace

Worked example: Elbow angle

Given: Target (0.45, 0.30)

Find: cos q₂.

Answer: 0.177 → q₂ = ±79.8°

Worked example: Wrist centre

Given: Tool at (0.8, 0, 0.5), tool z pointing down, d₆ = 0.1 m

Find: p_w.

Answer: (0.8, 0, 0.6)

Analytical and numerical IK of a 2R arm

import numpy as np
# Inverse kinematics: analytical 2R solution (elbow up/down) and numerical damped least squares
L1, L2 = 0.40, 0.30
x, y = 0.45, 0.30
c2 = (x*x + y*y - L1*L1 - L2*L2) / (2 * L1 * L2)
for name, s2 in (("elbow down", np.sqrt(1 - c2*c2)), ("elbow up", -np.sqrt(1 - c2*c2))):
    q2 = np.arctan2(s2, c2)
    q1 = np.arctan2(y, x) - np.arctan2(L2 * s2, L1 + L2 * c2)
    print(f"{name}: q1 = {np.degrees(q1):7.2f} deg, q2 = {np.degrees(q2):7.2f} deg")
def fk(q): return np.array([L1*np.cos(q[0]) + L2*np.cos(q[0]+q[1]), L1*np.sin(q[0]) + L2*np.sin(q[0]+q[1])])
def jac(q):
    s1, c1, s12, c12 = np.sin(q[0]), np.cos(q[0]), np.sin(q[0]+q[1]), np.cos(q[0]+q[1])
    return np.array([[-L1*s1 - L2*s12, -L2*s12], [L1*c1 + L2*c12, L2*c12]])
q, lam = np.array([0.1, 0.1]), 0.01
for it in range(50):
    e = np.array([x, y]) - fk(q)
    if np.linalg.norm(e) < 1e-9: break
    J = jac(q)
    q = q + J.T @ np.linalg.solve(J @ J.T + lam**2 * np.eye(2), e)
q = (q + np.pi) % (2 * np.pi) - np.pi              # wrap angles to [-180, 180)
print(f"damped least squares converged in {it} iterations: q = {np.round(np.degrees(q), 2).tolist()} deg, error {np.linalg.norm(e):.1e} m")
# elbow down: q1 =    0.60 deg, q2 =   79.80 deg
# elbow up: q1 =   66.78 deg, q2 =  -79.80 deg
# damped least squares converged in 14 iterations: q = [0.6, 79.8] deg, error 1.5e-11 m

Two postures reach the same point — the controller must pick one consistently (robot 'configuration' flags) to avoid sudden flips. The numerical solver, starting near q = (0.1, 0.1) rad, converges to the elbow-down solution in 14 iterations; its raw angles wrap around several turns, so they're normalised to ±180°. Damping (λ) keeps steps bounded near singularities where J⁻¹ blows up.

Common mistakes

Applications

Key takeaways

Going further