Book contents
Contents

DH generator

xyz / joint axis
Tool positionx 0y 0z 0mm

DH geometry

JointTypeθ₀ · °d₀ · mmaᵢ · mmαᵢ · °q
Tool offset · mm

Standard DH · millimetres · degrees

Tool pose in the base frame

Rotation occupies the first three columns; translation in millimetres is in the last column.

Selected row · local transform

RAW Book Robotics Forward Kinematics

Introduction to the Denavit-Hartenberg Convention

Robert Eisele

A robot arm is not primarily a collection of lengths. It is a sequence of axes about which things can move. Two arms with identical link lengths can behave completely differently if one elbow bends upward and the other swivels sideways. To predict the tool pose, the geometry of those axes matters as much as their separation.

The Denavit-Hartenberg convention, usually abbreviated DH, is a systematic way to describe that geometry. Attach carefully chosen coordinate frames to consecutive links, and one step along a serial chain needs only four numbers. Two describe the motion and offset along the joint axis; two describe the distance and twist between consecutive joint axes. Multiplying the resulting transforms gives the position and orientation of the tool.

Start with One Joint, Not a Matrix

Imagine holding the first link still and moving the next one. For a revolute joint, every point on the moving link traces a circle around one fixed line: the joint axis. For a prismatic joint, the link slides along one fixed direction without changing its orientation. These are the idealized joints used in the model; bending, backlash and elastic deformation are excluded.

Choose a local \(z\)-axis along that joint axis. A revolute joint now changes a rotation about \(z\), while a prismatic joint changes a translation along \(z\). What looked like arbitrary three-dimensional motion has become one scalar variable. The problem is then how to place the next frame so that the fixed geometry is equally simple.

DH does not add or remove any physical freedom. It chooses coordinates that make the freedom already present in the mechanism easy to describe. A six-joint serial robot still has six joint coordinates, even though its DH table contains four entries per row.

An open chain with \(n\) joints has \(n+1\) links, including the base link numbered zero. A frame attached to link \(i\) moves with that link: the coordinates \({}^i\mathbf{p}\) of any rigidly attached point remain constant, although its base-frame coordinates change. The relative transform from link \(i\) to link \(i-1\) depends only on that joint's coordinate, so it is often written as the A-matrix

\[ A_i(q_i):={}^{i-1}T_i(q_i). \]

Moving an earlier joint changes both of these adjacent links in the base frame, but does not change their relative pose if \(q_i\) stays fixed. This is the distinction between the local function \(A_i(q_i)\) and the accumulated pose \({}^0T_i(q_1,\ldots,q_i)\).

What a Coordinate Frame Actually Describes

A frame consists of an origin \(O\) and three perpendicular unit directions \(\hat{\mathbf{x}},\hat{\mathbf{y}},\hat{\mathbf{z}}\). It is a small ruler attached rigidly to a body. The coordinates of a point depend on which ruler is used; the physical point does not.

If a child frame has origin \(\mathbf{t}\) and axes expressed in the parent frame as columns of \(R\), then a point with child coordinates \(\mathbf{p}_{\mathrm{child}}\) has parent coordinates

\[ \mathbf{p}_{\mathrm{parent}}=R\mathbf{p}_{\mathrm{child}}+\mathbf{t}, \qquad R=[\hat{\mathbf{x}}\ \hat{\mathbf{y}}\ \hat{\mathbf{z}}]. \]

The columns of \(R\) answer three concrete questions: where does one unit along the child's \(x\), \(y\) and \(z\) point in the parent frame? The vector \(\mathbf{t}\) answers where the child's origin is. A pose is these two pieces together, not merely a point in space.

A right-handed frame uses the cross product and satisfies \(\hat{\mathbf{y}}=\hat{\mathbf{z}}\times\hat{\mathbf{x}}\). Positive rotations obey the right-hand rule: point the right thumb along the positive axis; the curl of the fingers is the positive angular direction. A drawing that looks clockwise from the other side of the axis has not changed this rule.

Why Four Parameters Can Replace Six

An unrestricted rigid-body pose needs three translation coordinates and three orientation coordinates. It would therefore seem that each link needs six geometric parameters. But DH frames are not unrestricted: their \(z\)-axes are prescribed by the joints, and their \(x\)-axes are chosen along common normals between consecutive \(z\)-axes. Those constraints remove two coordinates that would otherwise describe arbitrary frame placement.

This is why four numbers suffice. It is not a claim that every arbitrary pair of pre-existing CAD frames can be represented by one DH row. First choose DH-compatible frames; keep arbitrary base and tool attachments as separate fixed transforms.

Existence and Uniqueness for Fixed Frames

There are two different questions: whether a pair of already chosen frames admits a DH representation, and how many valid frame choices a mechanism permits. For the first question, the standard-DH conditions are precise:

  1. DH1: the child axis \(x_i\) is perpendicular to the parent axis \(z_{i-1}\).
  2. DH2: the line through the child origin in direction \(x_i\) intersects the parent \(z_{i-1}\)-axis.

For two right-handed orthonormal frames satisfying these conditions, there is exactly one signed pair \((a_i,d_i)\) and one pair of angles \((\theta_i,\alpha_i)\), modulo full turns, such that

\[ A_i=R_z(\theta_i)T_z(d_i)T_x(a_i)R_x(\alpha_i). \]

To see why, express the child axes and origin in the parent frame. Write \(A_i=[R,\mathbf{t};\mathbf{0}^{\mathsf T},1]\), with entries \(r_{jk}\). The first column of \(R\) is the child \(x_i\)-direction. DH1 says \(r_{31}=0\), so its unit length requires

