TT Lab
Blog

한국어 English 日本語 中文

Get started
Blog

Blog

Forward Kinematics: DH Parameters and Product of Exponentials (PoE), 2-Link Planar Arm and 3-Axis Wrist

Status: Draft (2026-10-18), Measured. Numbers were calculated directly using Python 3.9.6 and numpy 2.0.2 on a laptop (Apple M1 Max, macOS 26.5). Times are the medians of 7 repetitions (dropping the first run). Raw data and code: working directory measure/robot-arm-basics/in arm.py, m03_fk.py, out/m03_fk.json. The example arm is a virtual design with no values measured from a real robot (hardware unmeasured). References were accessed on 2026-10-18. Writing convention: Measured data is the baseline; unmeasured items are marked as "Unmeasured", and unverified items as "Unverified".

Table of Contents

1. Intuition: Starting with the Easier Direction

Once all joint angles of an arm are known, the position of the racket is uniquely determined. You simply apply a ruler from the shoulder to the elbow, and another from the elbow to the wrist repeatedly. This is forward kinematics. The solution is always unique and the calculation is short.

The opposite direction—namely, "what joint angles should be set to place the racket there at that orientation"—can have multiple or no solutions, making it much harder. That is inverse kinematics, covered in part 4. Forward kinematics must be accurately established first in order to verify the solutions of inverse kinematics.

2. Diagram: The Example Arm of This Series

예제 팔: 6축 팔꿈치형 + 구형 손목(옆에서 본 모습) 1 요(수직축) 2 어깨 피치 3 팔꿈치 피치 4·5·6 손목 d1 = 0.30 a2 = 0.40 d4 = 0.35 d6 = 0.15 라켓 i a α d θ 1 0 +90° 0.30 θ1 2 0.40 0 0 θ2 3 0 +90° 0 θ3 4 0 −90° 0.35 θ4 5 0 +90° 0 θ5 6 0 0 0.15 θ6 길이 단위 m. 표준 DH. 손목 세 축이 한 점(손목 중심)에서 만난다.
Diagram: 6-axis anthropomorphic arm and spherical wrist. Link lengths and DH table

The example arm has a structure similar to a human arm.

As an open-source hardware alternative, a design mounting a 2-3 axis wrist on a 2-axis Cartesian gantryis also a strong candidate. The Google DeepMind system also mounted a 6-axis industrial arm on a 2-axis linear gantry (arXiv:2408.03906 Section II-A). Gantries have forward and inverse kinematics that consist almost entirely of additions, so their advantages are calculated separately in part 4.

3. Calculations

3.1 2-Link Planar Arm

The end point of a planar arm with link lengths L1, L2 and joint angles q1, q2 is given by:

x = L1·cos q1 + L2·cos(q1 + q2)
y = L1·sin q1 + L2·sin(q1 + q2)

This equation serves as the starting point for inverse kinematics in part 4, the Jacobian in part 5, and dynamics in part 9. The planar problem formed by joints 2 and 3 of the example arm is precisely this.

3.2 DH Parameters

If there are six joints, coordinate systems must be chained six times. The Denavit–Hartenberg (DH) convention defines the next coordinate system using only four numbers per link.

Symbol Meaning
θ_i Angle rotating about the z-axis (this is the joint variable for a revolute joint)
d_i Translation along the z-axis
a_i Translation along the new x-axis (link length)
α_i Angle rotating about the new x-axis (twist of the next joint axis)

This post uses the sequence "rotate by θ along z, translate by d, translate by a along x, and rotate by α" (commonly called standard DH). Depending on the textbook, there is also a modified DH that uses different sequences and subscripts. Appendix C of Modern Robotics defines them in the order α_{i−1}, a_{i−1}, d_i, φ_i. Even for the same arm, if conventions differ, the table numbers will differ, so if you receive a table from someone else, you must check their convention first.

def dh_T(a, alpha, d, th):            # 표준 DH: Rz(θ)·Tz(d)·Tx(a)·Rx(α)
    ct, st, ca, sa = cos(th), sin(th), cos(alpha), sin(alpha)
    return np.array([[ct, -st*ca,  st*sa, a*ct],
                     [st,  ct*ca, -ct*sa, a*st],
                     [0,   sa,     ca,    d   ],
                     [0,   0,      0,     1.0 ]])

def fk_dh(q):
    T = np.eye(4)
    for (a, alpha, d), qi in zip(DH, q):
        T = T @ dh_T(a, alpha, d, qi)
    return T                            # 라켓 좌표계 {E} 를 로봇 바닥 {B} 에서 본 4×4

3.3 Product of Exponentials (PoE)

