Robotics · Inverse Kinematics
📅 July 2026 ⏱ ≈ 13 min read 🎯 Intermediate–Advanced · Last updated: 9 July 2026

Jacobian-based IK vs FABRIK: a comparison

When a robot arm or animated skeleton needs to reach a target, two fundamentally different families of algorithms compete for the job: Jacobian-based methods, rooted in the arm's exact velocity kinematics, and FABRIK (Forward And Backward Reaching Inverse Kinematics), a purely geometric iterative solver. Neither is universally "better" — they trade accuracy, speed, and generality in different directions.

TL;DR: Jacobian-based IK computes exact joint updates from the arm's velocity matrix, handling orientation and joint limits well but costing O(n²)-O(n³) per step and needing damping near singularities. FABRIK skips matrices entirely, snapping joints along links in O(n) per iteration with no singularities — faster and simpler for games and animation, while Jacobian methods suit real robots and torque-aware planning.

The inverse kinematics problem

Forward kinematics computes end-effector pose from joint angles — straightforward matrix chain multiplication. Inverse kinematics (IK) asks the opposite: given a desired end-effector position (and often orientation), what joint angles achieve it? For a serial chain with more than a few joints, this system is usually nonlinear and either under-determined or over-determined — there may be no exact solution, infinitely many solutions, or a solution that's hard to find analytically. Both Jacobian methods and FABRIK are iterative numerical solvers for exactly this situation.

Jacobian-based IK

The Jacobian matrix J relates small changes in joint angles Δθ to the resulting small change in end-effector position/orientation Δx:

Δx = J(θ) · Δθ
J is an (m × n) matrix: m = task-space DOF (e.g. 6), n = number of joints

Each column j of J is the instantaneous velocity contribution of joint j — for a revolute joint, column j = z_j × (p_end − p_j), where z_j is the joint's rotation axis and p_j its position. To move the end-effector toward a target, invert the relationship and iterate:

e = target − current_position
Δθ = J⁺ · e // J⁺ = pseudo-inverse (or transpose, see below)
θ = θ + α · Δθ // α = small step size
repeat until |e| < tolerance

Three common variants differ in how they turn J into an update:

Singularities and damped least squares

A kinematic singularity occurs when the arm is fully outstretched or two joint axes align, causing J to lose rank — some directions of motion become momentarily unreachable no matter how the joints move. Near a singularity, the plain pseudo-inverse divides by a near-zero singular value and produces enormous, unstable joint velocity commands. Damped least squares (DLS), also called the Levenberg-Marquardt approach to IK, adds λ²I before inverting specifically to keep this bounded:

Δθ = Jᵀ · (J·Jᵀ + λ²I)⁻¹ · e
λ ≈ 0 far from singularities (behaves like JPI); λ larger near singularities (trades speed for stability)

This is the reason production robotics IK solvers (MoveIt's KDL plugin, most game-engine IK) default to DLS rather than a raw pseudo-inverse.

FABRIK, briefly

FABRIK (Forward And Backward Reaching Inverse Kinematics) sidesteps the Jacobian and matrix inversion entirely: it treats the chain as a sequence of rigid links and repeatedly snaps each joint onto the line toward its neighbor, alternating a backward pass (from end-effector to root) and a forward pass (from root back to end-effector), each time preserving link lengths exactly:

Backward: set J_n = target, then for i = n−1..0: J_i = J_{i+1} + L_i · normalize(J_i − J_{i+1})
Forward: reset J_0 = anchor, then for i = 0..n−1: J_{i+1} = J_i + L_i · normalize(J_{i+1} − J_i)
repeat until |J_n − target| < tolerance

For the full derivation and implementation see our dedicated article on IK FABRIK from scratch.

Head-to-head comparison

Property Jacobian (DLS) FABRIK
Core operation Matrix construction + inversion each step Vector normalize + scale, no matrices
Cost per iteration O(n²)–O(n³) O(n)
Typical iterations to converge 10–50 (gradient-descent-like) 4–15 (very fast geometric convergence)
Handles orientation targets Yes, natively (task-space includes rotation) Not natively — needs extensions
Handles branching chains Yes, with a stacked Jacobian Yes, with documented extensions
Singularity behavior Needs explicit damping (DLS) No singularities — purely geometric
Joint angle limits Natural to add as null-space projection Approximate, via post-hoc angle clamping
Physical plausibility Respects actual joint velocity dynamics Geometric only — no notion of joint velocity/torque
Best for Real robot arms, torque-aware planning, redundant-DOF arms Character animation, real-time games, tentacles/spider legs

JavaScript: Jacobian transpose solver

A minimal 2D Jacobian-transpose solver for an n-link planar arm — note how much more linear-algebra machinery this needs compared to FABRIK's pure vector arithmetic:

function jacobianTransposeStep(joints, angles, target, alpha = 0.01) {
  const n = angles.length;
  const end = forwardKinematics(joints, angles); // end-effector position
  const ex = target.x - end.x, ey = target.y - end.y;

  const dTheta = new Array(n).fill(0);
  let px = 0, py = 0, angleSum = 0;
  const positions = [{x: 0, y: 0}];

  // forward pass to get each joint's world position (needed for Jacobian columns)
  for (let i = 0; i < n; i++) {
    angleSum += angles[i];
    px += joints[i].length * Math.cos(angleSum);
    py += joints[i].length * Math.sin(angleSum);
    positions.push({x: px, y: py});
  }

  // Jacobian column i = z × (end − joint_i), in 2D this reduces to a perpendicular vector
  for (let i = 0; i < n; i++) {
    const rx = end.x - positions[i].x, ry = end.y - positions[i].y;
    const jCol = { x: -ry, y: rx }; // perpendicular = 2D cross product with z-axis
    // Δθ_i = J_i^T · e  (dot product of this column with the error vector)
    dTheta[i] = jCol.x * ex + jCol.y * ey;
  }

  return angles.map((a, i) => a + alpha * dTheta[i]);
}
Note: this transpose method needs a hand-tuned alpha step size and typically 20–40 iterations for smooth convergence — compare to FABRIK's typical 4–15 iterations with zero tuning parameters at all.

Choosing between them

In practice, many production systems use both: FABRIK (or CCD) for fast approximate reaching, refined by a few Jacobian-DLS iterations when precise end-effector orientation is required.

🦾 Try Inverse Kinematics

Compare FABRIK reaching behaviour live, right in the browser.

Open simulation →