Denavit–Hartenberg Parameters
Every industrial robot arm, from a six-axis welding robot to a surgical manipulator, is described by the same compact recipe: a table of four numbers per joint. The Denavit–Hartenberg convention, published in 1955, turned the messy problem of chaining 3D rotations and translations into a systematic, almost mechanical procedure — and it is still the standard way robotics textbooks and control software describe manipulator geometry today.
1. Why DH Parameters Exist
A serial robot arm is a chain of rigid links connected by joints. To compute where the end-effector (the gripper, welding tip, or scalpel) ends up given a set of joint angles — the forward kinematics problem — you need to describe the geometric relationship between every consecutive pair of links.
You could attach an arbitrary coordinate frame to each link and write down an arbitrary 4×4 homogeneous transformation between them. That works, but it needs six numbers per link (three translation, three rotation) and gives every robotics team its own inconsistent notation. In 1955, Jacques Denavit and Richard Hartenberg showed that if you place each frame according to a small set of rules, the transform between any two consecutive links can always be described with only four numbers instead of six. That reduction — and the fact that it is a shared standard — is why the DH convention is still taught in every robotics course.
2. The Four Parameters: a, α, d, θ
Each link i is described relative to link i−1 by four quantities, traditionally read off a "DH table" with one row per joint:
| Symbol | Name | Type | Meaning |
|---|---|---|---|
| aᵢ | Link length | constant | Distance from zᵢ₋₁ to zᵢ measured along xᵢ (the common normal) |
| αᵢ | Link twist | constant | Angle from zᵢ₋₁ to zᵢ measured about xᵢ |
| dᵢ | Link offset | variable for prismatic joints | Distance from xᵢ₋₁ to xᵢ measured along zᵢ₋₁ |
| θᵢ | Joint angle | variable for revolute joints | Angle from xᵢ₋₁ to xᵢ measured about zᵢ₋₁ |
For the overwhelmingly common case of a revolute joint (a rotating hinge, as in almost every industrial arm), a, α and d are fixed by the physical geometry of the robot, and θ is the single variable that changes as the joint moves — this is exactly the "joint angle" you command a servo to reach. For a prismatic joint (a linear slider), it is d that varies instead, while θ is fixed.
Two constants per joint (a, α) capture the shape of the link itself; two more (d, θ) capture how the joint moves that shape relative to the previous one. A 6-DOF arm is therefore fully specified by a 6×4 DH table — 24 numbers describe the entire kinematic structure.
3. Assigning Joint Frames: The DH Rules
The four parameters only work if the coordinate frame at each joint is placed according to strict rules. For joint i, attach a right-handed frame {xᵢ, yᵢ, zᵢ} as follows:
- zᵢ lies along the axis of joint i+1 (the axis the next joint rotates or slides about).
- xᵢ lies along the common normal between zᵢ₋₁ and zᵢ, pointing from axis i−1 toward axis i. If the two axes are parallel, any common perpendicular works; if they intersect, xᵢ is normal to the plane they define.
- yᵢ completes a right-handed frame: yᵢ = zᵢ × xᵢ.
- The origin of frame i is where the common normal xᵢ meets axis zᵢ.
Once every frame is assigned this way, aᵢ, αᵢ, dᵢ, θᵢ fall directly out of the geometry between frame i−1 and frame i, and the transform between them takes a single fixed algebraic form — no case-by-case derivation needed.
4. Building the Transformation Matrix
Given the four DH parameters for joint i, the homogeneous transform from frame i−1 to frame i is the product of four elementary transforms — rotate about z, translate along z, translate along x, rotate about x:
Multiplying these four matrices out gives the standard closed-form 4×4 DH transform:
Chaining n of these matrices gives the full forward-kinematics transform from the robot's base frame to its end-effector frame:
The rightmost column of T_base→n is the end-effector's (x, y, z) position in the base frame; the upper-left 3×3 block is its orientation as a rotation matrix. For a 6-DOF industrial arm this is simply six 4×4 matrix multiplications — cheap enough to run at kilohertz control rates.
5. Standard vs Modified DH Convention
There are two competing conventions in use, and mixing them up is the single most common source of bugs when implementing a DH-based kinematic model:
Standard (Classic/Distal) DH
Frame i is attached at the far end of link i, using zᵢ₋₁ as the axis of joint i. Used by Craig's popular textbook is actually the modified form — but many older papers and Paul's original 1981 formulation use this classic layout. The matrix shown above is the classic-DH form.
Modified (Proximal) DH
Frame i is attached at the near end of link i, and the transform order is rearranged to Rot_x(αᵢ₋₁)·Trans_x(aᵢ₋₁)·Rot_z(θᵢ)·Trans_z(dᵢ). Used in Craig's Introduction to Robotics and many URDF-derived toolchains.
Both conventions describe the same physical robot and give the same end-effector pose — but the individual a, α, d, θ values in the table will differ between them, and a transform matrix built with one convention's formula but another convention's table will silently produce a wrong (but plausible-looking) pose. Always check which convention a DH table was written for before plugging it into code.
6. Worked Example: A 3-DOF Arm
Consider a simple 3-DOF arm: a rotating base (joint 1, axis vertical), then two revolute "shoulder" and "elbow" joints (joints 2 and 3) rotating about horizontal axes, with link lengths L₂ and L₃. Its standard DH table is:
| i | aᵢ | αᵢ | dᵢ | θᵢ |
|---|---|---|---|---|
| 1 | 0 | 90° | d₁ | θ₁ (variable) |
| 2 | L₂ | 0° | 0 | θ₂ (variable) |
| 3 | L₃ | 0° | 0 | θ₃ (variable) |
Joint 1's twist of 90° rotates the following axis from vertical to horizontal, so joints 2 and 3 act like a planar 2-link arm mounted on a rotating turret — exactly the geometry of a typical desk-lamp-style manipulator or a simple pick-and-place robot. Multiplying T₀,₁·T₁,₂·T₂,₃ reduces algebraically to the familiar planar arm equations scaled by cos θ₁ and sin θ₁ for the turret rotation, which is a useful sanity check: the DH machinery should always reproduce simple special cases you can verify by hand.
7. Computing Forward Kinematics in Code
Implementing the DH chain is a small, reusable routine — build one 4×4 matrix per joint, then multiply them left to right:
function dhMatrix(theta, d, a, alpha) {
const ct = Math.cos(theta), st = Math.sin(theta);
const ca = Math.cos(alpha), sa = Math.sin(alpha);
// Row-major 4x4, classic (standard) DH convention
return [
[ct, -st * ca, st * sa, a * ct],
[st, ct * ca, -ct * sa, a * st],
[ 0, sa, ca, d],
[ 0, 0, 0, 1],
];
}
function matMul4(A, B) {
const C = Array.from({ length: 4 }, () => [0, 0, 0, 0]);
for (let i = 0; i < 4; i++)
for (let j = 0; j < 4; j++)
for (let k = 0; k < 4; k++)
C[i][j] += A[i][k] * B[k][j];
return C;
}
// dhTable: array of { theta, d, a, alpha } — one entry per joint
function forwardKinematics(dhTable) {
let T = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
];
for (const { theta, d, a, alpha } of dhTable) {
T = matMul4(T, dhMatrix(theta, d, a, alpha));
}
// End-effector position: last column, rows 0-2
const pos = [T[0][3], T[1][3], T[2][3]];
return { T, pos };
}
// Example: the 3-DOF arm from section 6
const dhTable = [
{ theta: 0.3, d: 0.4, a: 0, alpha: Math.PI / 2 },
{ theta: -0.5, d: 0, a: 0.5, alpha: 0 },
{ theta: 0.8, d: 0, a: 0.4, alpha: 0 },
];
const { pos } = forwardKinematics(dhTable);
console.log(pos); // [x, y, z] of the end-effectorBecause each joint contributes exactly one 4×4 matrix, this function scales linearly with the number of joints and generalizes to any serial chain — 3-DOF educational arms, 6-DOF industrial robots, or 7-DOF redundant manipulators — simply by extending the DH table.
8. Pitfalls, Singularities & Practical Notes
- Convention mismatches: as covered in section 5, standard and modified DH tables are not interchangeable with each other's matrix formula. Manufacturer datasheets and URDF files should always state which convention they use.
- Sign ambiguity: α and θ signs depend on the chosen right-handed frame orientation; flipping an axis direction flips the sign of the corresponding angle. Double-check frame diagrams rather than assuming a sign.
- Parallel and coincident axes: when zᵢ₋₁ and zᵢ are parallel, the common normal is not unique, and when they intersect, aᵢ = 0. These edge cases require care when assigning frames — most textbook derivations walk through them explicitly.
- Kinematic singularities: DH parameters describe geometry, not reachability. When two joint axes become collinear (e.g. an elbow fully extended), the Jacobian derived from the DH chain loses rank, and small end-effector motions require infinite joint velocities — a separate concern from the DH table itself, but one every downstream inverse-kinematics solver must handle.
- Where it's used: DH tables are the geometric backbone of ROS's
robot_state_publisher, MoveIt motion planning, MATLAB's Robotics System Toolbox, and virtually every industrial robot controller's kinematic model — because a compact, standardized table is far easier to calibrate, document, and debug than an arbitrary set of per-link transforms.