DH requires defining a coordinate system for every link, and the rules for doing so are tricky. The product of exponentials (PoE) formula uses only two coordinate systems: the base coordinate system and the zero-position racket pose M. It also treats each individual joint as a "screw motion rotating about a certain axis".

T(q) = e^[S1]q1 · e^[S2]q2 · … · e^[S6]q6 · M

S_i = (ω_i, v_i),  ω_i = 관절 축 방향 단위 벡터,  v_i = −ω_i × p_i  (p_i 는 축 위의 아무 점)

All S_i and M can be written by looking at just a single zero-position . This is the spatial-form PoE equation (4.14) in Chapter 4 of Modern Robotics, and that same book cites the lack of need for link coordinate systems as an advantage. Exponential matrices have a closed-form via Rodrigues' formula.

def exp6(S, th):
    w, v = S[:3], S[3:]
    W = skew(w)
    R = np.eye(3) + sin(th)*W + (1 - cos(th))*W@W
    G = np.eye(3)*th + (1 - cos(th))*W + (th - sin(th))*W@W
    T = np.eye(4); T[:3, :3] = R; T[:3, 3] = G @ v
    return T

The code for this series does not write S_i and M by hand; instead, it computes the zero-position coordinate systems from the DH table and extracts them from the z-axis and origin of each joint. This allows immediate verification of whether both methods represent the same arm.

3.4 Spherical Wrist and Wrist Center

Good things happen when the three wrist axes intersect at a single point. No matter how much joints 4, 5, and 6 rotate, the position of the wrist center does not change. The wrist center is determined solely by joints 1, 2, and 3, and inversely computing the wrist center from the racket pose is also straightforward.

손목 중심 = 라켓 중심 − d6 · (라켓 법선 방향, 곧 R 의 셋째 열)

Part 4 uses this property to split 6-axis inverse kinematics into "3 positions" and "3 orientations" and solves them in closed form.

4. Measurements

4.1 Do DH and PoE Produce the Same Answer?

Joint angles were randomly sampled 10,000 times between −π and π, and the 4×4 results of the two functions were compared element by element.

Item Value
Max element difference 5.6×10⁻¹⁶
Zero position M (position) (0.40, 0, −0.20) m, racket normal points downward (−z)

The differences are at the level of float64 rounding. The fact that the racket is positioned below the floor (−0.20 m) at the zero position is because an elbow angle of 0 points the forearm vertically downward. In a real robot, aligning this "meaning of 0" with the encoder zero position is the first step of calibration (Section 4.3).

4.2 Calculation Time

Calculation Per run (µs)
2-link planar closed-form (pure Python) 0.41
6-axis DH (numpy 6 matrix multiplications of 4×4) 15.2
6-axis PoE (numpy, 6 exponential matrices) 71.7
6-axis Jacobian (Part 5, in DH coordinate systems) 102.6

PoE was about 4.7 times slower than DH. This is because, in addition to sines and cosines, it performs multiple 3×3 matrix multiplications and additions per joint. Since a 1 kHz control cycle is 1,000 µs, both are sufficiently fast even in Python. When porting to a microcontroller, pre-expanded formulas like DH are expected to be advantageous (unmeasured).

4.3 How Much Do Small Errors Translate to at the Racket Tip?

Even if forward kinematics is accurate, it is useless if the actual arm dimensions and encoders are off. Four types of errors were introduced, and their impact on the deviations of the racket center position and racket normal orientation was measured across 5,000 random poses.

작은 오차가 라켓 끝에서 몇 mm 가 되나 링크 길이 ±1 mm 0.98 / 1.94 관절 영점 ±0.1° 0.62 / 1.43 엔코더 12비트 0.27 / 0.65 엔코더 14비트 0.07 / 0.16 0 0.5 1 1.5 2 라켓 중심 위치 오차(mm). 막대는 중앙값, 가는 선 끝은 95백분위.
Diagram: Magnitude at which link length, joint zero, and encoder resolution errors propagate into racket position error
Error Source Position Error Median/95% Normal Direction Error Median/95%
Link length ±1 mm (uniform, independent per joint) 0.98 / 1.94 mm 0°
Joint zero position ±0.1° 0.62 / 1.43 mm 0.09 / 0.19°
12-bit encoder (4,096 counts/rev) quantization 0.27 / 0.65 mm 0.04 / 0.08°
14-bit encoder (16,384 counts/rev) quantization 0.07 / 0.16 mm 0.01 / 0.02°

5. Limitations

6. Conclusion

Table tennis tidbit. Applying a ruler six times gives you the racket position. However, if the zero of the ruler is off by even 0.1°, the ball goes about 1 cm off target, so make sure to calibrate the zero position first!

References

All materials were accessed on 2026-10-18.

Sign in to like

Comments

No comments yet.

Sign in to leave a comment