\[ \hat{\mathbf{x}}_i=(\cos\theta_i,\sin\theta_i,0)^{\mathsf T}. \]

Choose \(\theta_i\) from this direction and undo that turn. The rotation \(R_z(-\theta_i)R\) then fixes the positive \(x\)-axis. A proper rotation fixing that axis must be a rotation \(R_x(\alpha_i)\). This determines the remaining twist. DH2 supplies an intersection point on the parent axis, giving

\[ \mathbf{t}=d_i\hat{\mathbf{z}}_{i-1}+a_i\hat{\mathbf{x}}_i. \]

The two directions are perpendicular unit vectors, so the two coefficients are unique. Conversely, the four-factor product always gives an \(x_i\)-direction perpendicular to old \(z\) and a child origin on a line meeting old \(z\). Thus these conditions are both necessary and sufficient.

The proof still works when \(a_i=0\): the chosen child \(x_i\)-direction exists even if the bridge has zero length. The angles are then fixed by the chosen frame, not by a nonzero bridge. The freedom to choose another valid frame for intersecting or coincident joint axes is a separate issue, not a failure of uniqueness for fixed frames.

Recovering DH Parameters from a Matrix

For a valid standard-DH frame pair, the constructive proof gives a direct inverse of the parameterization:

\[ heta_i=\operatorname{atan2}(r_{21},r_{11}),\qquad \alpha_i=\operatorname{atan2}(r_{32},r_{33}), \]

\[ d_i=t_z,\qquad a_i=t_x\cos\theta_i+t_y\sin\theta_i. \]

The first angle reads the new \(x\)-direction; the second reads the twist around it. Neither \(\operatorname{atan2}\) receives a zero pair for an exact proper rotation satisfying DH1. The signed length is the projection of the displacement onto the new \(x\)-direction, not necessarily \(\sqrt{t_x^2+t_y^2}\).

Before applying these equations to an arbitrary matrix, check that it is rigid, then check the DH constraints:

\[ R^{\mathsf T}R=I,\quad\det R=1,\quad r_{31}=0,\quad \rho:=-t_x\sin\theta_i+t_y\cos\theta_i=0. \]

The residual \(\rho\) is the displacement perpendicular to both old \(z\) and new \(x\). A nonzero residual means the child \(x\)-axis misses the parent \(z\)-axis. Use numerical tolerances appropriate to angular accuracy and length scale, reconstruct the matrix from the recovered parameters, and compare it with the input. Do not silently interpret a general pose matrix as a single DH row, or apply this inverse to modified DH.

The Common Normal

Take two consecutive joint-axis lines. A common normal is a line perpendicular to both and meeting both. For two nonparallel, nonintersecting lines in three dimensions, the shortest connecting segment lies on that line. It is the bridge between the axes.

Two joint axes joined by their common normal, with distance a and offset d zᵢ₋₁zᵢ aᵢ: common-normal distance dᵢ: offsetOᵢ₋₁ Oᵢxᵢ
A schematic projection of two axes. The bridge follows the new x-axis; the offset is measured along the previous z-axis. Perpendicularity is a three-dimensional property, not something to infer from the viewing angle.

Choose \(x_i\) along this bridge, usually pointing from \(z_{i-1}\) toward \(z_i\). Place \(O_i\) where the bridge meets \(z_i\). The previous origin \(O_{i-1}\) is already fixed by the preceding step; it need not lie at the start of this bridge. Reaching \(O_i\) therefore requires an offset along \(z_{i-1}\), followed by a distance along \(x_i\).

The bridge determines a direction, not the physical shape of a link. A curved casting, an L-shaped bracket and a straight beam may all have the same DH parameters if their joint axes have the same relative geometry. The tubes drawn by a kinematic visualizer are a skeleton, not a CAD reconstruction.

Computing the Bridge from Two Axis Lines

If the joint geometry comes from CAD or measurement, write two nonparallel axis lines as \(\mathbf{A}(s)=\mathbf{p}+s\mathbf{u}\) and \(\mathbf{B}(t)=\mathbf{q}+t\mathbf{v}\), where \(\mathbf{u}\) and \(\mathbf{v}\) are unit directions. The shortest bridge \(\mathbf{B}(t)-\mathbf{A}(s)\) is perpendicular to both. Set \(\boldsymbol{\Delta}=\mathbf{q}-\mathbf{p}\) and \(c=\mathbf{u}\cdot\mathbf{v}\). Orthogonality gives

\[ \mathbf{u}\cdot\boldsymbol{\Delta}+ct-s=0, \qquad \mathbf{v}\cdot\boldsymbol{\Delta}+t-cs=0. \]

Solving this two-equation system yields

\[ s=\frac{\mathbf{u}\cdot\boldsymbol{\Delta}-c\,\mathbf{v}\cdot\boldsymbol{\Delta}}{1-c^2}, \qquad t=\frac{c\,\mathbf{u}\cdot\boldsymbol{\Delta}-\mathbf{v}\cdot\boldsymbol{\Delta}}{1-c^2}. \]

When the bridge length is nonzero, choose \(\hat{\mathbf{x}}_i=(\mathbf{B}-\mathbf{A})/|\mathbf{B}-\mathbf{A}|\), \(O_i=\mathbf{B}\) and \(a_i=|\mathbf{B}-\mathbf{A}|\). If \(\mathbf{p}=O_{i-1}\), then \(d_i=s\). The signed angles can be read without an ambiguous inverse cosine:

