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/inarm.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
- 2. Diagram: The Example Arm of This Series
- 3. Calculations
- 4. Measurements
- 5. Limitations
- 6. Conclusion
- References
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
The example arm has a structure similar to a human arm.
- Joint 1 is the shoulder yaw rotating about the vertical axis, while joints 2 and 3 are parallel shoulder pitch and elbow pitch in the same direction. These three are responsible for the racket's position.
- Joints 4, 5, and 6 form a spherical wrist where the three axes intersect at a single point. These three are responsible for the racket's orientation. The point where the three axes intersect is called the wrist center.
- The lengths are d1 = 0.30, a2 = 0.40, d4 = 0.35, d6 = 0.15 m. d6 is from the wrist center to the center of the racket face. When the arm is fully extended, the distance from the shoulder to the wrist center is 0.75 m.
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.
| 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° |
- Link length errors alter position only, not orientation, because lengths do not change angles.
- A joint zero error of 0.1° translates to about 1 mm in position, but 0.1–0.2° in orientation . Part 7 measures that a 1° tilt in the racket normal shifts the ball's landing point by a median of 6 cm. Essentially, the zero error alone loses around 1 cm of accuracy.
- With a 14-bit encoder, quantization is negligible. 12-bit is also sufficient for position, but its 0.04° orientation resolution becomes part of the accumulated error.
5. Limitations
- Joints and links were treated as rigid bodies. Backlash and elasticity in belts and reducers, as well as link bending, are errors outside of forward kinematics and were not measured (unmeasured).
- Errors were introduced as mutually independent uniform distributions. Actual calibration errors may be intertwined and differ in magnitude.
- Which DH conventions textbooks other than Craig and Siciliano use could not be confirmed as their main texts were not accessible (unverified).
6. Conclusion
- Forward kinematics is the easy direction going from joint angles to racket pose, and serves as a verification tool for all calculations in parts 4, 5, and 9.
- DH represents the same arm with four numbers per link, while PoE uses one zero pose and six joint axes. Both methods matched at the 10⁻¹⁶ level.
- The spherical wrist fixes the wrist center, enabling inverse kinematics to be decoupled.
- From a hardware perspective, joint zero calibrationhas a greater impact on racket orientation error than encoder resolution.
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.
- Lynch, Park, Modern Robotics, 2017, open preprint, Chapter 4 Forward Kinematics (4.1 PoE, Eq. 4.14), Appendix C (DH Parameters).
- D'Ambrosio et al., Achieving Human Level Competitive Robot Table Tennis, arXiv:2408.03906, Section II-A (Arm and gantry configuration).
- Craig, Introduction to Robotics: Mechanics and Control 4th ed. (Pearson); Siciliano et al., Robotics: Modelling, Planning and Control(Springer 2009): Publisher chapter list verified only, main text unverified.