TT Lab
Blog

한국어 English 日本語 中文

Get started
Blog

Blog

Classical Control Baseline for a Table Tennis Robot: See, Predict, Swing, and Count the Returns

Status: Draft (2026-10-18), empirical measurement. Camera frequency, noise, delay, and robot velocity/force limits are all assumed values. Measurements were taken on 2026-10-18 on the same temporary pod as Part 2 (mini PC node Intel Core Ultra 9 185H, upper limit 3 CPU cores, 3 GiB memory, no GPU, mujoco 3.16.0). Physics time step 0.5 ms, racket contact solref (−4e6, −34) (values determined in Section 7 of Part 2). For the balls, we used the first 100 of the 500 samples (seed 0) identical to Part 2 from DeepMind's publicly released initial states, and under the 100 ms delay and 30 Hz conditions, only the first 50 were run due to time constraints. Each value was run once per condition. The first three conditions took 1,573 s for 300 runs (3 processes). Raw data is in the working directory tt-robot/out/(three F1 tables and raw JSON per run) and tt-robot/logs/ .

Table of Contents

1. Intuition: The Floor Reinforcement Learning Must Clear

When teaching a table tennis robot via reinforcement learning, we first need a definition of "good." The baseline in this post is a hand-coded classical controller. It sees the ball, predicts its flight path using physical equations, computes the hitting spot and racket angle, and sends the arm to that position. There is no learning involved. To know what reinforcement learning actually improves, we must first find out how many returns this baseline makes and where it fails.

2. Robot: Gantry 2-Axis + Wrist 2-Axis

Part Value (all assumed)
Gantry Plane 38 cm behind the table endline (y = −1.75 m), spanning x ±0.9 m, height z −0.15–0.7 m
Wrist Two axes for yaw and pitch, ±1.4 rad. Racket face center is 0.15 m from the pitch axis
Limits Gantry 4 m/s, 40 m/s², force 400 N (horizontal) and 300 N (vertical). Wrist 20 and 30 rad/s, 400 and 600 rad/s², 20 N·m

This layout corresponds to the "rail 2-axis + wrist 2-axis" (stages 2 and 3) from the hardware plan in Part 3. Because the gantry lacks a depth (y) axis, the exact moment the reachable y of the racket meets the ball's y defines the hitting time.

