Kinematics

Kinematics describes the geometry of motion — how joint angles relate to end-effector position — without considering forces. Forward kinematics computes position from joint angles. Inverse kinematics computes joint angles from a desired position.

Why It Matters

Every robot arm, legged robot, and manipulator needs kinematics. Forward kinematics tells you where the tool is. Inverse kinematics tells you how to move joints to reach a target. Without this, you can’t plan movements or control a robot’s end-effector.

Forward Kinematics

Given joint angles → compute end-effector position and orientation.

      θ₁          θ₂
  ●────────l₁────────●────────l₂────────→ (x, y)
 base         joint 1          end effector
import numpy as np
 
def forward_2link(l1, l2, theta1, theta2):
    """Forward kinematics for a 2-link planar arm."""
    x = l1 * np.cos(theta1) + l2 * np.cos(theta1 + theta2)
    y = l1 * np.sin(theta1) + l2 * np.sin(theta1 + theta2)
    return x, y
 
# Both links 1m, both at 45°
x, y = forward_2link(1.0, 1.0, np.pi/4, np.pi/4)
print(f"End effector at ({x:.3f}, {y:.3f})")  # (0.707, 1.707)

Homogeneous Transformation Matrices

Each joint contributes a 4×4 transformation (rotation + translation):

T = [R  d]    R = 3×3 rotation matrix
    [0  1]    d = 3×1 translation vector

T_total = T₁ · T₂ · T₃ · ... · Tₙ   (chain multiply from base to tip)
def transform_2d(theta, length):
    """2D homogeneous transform: rotate by theta, translate by length."""
    c, s = np.cos(theta), np.sin(theta)
    return np.array([
        [c, -s, length * c],
        [s,  c, length * s],
        [0,  0,          1]
    ])
 
# Forward kinematics via matrix chain
T = transform_2d(np.pi/4, 1.0) @ transform_2d(np.pi/4, 1.0)
x, y = T[0, 2], T[1, 2]  # extract position from last column

Inverse Kinematics

Given desired end-effector position → compute joint angles. This is harder because:

  • Multiple solutions: elbow-up vs elbow-down configurations
  • No solution: target outside workspace (too far to reach)
  • Singularities: configurations where degrees of freedom are lost

Using the law of cosines:

def inverse_2link(l1, l2, x, y):
    """Inverse kinematics for 2-link planar arm (elbow-up solution)."""
    d = np.sqrt(x**2 + y**2)
    if d > l1 + l2 or d < abs(l1 - l2):
        return None  # unreachable
 
    cos_theta2 = (x**2 + y**2 - l1**2 - l2**2) / (2 * l1 * l2)
    theta2 = np.arccos(np.clip(cos_theta2, -1, 1))  # elbow-up
    # theta2 = -np.arccos(...)  for elbow-down
 
    theta1 = np.arctan2(y, x) - np.arctan2(l2 * np.sin(theta2),
                                             l1 + l2 * np.cos(theta2))
    return theta1, theta2
 
# Reach for position (1.0, 1.0)
result = inverse_2link(1.0, 1.0, 1.0, 1.0)
if result:
    theta1, theta2 = result
    print(f"θ₁={np.degrees(theta1):.1f}°, θ₂={np.degrees(theta2):.1f}°")

Numerical IK (For Complex Robots)

For robots with 6+ joints, analytical solutions are often impractical. Use iterative methods:

  1. Compute current end-effector position (forward kinematics)
  2. Compute error to target
  3. Use the Jacobian to map joint velocity → end-effector velocity
  4. Compute joint update: Δθ = J⁻¹ · Δx (or J^T or damped least squares)
  5. Repeat until converged

DH Parameters (Denavit-Hartenberg)

A systematic convention for describing any serial robot using 4 parameters per joint:

ParameterSymbolMeaning
Link lengthaDistance between joint axes along the common normal
Link twistαAngle between joint axes about the common normal
Joint offsetdDistance along joint axis (variable for prismatic joints)
Joint angleθRotation about joint axis (variable for revolute joints)

Each joint produces a standard 4×4 transform:

T_i = Rot_z(θ) · Trans_z(d) · Trans_x(a) · Rot_x(α)

DH parameters for a full robot arm are typically provided in the robot’s datasheet.

Jacobian

The Jacobian J maps joint velocities to end-effector velocities:

ẋ = J(θ) · θ̇

J is a 6×n matrix (for 3D position + orientation, n joints)

At a singularity, the Jacobian loses rank — the robot can’t move in certain directions (like a fully extended arm can’t move radially). Near singularities, joint velocities become very large.

Workspace

The set of all positions the end-effector can reach:

2-link arm workspace:
  Outer boundary: circle of radius l₁ + l₂ (full extension)
  Inner boundary: circle of radius |l₁ - l₂| (folded back)
  Reachable workspace: annular ring between the two circles