\[ heta_i=\operatorname{atan2}(\hat{\mathbf{y}}_{i-1}\cdot\hat{\mathbf{x}}_i,\hat{\mathbf{x}}_{i-1}\cdot\hat{\mathbf{x}}_i), \qquad \alpha_i=\operatorname{atan2}\!\left(\hat{\mathbf{x}}_i\cdot(\mathbf{u}\times\mathbf{v}),\mathbf{u}\cdot\mathbf{v}\right). \]

This construction turns axis geometry into a standard-DH row. It is not an automatic solution for all special cases: when the axes intersect the bridge has zero length, and when they are parallel \(1-c^2=0\). The frame choices for those cases are described separately below. The small denominator also explains the sensitivity of nearly parallel axes.

Assigning Standard-DH Frames

  1. Number the physical joints. Joint \(i\) connects link \(i-1\) to link \(i\), for \(i=1,\ldots,n\).
  2. Align \(z_{i-1}\) with joint \(i\). Mark the positive angular or sliding direction. In particular, joint 1 acts about or along \(z_0\), not \(z_1\).
  3. Choose \(x_i\) along the common normal from \(z_{i-1}\) to \(z_i\). Handle parallel, intersecting or coincident axes with the choices described below.
  4. Place \(O_i\) on \(z_i\) where \(x_i\) meets it. Set \(y_i=z_i\times x_i\) to complete the right-handed frame.
  5. Choose the boundary frames. Put \(z_0\) on the first joint axis and select a convenient \(x_0\). At the last link, where no next physical joint dictates \(z_n\), choose a convenient terminal frame and record any remaining tool offset separately.
  6. Read the four signed parameters. Use the selected axis directions, not unsigned dimensions from a drawing.

Frame choices are not unique. Two valid tables can describe the same physical arm while using different origins, zero-angle references or tool frames. Comparing raw table entries is therefore not enough; compare the resulting poses in the same external base and tool frames.

Aligning the base axes with the world axes is a convenience, not a general DH rule. It is possible only if the first joint axis has the required alignment with world \(z\); otherwise record a base-to-world transform. Likewise, the common normal need not follow a casting's centreline, and choosing \(d_i=0\) for parallel axes is optional. The axes belong to the kinematic geometry, not to a particular drawing or industrial design.

The Four DH Parameters

ParameterMeaning in standard DHIntuitive question
\(\theta_i\)Rotation about \(z_{i-1}\), from \(x_{i-1}\) toward the common-normal direction \(x_i\)Which way does the bridge point around the old joint axis?
\(d_i\)Signed translation along \(z_{i-1}\) to the common normalHow far along the old axis does the bridge begin?
\(a_i\)Signed translation along \(x_i\) between \(z_{i-1}\) and \(z_i\)How long is the bridge between the axes?
\(\alpha_i\)Rotation about \(x_i\), from \(z_{i-1}\) toward \(z_i\)How much does the next joint axis tilt across the bridge?

Keep two pairs in mind:

\[ \underbrace{\theta_i,d_i}_{\text{about/along the old joint axis}} \qquad \underbrace{a_i,\alpha_i}_{\text{along/about the common normal}}. \]

The distinction between \(\theta\) and \(\alpha\) is particularly important. \(\theta\) turns the outgoing link around the current joint; \(\alpha\) describes the fixed twist that makes the next joint axis point in a different direction. A 90° elbow movement and a 90° twist between two motor axes are not the same parameter.

Geometry versus Joint State

For a revolute joint, write \(\theta_i=\theta_{i,0}+q_i\), with \(d_i,a_i,\alpha_i\) fixed. For a prismatic joint, write \(d_i=d_{i,0}+q_i\), with \(\theta_i,a_i,\alpha_i\) fixed. The constants \(\theta_{i,0}\) and \(d_{i,0}\) encode the chosen zero reference; \(q_i\) is the actual joint displacement from that reference.

The generator keeps these offsets separate from the joint sliders. Moving a revolute slider changes \(\theta\), not the link length. Moving a prismatic slider changes \(d\), not \(a\). Encoder direction can be modeled as \(q_i=s_i(q_{i,\mathrm{encoder}}-q_{i,\mathrm{zero}})\), with \(s_i\in\{-1,1\}\). Its calibration should not be hidden in a casually flipped axis.

Deriving the Homogeneous Transform

Translation and Rotation in One Multiplication

The equation \(R\mathbf{p}+\mathbf{t}\) contains both multiplication and addition. Append a fourth coordinate equal to one, and both become a single matrix multiplication:

\[ \begin{bmatrix}\mathbf{p}_{\mathrm{parent}}\\1\end{bmatrix} =\underbrace{\begin{bmatrix}R&\mathbf{t}\\\mathbf{0}^{\mathsf T}&1\end{bmatrix}}_{T} \begin{bmatrix}\mathbf{p}_{\mathrm{child}}\\1\end{bmatrix}. \]

This extra coordinate is bookkeeping, not a fourth spatial dimension. For a direction vector use a final coordinate zero, so translation has no effect. This distinction prevents the common mistake of applying an origin offset to an axis direction.

The Four Elementary Steps

Starting with the parent frame, the standard-DH construction is a local-frame walk:

  1. Rotate about the current \(z\)-axis by \(\theta_i\).
  2. Translate along that \(z\)-axis by \(d_i\).
  3. Translate along the now-oriented \(x\)-axis by \(a_i\).
  4. Rotate about that \(x\)-axis by \(\alpha_i\).

