Denavit-Hartenberg (DH) Parameters
Denavit-Hartenberg convention for systematically describing robot manipulator kinematics using 4 parameters per joint.
Overview
Denavit-Hartenberg (DH) parameters provide a standardized way to describe the kinematic chain of a robot manipulator using only 4 parameters per joint.
Purpose:
- Systematic representation of serial manipulators
- Standardized coordinate frame assignment
- Compact kinematic description
- Foundation for forward and inverse kinematics
The Four DH Parameters
| Parameter | Symbol | Description |
|---|---|---|
| Link Length | $a_i$ | Distance along $x_i$ from $z_{i-1}$ to $z_i$ |
| Link Twist | $\alpha_i$ | Angle about $x_i$ from $z_{i-1}$ to $z_i$ |
| Link Offset | $d_i$ | Distance along $z_{i-1}$ from $x_{i-1}$ to $x_i$ |
| Joint Angle | $\theta_i$ | Angle about $z_{i-1}$ from $x_{i-1}$ to $x_i$ |
Joint Variables
- Revolute joint: $\theta_i$ varies (joint variable), $d_i$ is constant
- Prismatic joint: $d_i$ varies (joint variable), $\theta_i$ is constant
DH Transformation Matrix
Interactive DH Parameter Visualization
Classic DH Convention (Craig)
Transformation from frame $i-1$ to frame $i$:
$$ T_i^{i-1} = \begin{bmatrix} \cos\theta_i & -\sin\theta_i\cos\alpha_i & \sin\theta_i\sin\alpha_i & a_i\cos\theta_i \\ \sin\theta_i & \cos\theta_i\cos\alpha_i & -\cos\theta_i\sin\alpha_i & a_i\sin\theta_i \\ 0 & \sin\alpha_i & \cos\alpha_i & d_i \\ 0 & 0 & 0 & 1 \end{bmatrix} $$
Transformation Sequence:
- Rotate about $z_{i-1}$ by $\theta_i$
- Translate along $z_{i-1}$ by $d_i$
- Translate along $x_i$ by $a_i$
- Rotate about $x_i$ by $\alpha_i$
Python Implementation
1import numpy as np
2
3def dh_matrix(theta, d, a, alpha):
4 """
5 Compute DH transformation matrix (Classic convention)
6
7 Args:
8 theta: Joint angle (radians)
9 d: Link offset
10 a: Link length
11 alpha: Link twist (radians)
12
13 Returns:
14 4x4 homogeneous transformation matrix
15 """
16 ct = np.cos(theta)
17 st = np.sin(theta)
18 ca = np.cos(alpha)
19 sa = np.sin(alpha)
20
21 T = np.array([
22 [ct, -st*ca, st*sa, a*ct],
23 [st, ct*ca, -ct*sa, a*st],
24 [0, sa, ca, d ],
25 [0, 0, 0, 1 ]
26 ])
27
28 return T
29
30# Example: Single joint
31theta = np.pi/4 # 45 degrees
32d = 0.1
33a = 0.5
34alpha = np.pi/2 # 90 degrees
35
36T = dh_matrix(theta, d, a, alpha)
37print("Transformation matrix:")
38print(T)
Frame Assignment Rules
Classic DH Rules
- $z_i$ axis: Along the axis of joint $i+1$
- $x_i$ axis: Common normal between $z_{i-1}$ and $z_i$
- $y_i$ axis: Complete right-hand coordinate system
- Origin: Intersection of $x_i$ and $z_i$
Step-by-Step Procedure
1Step 1: Identify joint axes
2 - Mark the axis of rotation (revolute) or translation (prismatic)
3 - These become the z-axes
4
5Step 2: Establish base frame
6 - z₀ along joint 1 axis
7 - x₀ and y₀ chosen for convenience (usually align with world frame)
8
9Step 3: For each joint i (i = 1 to n):
10 a. Draw z_i along joint i+1 axis
11 b. Find common normal between z_{i-1} and z_i
12 c. Place x_i along this common normal
13 - If z_{i-1} and z_i intersect: x_i perpendicular to both
14 - If z_{i-1} and z_i are parallel: x_i arbitrary (choose convenient)
15 d. Place origin at intersection of x_i and z_i
16 e. Complete frame with y_i (right-hand rule)
17
18Step 4: Measure DH parameters
19 a. a_i: distance along x_i from z_{i-1} to z_i
20 b. α_i: angle about x_i from z_{i-1} to z_i (right-hand rule)
21 c. d_i: distance along z_{i-1} from x_{i-1} to x_i
22 d. θ_i: angle about z_{i-1} from x_{i-1} to x_i (right-hand rule)
Modified DH Convention (Khalil)
Alternative convention with frame attached to current joint instead of next joint.
Modified DH Matrix
1def modified_dh_matrix(theta, d, a, alpha):
2 """
3 Modified DH transformation (Khalil convention)
4
5 Differences from classic:
6 - Frame i attached to joint i (not i+1)
7 - Different parameter interpretation
8 """
9 ct = np.cos(theta)
10 st = np.sin(theta)
11 ca = np.cos(alpha)
12 sa = np.sin(alpha)
13
14 T = np.array([
15 [ct, -st, 0, a ],
16 [st*ca, ct*ca, -sa, -d*sa],
17 [st*sa, ct*sa, ca, d*ca],
18 [0, 0, 0, 1 ]
19 ])
20
21 return T
Classic vs Modified DH
| Aspect | Classic DH | Modified DH |
|---|---|---|
| Frame attachment | Frame $i$ at joint $i+1$ | Frame $i$ at joint $i$ |
| Parameter order | Rot($z$) → Trans($z$) → Trans($x$) → Rot($x$) | Trans($x$) → Rot($x$) → Trans($z$) → Rot($z$) |
| Common normal | From $z_{i-1}$ to $z_i$ | From $z_i$ to $z_{i+1}$ |
| Usage | More common in textbooks | Used in some software (Khalil) |
Forward Kinematics
Computing End-Effector Pose
1def forward_kinematics(dh_params):
2 """
3 Compute forward kinematics from DH parameters
4
5 Args:
6 dh_params: List of dicts with keys 'theta', 'd', 'a', 'alpha'
7
8 Returns:
9 4x4 transformation matrix from base to end-effector
10 """
11 T = np.eye(4)
12
13 for params in dh_params:
14 Ti = dh_matrix(**params)
15 T = T @ Ti
16
17 return T
18
19# Example: 2-link planar arm
20dh_params = [
21 {'theta': np.pi/4, 'd': 0, 'a': 1.0, 'alpha': 0},
22 {'theta': np.pi/3, 'd': 0, 'a': 0.8, 'alpha': 0}
23]
24
25T = forward_kinematics(dh_params)
26print("End-effector position:", T[:3, 3])
27print("End-effector orientation:")
28print(T[:3, :3])
Extract Position and Orientation
1def extract_pose(T):
2 """Extract position and orientation from transformation matrix"""
3 # Position
4 position = T[:3, 3]
5
6 # Orientation (rotation matrix)
7 rotation = T[:3, :3]
8
9 # Convert to Euler angles (ZYX convention)
10 import scipy.spatial.transform as tf
11 r = tf.Rotation.from_matrix(rotation)
12 euler_angles = r.as_euler('zyx', degrees=False)
13
14 return {
15 'position': position,
16 'rotation_matrix': rotation,
17 'euler_angles': euler_angles
18 }
19
20pose = extract_pose(T)
21print("Position:", pose['position'])
22print("Euler angles (ZYX):", np.degrees(pose['euler_angles']), "degrees")
Common Mistakes
1. Incorrect Frame Assignment
1❌ BAD: z-axis not along joint axis
2 - Arbitrary frame placement
3 - Doesn't follow DH convention
4
5✅ GOOD: z-axis strictly along joint rotation/translation
6 - Follow DH rules systematically
7 - Verify each frame placement
2. Wrong Transformation Order
1# ❌ BAD: Incorrect order
2T = Trans(x, a) @ Rot(z, theta) @ Trans(z, d) @ Rot(x, alpha)
3
4# ✅ GOOD: Correct DH order (Classic)
5T = Rot(z, theta) @ Trans(z, d) @ Trans(x, a) @ Rot(x, alpha)
3. Angle Units
1# ❌ BAD: Mixing degrees and radians
2theta_deg = 45
3T = dh_matrix(theta_deg, d, a, alpha) # Wrong!
4
5# ✅ GOOD: Always use radians
6theta_rad = np.radians(45)
7T = dh_matrix(theta_rad, d, a, alpha)
4. Sign Conventions
1❌ BAD: Inconsistent angle measurement
2 - Mixing left-hand and right-hand rules
3 - Arbitrary positive directions
4
5✅ GOOD: Consistent right-hand rule
6 - All rotations follow right-hand rule
7 - Document positive directions clearly
Validation
Test with Known Configurations
1def validate_dh(robot, test_cases):
2 """Validate DH parameters with known configurations"""
3
4 for test in test_cases:
5 joints = test['joints']
6 expected = test['expected_position']
7
8 # Compute FK
9 T = robot.forward_kinematics(*joints)
10 actual = T[:3, 3]
11
12 # Check error
13 error = np.linalg.norm(actual - expected)
14
15 print(f"Joints: {joints}")
16 print(f"Expected: {expected}")
17 print(f"Actual: {actual}")
18 print(f"Error: {error:.6f} m")
19
20 assert error < 1e-6, f"FK error too large: {error}"
21
22 print("\n✓ All validation tests passed!")
23
24# Example test cases
25test_cases = [
26 {
27 'joints': [0, 0],
28 'expected_position': np.array([1.8, 0, 0]) # L1 + L2
29 },
30 {
31 'joints': [np.pi/2, 0],
32 'expected_position': np.array([0, 1.8, 0])
33 }
34]
Best Practices
1✅ DO:
2- Follow DH convention strictly
3- Document frame assignments clearly
4- Use consistent units (radians, meters)
5- Validate with known configurations
6- Draw diagrams before implementing
7- Check for parallel/intersecting axes cases
8
9❌ DON'T:
10- Mix DH conventions (classic vs modified)
11- Skip frame assignment verification
12- Use degrees in calculations
13- Forget to handle special cases (parallel axes)
14- Assume arbitrary frame placement is valid
Further Reading
- Craig, J.J. "Introduction to Robotics: Mechanics and Control"
- Spong, M.W. "Robot Modeling and Control"
- DH Parameters Tutorial (Duke)
- Modified DH Parameters (Khalil)
Related Snippets
- DH Parameter Examples and Common Configurations
Practical examples of DH parameter configurations for common robot manipulators … - Four-Wheel Independent Drive Kinematics
Forward and inverse kinematics for four-wheel independent drive robots with … - Front-Wheel Drive (FWD) Kinematics
Forward and inverse kinematics for front-wheel drive robots with Ackermann … - Jacobian Matrices for Forward and Inverse Kinematics
Jacobian matrices relate joint velocities to end-effector velocities, essential … - Mecanum Wheel Kinematics
Forward and inverse kinematics for mecanum wheel robots, enabling … - Rear-Wheel Drive (RWD) Kinematics
Forward and inverse kinematics for rear-wheel drive robots with front-wheel … - Two-Wheel Balancing Robot Kinematics and Control
Kinematics and control for two-wheel self-balancing robots (inverted pendulum on … - Two-Wheel Differential Drive Robot Kinematics
Forward and inverse kinematics for two-wheel differential drive robots, the most …