· Robotics  · 3 min read

Understanding Numerical Inverse Kinematics: A Simple Guide

Numerical inverse kinematics can iteratively solve for joint angles to reach a desired end-effector position using gradient descent with the Jacobian pseudo-inverse, suitable for planar manipulators and more complex robotic arms.

Numerical inverse kinematics can iteratively solve for joint angles to reach a desired end-effector position using gradient descent with the Jacobian pseudo-inverse, suitable for planar manipulators and more complex robotic arms.

Introduction

Numerical inverse kinematics is a powerful method to compute joint configurations that bring the robot’s end-effector to a desired position when analytical solutions are difficult. By leveraging the Jacobian matrix and iterative updates, the algorithm minimizes the difference between the current and target end-effector positions using a gradient descent-like approach. This method can handle singularities and is adaptable to more complex kinematic chains.


Forward Kinematics

Forward kinematics maps joint angles to an end-effector position. For a planar arm with two serially connected links of lengths L1L_1 and L2L_2 and joint angles θ1\theta_1 and θ2\theta_2:

x=L1cos(θ1)+L2cos(θ1+θ2)x = L_1 \cos(\theta_1) + L_2 \cos(\theta_1 + \theta_2) y=L1sin(θ1)+L2sin(θ1+θ2)y = L_1 \sin(\theta_1) + L_2 \sin(\theta_1 + \theta_2)

This provides the current end-effector position, which is compared to the target.


Jacobian Matrix

The Jacobian describes how small changes in joint angles affect the end-effector’s position:

J=[ ⁣L1sinθ1L2sin(θ1+θ2)L2sin(θ1+θ2)L1cosθ1+L2cos(θ1+θ2)L2cos(θ1+θ2)]J = \begin{bmatrix} -\!L_1 \sin\theta_1 - L_2 \sin(\theta_1 + \theta_2) & -L_2 \sin(\theta_1 + \theta_2) \\ L_1 \cos\theta_1 + L_2 \cos(\theta_1 + \theta_2) & L_2 \cos(\theta_1 + \theta_2) \end{bmatrix}

It is used to translate position errors into joint angle updates.


Loss Function and Gradient

The error vector is defined as:

e=[xtargetxcurrentytargetycurrent]e = \begin{bmatrix} x_{\text{target}} - x_{\text{current}} \\ y_{\text{target}} - y_{\text{current}} \end{bmatrix}

The squared norm of this vector serves as a loss function:

L=e2L = \| e \|^2

Gradient descent updates the joint angles proportionally to the Jacobian pseudo-inverse multiplied by the error:

Δθ=αJ+e\Delta \theta = \alpha J^+ e

Where J+J^+ is the pseudo-inverse of the Jacobian and α\alpha is the learning rate.


Algorithm Workflow

  1. Initialize: Start with an initial guess for the joint angles.

  2. Iterative Update:

    • Compute current end-effector position via forward kinematics.
    • Calculate the error vector and loss.
    • Compute the Jacobian and its pseudo-inverse.
    • Update joint angles using Δθ=αJ+e\Delta \theta = \alpha J^+ e.
  3. Convergence: Stop when the error norm is below a threshold or after a maximum number of iterations.


Example Implementation in Python

import numpy as np

# Forward kinematics
def forward_kinematics(q, L1, L2):
    x = L1 * np.cos(q[0]) + L2 * np.cos(q[0] + q[1])
    y = L1 * np.sin(q[0]) + L2 * np.sin(q[0] + q[1])
    return np.array([x, y])

# Jacobian computation
def jacobian(q, L1, L2):
    J11 = -L1 * np.sin(q[0]) - L2 * np.sin(q[0] + q[1])
    J12 = -L2 * np.sin(q[0] + q[1])
    J21 = L1 * np.cos(q[0]) + L2 * np.cos(q[0] + q[1])
    J22 = L2 * np.cos(q[0] + q[1])
    return np.array([[J11, J12], [J21, J22]])

# Numerical inverse kinematics
def inverse_kinematics_jacobian(target_pos, initial_q, L1, L2, max_iterations=1000, tolerance=1e-4, learning_rate=0.1):
    q = np.array(initial_q, dtype=float)
    for i in range(max_iterations):
        current_pos = forward_kinematics(q, L1, L2)
        error = target_pos - current_pos
        if np.linalg.norm(error) < tolerance:
            print(f"Converged in {i} iterations.")
            return q
        J = jacobian(q, L1, L2)
        J_pseudo_inverse = np.linalg.pinv(J)
        q += learning_rate * np.dot(J_pseudo_inverse, error)
    print("Did not converge within maximum iterations.")
    return q

Practical Insights

  • Using the Jacobian pseudo-inverse allows the algorithm to handle singular configurations gracefully.
  • Proper initialization of joint angles and tuning the learning rate are essential for convergence.
  • The method generalizes to manipulators with more degrees of freedom and more complex kinematic chains.
  • This approach is particularly useful when analytical solutions are unavailable or cumbersome to derive.
Back to Blog

Related Posts

View All Posts »
Understanding FABRIK: A Simple Guide

Understanding FABRIK: A Simple Guide

FABRIK(A Fast Iterative Solver for the Inverse Kinematics Problem) is a heuristic, iterative inverse kinematics solver that avoids complex matrix operations and singularities, providing smooth motion and fast convergence for robotic chains.