The first pair aligns and reaches the bridge. The second crosses the bridge and aligns the next joint axis. Using column vectors, each local operation is postmultiplied onto the current frame transform:

\[ {}^{i-1}T_i =R_z(\theta_i)T_z(d_i)T_x(a_i)R_x(\alpha_i). \]

There are two different orders to keep apart. A frame assembled by local updates walks through these steps from left to right. Once the complete matrix acts on a coordinate vector, its rightmost factor acts on that vector first. These are two descriptions of the same product, not contradictory recipes.

The elementary matrices follow directly from where they send the coordinate axes and origin:

\[ R_z(\theta)=\begin{bmatrix} \cos\theta&-\sin\theta&0&0\\ \sin\theta&\cos\theta&0&0\\ 0&0&1&0\\0&0&0&1 \end{bmatrix},\qquad T_z(d)=\begin{bmatrix}1&0&0&0\\0&1&0&0\\0&0&1&d\\0&0&0&1\end{bmatrix}. \]

\[ T_x(a)=\begin{bmatrix}1&0&0&a\\0&1&0&0\\0&0&1&0\\0&0&0&1\end{bmatrix},\qquad R_x(\alpha)=\begin{bmatrix} 1&0&0&0\\0&\cos\alpha&-\sin\alpha&0\\ 0&\sin\alpha&\cos\alpha&0\\0&0&0&1 \end{bmatrix}. \]

Translations and rotations about the same axis commute: \(R_z(\theta)T_z(d)=T_z(d)R_z(\theta)\), and similarly for \(x\). A translation along \(x\) does not generally commute with a rotation about \(z\): after a turn, local \(x\) points somewhere else. That is why swapping the two pairs changes the model.

Read the Translation Before Expanding the Matrix

After the first two steps, the origin is at \((0,0,d_i)\). The \(x\)-axis has turned to \((\cos\theta_i,\sin\theta_i,0)\), so moving a distance \(a_i\) along it gives

\[ \mathbf{t}_i=\begin{bmatrix}a_i\cos\theta_i\\a_i\sin\theta_i\\d_i\end{bmatrix}. \]

The final twist rotates the frame about its own \(x\)-axis; it does not move its origin. This immediately explains why \(\alpha_i\) is absent from the translation column of the standard-DH matrix. It still changes the directions of subsequent links and thus their later positions.

The Standard-DH Matrix

Multiplying the four factors, with \(c_\theta=\cos\theta_i\), \(s_\theta=\sin\theta_i\), \(c_\alpha=\cos\alpha_i\) and \(s_\alpha=\sin\alpha_i\), gives

\[ \boxed{{}^{i-1}T_i=\begin{bmatrix} c_\theta&-s_\theta c_\alpha&s_\theta s_\alpha&a_i c_\theta\\ s_\theta&c_\theta c_\alpha&-c_\theta s_\alpha&a_i s_\theta\\ 0&s_\alpha&c_\alpha&d_i\\ 0&0&0&1 \end{bmatrix}.} \]

Instead of memorizing sixteen entries, read the columns. The first is the new \(x\)-axis, unchanged by a twist about itself. The third is the new \(z\)-axis after the twist. The fourth is the origin reached by moving along old \(z\), then new \(x\). The second completes the right-handed triad.

From One Row to an Entire Robot

The superscripts tell us what a transform does: \({}^{i-1}T_i\) converts coordinates from frame \(i\) to frame \(i-1\), while also representing the pose of frame \(i\) in frame \(i-1\). For a point attached to the terminal link,

\[ {}^0\mathbf{p} ={}^0T_1\,{}^1T_2\cdots{}^{n-1}T_n\,{}^n\mathbf{p}, \qquad {}^0T_n=\prod_{i=1}^n{}^{i-1}T_i. \]

Each next step is expressed in the frame reached by the preceding steps. Simply adding the translation columns of the individual rows is wrong unless the relevant frames happen to have the same orientation.

Writing an accumulated transform as \((R,\mathbf{t})\) and the next row as \((R_i,\mathbf{t}_i)\), the update is

\[ R_{\mathrm{new}}=RR_i,\qquad \mathbf{t}_{\mathrm{new}}=\mathbf{t}+R\mathbf{t}_i. \]

The previous orientation rotates the new displacement into the base coordinates before the displacement can be added. This one equation captures the reason a robot chain bends rather than simply stacking lengths on world axes.

Why Intermediate Frame Choices Cancel