3. Pipeline: One Function per Step

  1. Ball state estimation. Assuming the camera only observes the ball's position (120 Hz, noise σ 3 mm, delay 30 ms), we fit position, velocity, and spin via least squares. Since spin is only visible through trajectory curvature, we include a term pulling it toward prior values.
  2. Flight prediction. Gravity, drag, and Magnus forces are solved using RK4, and table bounces are handled via an impulse model. Coefficients are measured simulator values from Part 2.
  3. Shot determination. The reflection velocity required to reach the target landing spot (center of opponent's court) is calculated via shooting methods, and the mirror law and impulse model determine the racket normal and swing velocity.
  4. Inverse kinematics. The two wrist angles follow directly from the normal vector, and the gantry requires a single subtraction (code below).
  5. Joint trajectory. Connects the current state to the hitting instant (position, velocity, zero acceleration) using a fifth-order polynomial. The pitch velocity at impact translates directly to the swing.
  6. Joint control. Tracks trajectories using computed torque (PD + feedforward), clamped by force limits.
  7. Replanning. Plans once 0.2 s before the bounce, and after the bounce, realigns trajectories every 50 ms using new observations.
def ik(c, n, rb):
    """원하는 라켓 면 중심 c 와 법선 n → 관절 [x, z, yaw, pitch]."""
    n = np.asarray(n, float) / np.linalg.norm(n)
    th = math.asin(max(-1.0, min(1.0, n[2])))      # pitch
    psi = math.atan2(-n[0], n[1])                   # yaw
    x = c[0] - rb.L * math.sin(th) * math.sin(psi)  # 갠트리는 손목 오프셋을 빼면 끝
    z = c[2] - rb.L * math.cos(th)
    y_res = c[1] - (rb.y_g - rb.L * math.sin(th) * math.cos(psi))   # 0 이어야 닿는다
    q = np.array([x, z, psi, th])
    ok = bool(np.all(q >= np.array(rb.lo)) and np.all(q <= np.array(rb.hi)))
    return q, y_res, ok

(Excerpted from TT Lab experiment code ttsim.py ; docstrings and comments have been shortened.)

Because the orthogonal gantry maps its two axes directly to the racket position, there are no singularities, multiple solutions, or numerical inverse kinematics. With a 6-axis arm, the same task would require numerical optimization and singularity avoidance. Rotating the pitch makes the velocity of the racket face center point precisely orthogonal to the face, cleanly separating "where to aim" (angle) from "how hard to hit" (pitch velocity).

4. Results

Condition Camera (frequency, noise, delay, assumed) Planner Physics Coefficients Ball Set Return Success Hit but Failed Missed Planning Failure
True State True state known directly Measured simulator values 100 62% 16 2 20
120 Hz, 30 ms delay 120 Hz, 3 mm, 30 ms Measured simulator values 100 60% 8 9 23
Literature coefficients for planner only 120 Hz, 3 mm, 30 ms Literature (TT3D drag/Magnus, table e 0.85, μ 0.3) 100 48% 11 11 30
120 Hz, 100 ms delay 120 Hz, 3 mm, 100 ms Measured simulator values 50 26% 4 17 16
30 Hz, 100 ms delay 30 Hz, 10 mm, 100 ms Measured simulator values 50 2% 0 17 32

"Hit but failed" combines balls landing out-of-bounds and into the robot's own court. The 50 balls in the 100 ms delay condition are identical to the first 50 balls of the 100-ball set under the 30 ms condition, where the success rate for those 50 was also 60%.

고전 제어 기준선: 공이 어디서 실패하나 공개 초기 상태 표본(앞의 셋 100개, 뒤의 둘 50개). 카메라 수치는 가정값. 참 상태를 안다 62% 120 Hz·지연 30 ms 60% 플래너만 문헌 계수 48% 120 Hz·지연 100 ms 26% 30 Hz·지연 100 ms 2% 반환 성공 맞혔으나 탁자 밖 맞혔으나 자기 코트 못 맞힘 계획 실패 라켓 추종 오차 중앙값 0.05–0.08 cm. 제어보다 작업 공간·지연이 실패를 가릅니다.
Figure: Return Success and Failure Types by Condition
Condition Median Hitting Time Error Median Ball Prediction Error at Impact Median Racket Tracking Error Median Landing Error for Successful Returns
True State 1.6 ms 1.9 cm 0.08 cm 21.3 cm
120 Hz, 30 ms delay 2.3 ms 3.8 cm 0.07 cm 18.5 cm
Literature coefficients for planner only 2.0 ms 3.3 cm 0.06 cm 12.4 cm
120 Hz, 100 ms delay 2.2 ms 9.7 cm 0.07 cm 21.0 cm
30 Hz, 100 ms delay 2.2 ms 34.6 cm 0.05 cm 12.4 cm (1 ball)

5. What Explains Failures

6. Limitations

7. Moving on to the Next Part

Next, we will pit two reinforcement learning approaches (a hybrid learning only strike parameters, and a direct joint-target approach) against this baseline using the same ball samples, camera assumptions, and robot limits (Part 7). Before that, in Part 6, we will review the DeepMind robot's limitations from their original paper and analyze spin mechanics via simulation. We will also include failure-reason breakdowns to clearly show which failure modes reinforcement learning eliminates.

TT's Note. The arm moved precisely with a 0.7 mm error, yet missed four out of ten balls. The problem wasn't the arm—it was the position (workspace) and the eyes (delay). Please fix the vision system first!

References

All links were verified active as of 2026-10-18.

Sign in to like

Comments

No comments yet.

Sign in to leave a comment