Imagine replacing each link's ruler without moving the link itself. Let \(S_i={}^{i}T_{i'}\) be the constant pose of a new link frame \(i'\) in the old frame \(i\). A point's new coordinates first pass through \(S_i\), then through \(A_i\), and finally into the new parent coordinates through \(S_{i-1}^{-1}\). Hence

\[ A_i'=S_{i-1}^{-1}A_iS_i. \]

When these steps are multiplied, every internal change of ruler is immediately undone by the next step:

\[ A_1'\cdots A_n' =S_0^{-1}A_1\underbrace{S_1S_1^{-1}}_I A_2\cdots \underbrace{S_{n-1}S_{n-1}^{-1}}_I A_nS_n =S_0^{-1}({}^0T_n)S_n. \]

If the base and terminal frames are unchanged, \(S_0=S_n=I\), so the accumulated transform is identical. If those endpoint frames change too, their external attachments must change consistently. With \(B={}^WT_0\) and \(E={}^nT_E\), use \(B'=BS_0\) and \(E'=S_n^{-1}E\). Then

\[ B'(A_1'\cdots A_n')E'=B(A_1\cdots A_n)E. \]

The physical world-to-tool pose therefore stays the same. This is an algebraic property of frame changes, not permission to change a DH table's numbers independently. Arbitrary \(S_i\) can also produce frames that no longer satisfy DH1 and DH2; to obtain another DH table, the new frames must themselves be DH-compatible.

Transforms Between Any Two Links

The same reasoning applies to a subchain:

\[ {}^iT_j= \begin{cases} A_{i+1}\cdots A_j,&i<j,\\ I,&i=j,\\ ({}^jT_i)^{-1},&i>j. \end{cases} \]

The indices indicate which coordinates are converted, so they prevent an inverse or multiplication-order error more reliably than naming a matrix simply “the robot transform.”

Worked Example: A Planar Two-Link Arm

Consider a shoulder and elbow rotating about parallel, upward-pointing axes. Let their links have lengths \(L_1\) and \(L_2\), and let \(q_1=q_2=0\) be the fully extended pose along positive \(x\). The terminal \(z_2\)-axis is chosen parallel to the physical joint axes.

JointType\(\theta_i\)\(d_i\)\(a_i\)\(\alpha_i\)
1Revolute\(q_1\)0\(L_1\)0
2Revolute\(q_2\)0\(L_2\)0

The first row reaches \((L_1\cos q_1,L_1\sin q_1,0)\). The second link points at angle \(q_2\) relative to the first link, so its angle in the base frame is \(q_1+q_2\):

\[ x=L_1\cos q_1+L_2\cos(q_1+q_2),\qquad y=L_1\sin q_1+L_2\sin(q_1+q_2),\qquad z=0. \]

Planar shoulder and elbow arm: the second angle is relative to the first link L₁L₂q₁q₂toolxy
The elbow angle is measured from the continuation of the first link, not from the world x-axis. Its sign depends on the chosen positive z direction.

With \(L_1=200\) mm, \(L_2=140\) mm, \(q_1=30°\) and \(q_2=45°\),

\[ x=200\cos30°+140\cos75°\approx209.440\ \mathrm{mm},\\ y=200\sin30°+140\sin75°\approx235.230\ \mathrm{mm}. \]

The tool's orientation is \(R_z(75°)\), not \(R_z(45°)\). Position alone would miss the accumulated rotation. At \(q_1=q_2=0\), the tool must be at \((340,0,0)\); at \(q_1=90°,q_2=0\), it must be at \((0,340,0)\). These simple configurations are excellent implementation tests.

The Same Result from Vectors and Trigonometry

The matrix result has a simple vector interpretation:

\[ {}^0\mathbf{p}_E =R_z(q_1)\begin{bmatrix}L_1\\0\\0\end{bmatrix} +R_z(q_1+q_2)\begin{bmatrix}L_2\\0\\0\end{bmatrix}. \]

Both displacement vectors are now expressed in the base frame, so they can be added. Expanding their components gives the sine-and-cosine equations above. DH products, vector addition and direct trigonometry are not competing descriptions: the matrix method automates the coordinate conversions that the geometric solution performs explicitly.

The Position Workspace Is a Circle or Annulus

Assume \(L_1,L_2>0\), both revolute joints can make full turns, and there are no obstacles. The tool's distance \(r=\sqrt{x^2+y^2}\) from the shoulder satisfies

\[ r^2=L_1^2+L_2^2+2L_1L_2\cos q_2. \]

The elbow changes \(\cos q_2\) continuously from \(-1\) to \(1\). The smallest radius occurs when the links fold back against each other; the largest when they line up in the same direction:

\[ \boxed{|L_1-L_2|\leq r\leq L_1+L_2.} \]

The full-turn 2R position workspace lies between an inner and outer circle outer: L₁ + L₂inner: |L₁ − L₂|shoulderreachable positions
The fully extended and fully folded poses bound the position workspace. The hole disappears when the two link lengths are equal.

Rotating the shoulder sweeps every direction at each attainable radius, so the complete position workspace is a closed annulus. If \(L_1=L_2\), its inner radius is zero and it becomes a disk. For the 200 mm and 140 mm example, reachable radii run from 60 mm to 340 mm. Joint limits reduce this set; the generator's motion limits are not an unrestricted-workspace calculation.

Position reachability is not arbitrary pose reachability. A 2R planar arm has two joint coordinates but a planar tool pose has three coordinates \((x,y,\gamma)\). Its orientation \(\gamma=q_1+q_2\) is coupled to the position. For example, the only fully extended pose at \((L_1+L_2,0)\) has \(\gamma=0\), modulo full turns. That position cannot simultaneously have a 90° tool orientation without an additional degree of freedom or a different tool attachment.

Worked Example: A Twisted Axis Followed by a Slider

Now let row 1 have \(\theta_1=90°\), \(d_1=100\) mm, \(a_1=200\) mm and \(\alpha_1=90°\). Its origin is

\[ \mathbf{t}_1=(0,200,100)^{\mathsf T},\qquad R_1=\begin{bmatrix}0&0&1\\1&0&0\\0&1&0\end{bmatrix}. \]

The third column reveals that the next joint's local \(z_1\)-axis points along positive world \(x\). Make joint 2 prismatic with \(a_2=\alpha_2=\theta_2=0\) and \(d_2=50\) mm. Sliding by 50 mm along \(z_1\) moves the tool to

\[ \mathbf{t}_2=\mathbf{t}_1+R_1\begin{bmatrix}0\\0\\50\end{bmatrix} =\begin{bmatrix}50\\200\\100\end{bmatrix}\ \mathrm{mm}. \]

A prismatic joint does not necessarily move upward in the scene. It moves along its own joint axis, which preceding rotations and twists may have directed anywhere. This example separates the joint variable \(d_2\) from the fixed twist \(\alpha_1\).

Parallel, Intersecting and Coincident Axes

Parallel Axes

Two distinct parallel axes have many common normals: slide the connecting segment along the axes and it stays perpendicular. Their perpendicular separation is fixed, but the frame origins along the axes remain a choice. A convenient choice often makes \(d_i=0\). If the directed axes point the same way, \(\alpha_i=0\); if they point opposite ways, a consistent twist is \(\alpha_i=\pi\), modulo full turns.

Do not compute the common-normal direction by normalizing \(z_{i-1}\times z_i\) in this case: the cross product is zero. Use the displacement between the distinct parallel lines, perpendicular to their direction.

Intersecting Axes

For two nonparallel axes that intersect, their shortest separation is zero, so \(a_i=0\). Choose \(O_i\) at the intersection and choose \(x_i\) perpendicular to both axes. The cross product provides one possible direction; reversing it changes parameter signs and angular references. The twist \(\alpha_i\) generally remains nonzero, and \(d_i\) can remain nonzero if the previous origin lies elsewhere on its axis.

Coincident Axes

When the axes lie on the same line, there is no bridge direction to determine \(x_i\). Here \(a_i=0\); choose a perpendicular \(x_i\) consistent with the preceding frame and a convenient reference pose. Axial offsets and rotations can still be meaningful. An axial offset between origins does not make the coincident axes distinct lines.

Near-Parallel Axes and Calibration

A tiny angle between nearly parallel axes can push their common-normal intersection points very far away. DH parameters may then become numerically large or change dramatically under a small geometric perturbation, even though the physical arm changes very little. This is a weakness of the parameterization near that geometry, not evidence of a broken mechanism. For calibration and optimization, carefully chosen alternative frame models or a product-of-exponentials model may be more stable.

Standard DH versus Modified DH

Craig's modified DH convention places frames differently and assigns joint \(i\) to \(z_i\). A common notation writes its row as \((a_{i-1},\alpha_{i-1},\theta_i,d_i)\) and uses

\[ {}^{i-1}T_i^{\mathrm{MDH}} =R_x(\alpha_{i-1})T_x(a_{i-1})R_z(\theta_i)T_z(d_i). \]

Writing \(a=a_{i-1}\), \(\alpha=\alpha_{i-1}\), \(\theta=\theta_i\), \(d=d_i\), the matrix is

\[ {}^{i-1}T_i^{\mathrm{MDH}}=\begin{bmatrix} \cos\theta&-\sin\theta&0&a\\ \sin\theta\cos\alpha&\cos\theta\cos\alpha&-\sin\alpha&-d\sin\alpha\\ \sin\theta\sin\alpha&\cos\theta\sin\alpha&\cos\alpha&d\cos\alpha\\ 0&0&0&1 \end{bmatrix}. \]

Notice the translation column: in standard DH, \(a\) is turned by \(\theta\); in modified DH, \(d\) is tilted by \(\alpha\). This is not an indexing typo but the consequence of a different order and different attached frames.

Standard DHCraig modified DH
Joint \(i\) axis\(z_{i-1}\)\(z_i\)
Geometric pair\(a_i,\alpha_i\)\(a_{i-1},\alpha_{i-1}\)
Factor order\(R_zT_zT_xR_x\)\(R_xT_xR_zT_z\)

For the single numerical row \(\theta=90°\), \(d=100\), \(a=200\), \(\alpha=90°\), standard DH gives translation \((0,200,100)\), while modified DH gives \((200,-100,0)\). Merely switching a selector while keeping the table unchanged therefore changes the modeled chain. To represent the same physical robot, reassign the frames and rederive the table, including the boundary frames.

The generator labels modified columns with their proper subscripts and exports the convention. Its switch evaluates the current numbers under the selected convention; it does not claim to convert a table automatically.

Base Frames, Tool Frames and the Last Axis

Let \(W\) be a world frame, \(0\) the DH base frame, \(n\) the final DH frame and \(E\) the physical tool frame. Then

\[ {}^WT_E={}^WT_0\left(\prod_{i=1}^n{}^{i-1}T_i\right){}^nT_E. \]

The base transform mounts the robot in the room; the tool transform locates a gripper tip, pen point or sensor relative to the final link. A tool offset is not necessarily another physical joint. In the generator, a fixed tool translation is applied in the last frame's coordinates after the DH chain. A general real application can also have a fixed tool rotation.

The last frame's \(z_n\)-axis in standard DH need not be another actuated axis. It is a chosen terminal coordinate direction. Adding a DH row simply to draw an end effector can accidentally create an extra degree of freedom unless that row is explicitly fixed.

A Spherical Wrist: Separating Position and Orientation

A spherical wrist has three revolute joint axes intersecting at one point, the wrist centre \(W_c\). Moving those joints changes orientation without moving that common centre. The arm before the wrist positions \(W_c\); the wrist then aims the attached tool. This is the geometric reason many six-axis robot calculations can be separated into an arm-position problem and a wrist-orientation problem.

An ideal freely orientable spherical joint has three rotational degrees of freedom, not two. Three intersecting revolute axes can provide a local orientation parameterization with zero axis-separation lengths between them; the joint limits and singular configurations of a real wrist still matter.

One convenient standard-DH wrist uses the following rows relative to a frame 3 whose origin is \(W_c\):

Joint\(\theta_i\)\(d_i\)\(a_i\)\(\alpha_i\)
4\(q_4\)00\(-\pi/2\)
5\(q_5\)00\(\pi/2\)
6\(q_6\)\(h\)00

The fixed offset \(h\) locates the terminal origin along the final joint axis; all three physical axis lines still meet at \(W_c\). The rotational product is

\[ {}^3R_6=R_z(q_4)R_x(-\pi/2)R_z(q_5)R_x(\pi/2)R_z(q_6) =R_z(q_4)R_y(q_5)R_z(q_6). \]

The middle identity follows because the first fixed twist carries local \(z\) into positive \(y\); conjugating a rotation changes its axis accordingly. Thus these joint coordinates form a particular ZYZ Euler-angle sequence. Other valid wrist frame choices can introduce signs or fixed angular offsets, so this identity should not be applied to a differently assigned wrist table.

For any tool offset \(\mathbf{r}\) measured from \(W_c\) in the terminal coordinates,

\[ {}^0\mathbf{p}_E={}^0\mathbf{p}_{W_c}+{}^0R_6\mathbf{r}. \]

The centre stays fixed while the tool tip generally moves. For the axial offset \(\mathbf{r}=h\hat{\mathbf{z}}\), it sweeps directions around the centre; the final roll \(q_6\) alone does not change that axial point. With a sideways tool offset, even the final roll can move the tip. “The wrist controls only orientation” is therefore true for the centre, not automatically for the physical tool position.

If the tool axes coincide with the terminal axes, a desired tool pose and a known terminal offset first give \({}^0\mathbf{p}_{W_c}={}^0\mathbf{p}_E-{}^0R_E\mathbf{r}\). If the arm can reach that centre, solve the remaining relative orientation \({}^3R_6=({}^0R_3)^{\mathsf T}{}^0R_E\). This describes the decoupling strategy, not a promise that the arm has a unique solution or that all desired poses satisfy its joint limits.

If the tool has an additional fixed rotation \({}^6R_E\), remove it first: \({}^0R_6={}^0R_E({}^6R_E)^{\mathsf T}\). Use this wrist orientation with an offset vector expressed in frame 6, rather than mixing a tool-frame vector with a wrist-frame rotation.

In this wrist parameterization, \(q_5=0\) or \(\pi\) aligns the first and last wrist axes. Their instantaneous angular effects are then dependent, producing a physical wrist singularity. This is distinct from the roll-pitch-yaw chart singularity described next: an orientation-coordinate singularity by itself does not prove that a robot Jacobian has lost rank.

Recovering Roll, Pitch and Yaw from the Pose

A forward-kinematics result already contains a complete orientation matrix. Euler angles are a way to report that orientation, not extra kinematic information. Their names are insufficient without a factor order and an axis convention. Here use column vectors and

\[ R=R_z(\psi)R_y(\beta)R_x(\varphi), \]

where \(\psi\) is yaw, \(\beta\) is pitch and \(\varphi\) is roll. These are reporting angles, not the DH joint angles \(\theta_i\). The ZYZ wrist angles above are another sequence and must not be substituted into this ZYX sequence.

Three entries and the first-column horizontal length make the extraction transparent:

\[ r_{11}=\cos\psi\cos\beta,\quad r_{21}=\sin\psi\cos\beta,\quad r_{31}=-\sin\beta, \]

\[ r_{32}=\sin\varphi\cos\beta,\qquad r_{33}=\cos\varphi\cos\beta. \]

Choose the principal pitch branch \(-\pi/2\leq\beta\leq\pi/2\). Away from its endpoints, \(\cos\beta>0\), and the angles follow from

\[ \psi=\operatorname{atan2}(r_{21},r_{11}),\qquad \beta=\operatorname{atan2}\!\left(-r_{31},\operatorname{hypot}(r_{11},r_{21})\right),\qquad \varphi=\operatorname{atan2}(r_{32},r_{33}). \]

There is no division by \(\cos\beta\), and \(\operatorname{atan2}\) keeps quadrant information that \(\arcsin\), \(\arccos\) or \(\arctan(y/x)\) would lose. A zero value in one argument is not a special failure: it is the simultaneous pair \((0,0)\) that has no direction.

Gimbal Lock Is a Loss of Angle Separation

At \(\beta=\pi/2\), the first-column horizontal entries vanish. The matrix depends on roll and yaw only through \(\varphi-\psi\). At \(\beta=-\pi/2\), it depends on them through \(\varphi+\psi\). Infinitely many roll/yaw pairs therefore describe the same orientation. The matrix remains valid; only the distinction between these two reporting angles has been lost.

A deterministic reporting convention can set \(\varphi=0\) at either singular endpoint and recover

\[ \psi=\operatorname{atan2}(-r_{12},r_{22}). \]

This yaw is a representative of the coupled angles, not a recovered independent physical yaw. A practical extraction uses a declared tolerance:

horizontal = hypot(r11, r21)
pitch = atan2(-r31, horizontal)
if horizontal > tolerance:
  yaw = atan2(r21, r11)
  roll = atan2(r32, r33)
else:
  roll = 0
  yaw = atan2(-r12, r22)

For a matrix only near a singular endpoint, the fallback is a tolerance-based approximation, not an exact inverse. Reconstruct the rotation and check the residual against the accuracy required. Tiny orientation changes near gimbal lock can cause large changes in the separated Euler angles; matrices or unit quaternions are preferable for interpolation and feedback calculations.

Even away from gimbal lock, the angles are not globally unique. Besides full-turn shifts, \((\psi+\pi,\pi-\beta,\varphi+\pi)\) gives the same ZYX rotation. Selecting a principal pitch branch removes this ambiguity for nonsingular reporting, but does not make Euler angles continuous across every branch boundary. In the planar example, yaw is \(q_1+q_2\) modulo full turns and pitch and roll are zero.

A Forward-Kinematics Implementation

The implementation follows the geometric derivation directly. Internally angles are in radians and all lengths use one consistent unit; degrees are only a user-interface representation. The following pseudocode separates offsets from joint displacements:

transform = identity4()
for each row in order:
    theta = row.thetaOffset
    d = row.dOffset
    if row.type == "R":
        theta += row.q
    if row.type == "P":
        d += row.q
    step = Rz(theta) * Tz(d) * Tx(row.a) * Rx(row.alpha)
    transform = transform * step
toolPose = basePose * transform * toolOffset

The stage uses the same factor products with Three.js matrix operations rather than maintaining a second set of hand-expanded formulas. Intermediate products retain the actual frames, so the visualized axes and the reported pose come from the same computation.

Inverting a Pose

If \(T=[R,\mathbf{t};\mathbf{0}^{\mathsf T},1]\) is rigid, then

\[ T^{-1}=\begin{bmatrix}R^{\mathsf T}&-R^{\mathsf T}\mathbf{t}\\\mathbf{0}^{\mathsf T}&1\end{bmatrix}. \]

Undo the translation in the correct frame and then undo the rotation. Negating the translation column without rotating it is not generally an inverse. Also distinguish inverting a pose matrix from inverse kinematics: the latter finds joint coordinates that achieve a requested pose and can have multiple solutions, no solution or singular configurations.

From Frames to a Geometric Jacobian

DH also provides the origins and directions needed for velocity kinematics. In standard DH, let \(\mathbf{o}_{i-1}\) and \(\hat{\mathbf{z}}_{i-1}\) be the origin and joint direction in the base frame, and let \(\mathbf{o}_E\) be the tool position. A revolute joint contributes

\[ J_i=\begin{bmatrix} \hat{\mathbf{z}}_{i-1}\times(\mathbf{o}_E-\mathbf{o}_{i-1})\\ \hat{\mathbf{z}}_{i-1} \end{bmatrix}. \]

The cross product is the tangent velocity induced by rotating the tool's radius about the joint axis. A prismatic joint contributes

\[ J_i=\begin{bmatrix}\hat{\mathbf{z}}_{i-1}\\\mathbf{0}\end{bmatrix}. \]

Stacking these columns gives \([\mathbf{v}_E;\boldsymbol{\omega}_E]=J\dot{\mathbf{q}}\). Revolute rates here are in radians per second. These are geometric angular-velocity columns, not derivatives of an arbitrary Euler-angle parameterization. Under modified DH use the actual joint frame \(i\), or extract the axis at the stage immediately before its \(R_z/T_z\) operations. Reusing standard-DH indices blindly is a frequent Jacobian bug.

Why a Straight Arm Is a Singular Pose

For the planar two-link example, differentiate the endpoint equations with respect to \(q_1\) and \(q_2\). Its position Jacobian is

\[ J_{xy}=\begin{bmatrix} -L_1\sin q_1-L_2\sin(q_1+q_2)&-L_2\sin(q_1+q_2)\\ L_1\cos q_1+L_2\cos(q_1+q_2)&L_2\cos(q_1+q_2) \end{bmatrix},\qquad \det J_{xy}=L_1L_2\sin q_2. \]

With nonzero link lengths, the Jacobian loses rank when \(q_2\) is 0 or \(\pi\), modulo full turns. The two links are collinear, so the two joints initially move the endpoint along the same tangent direction. An instantaneous displacement directly along the straight arm cannot be produced by finite joint rates at that pose. The arm can still bend and then move inward; that change involves more than the first-order velocity available at the singular instant.

Forward kinematics remains well defined there. It is the attempt to invert a local velocity map that becomes problematic, not the DH transform itself. This distinction separates a physical kinematic singularity from the coordinate ambiguity of coincident or parallel DH axes.

Checks That Catch Most DH Mistakes

What DH Does Not Tell You

A DH chain describes ideal rigid-body geometry and motion. It does not establish collision clearance, link stiffness, payload, motor torque, dynamic balance, electrical limits or a controller's safe operating envelope. Joint limits constrain the allowed \(q_i\), but they are not encoded by the four DH parameters themselves. Closed-loop mechanisms additionally need loop-closure constraints; a single serial product does not enforce them.

Nor does a plausible-looking 3D model prove a DH table correct. Several mistakes can cancel in one reference pose and reappear when joints move. Verify multiple configurations and, for physical robots, compare against measured poses. A screenshot is evidence of rendering, not of calibrated kinematics.

The Essential Picture

Read a DH row as turn around the old axis, move along it, cross the bridge, tilt the next axis. The joint supplies one variable; carefully chosen frames compress the remaining geometry. The matrix is a record of that walk, and the forward-kinematics product simply repeats it from base to tool.

Once that picture is clear, \(\theta\) and \(d\) no longer look like arbitrary table columns, \(a\) and \(\alpha\) stop being confused with physical link shape, and the difference between standard and modified DH becomes a difference in how the walk is organized.

References