TT Lab
요금제

한국어

시작하기
블로그

블로그

탁구 로봇의 고전 제어 기준선: 보고, 예측하고, 휘두르면 몇 개나 넘길까

상태: 초안 (2026-10-18), 실측. 카메라 주기·잡음·지연과 로봇의 속도·힘 한계는 모두 가정값입니다. 측정은 2026-10-18 에 2편과 같은 임시 파드(미니 PC 노드 Intel Core Ultra 9 185H, 상한 CPU 3코어·메모리 3 GiB, GPU 없음, mujoco 3.16.0)에서 했습니다. 물리 시간 간격 0.5 ms, 라켓 접촉 solref (−4e6, −34)(2편 7절에서 정한 값)입니다. 공은 DeepMind 공개 초기 상태에서 2편과 같은 500개 표본(seed 0)의 앞쪽 100개를 썼고, 지연 100 ms 와 30 Hz 조건은 시간 때문에 앞쪽 50개만 돌렸습니다. 조건마다 한 번 돌린 값입니다. 앞의 세 조건 300회에 1,573 s 가 걸렸습니다(프로세스 3개). 원자료는 작업 디렉터리 tt-robot/out/(F1 표 세 개와 회차별 원자료 JSON)과 tt-robot/logs/ 에 있습니다.

목차

1. 직관: 강화학습이 넘어야 할 바닥

강화학습으로 탁구 로봇을 가르친다고 할 때, 「잘한다」의 기준이 먼저 있어야 합니다. 이 글의 기준선은 사람이 손으로 짠 고전 제어입니다. 공을 보고, 날아갈 길을 물리 식으로 예측하고, 칠 자리와 라켓 각도를 계산해 팔을 그 자리로 보냅니다. 학습은 하나도 없습니다. 이 기준선이 몇 개를 넘기는지, 그리고 어디서 실패하는지를 알아야 강화학습이 무엇을 줄였는지 말할 수 있습니다.

2. 로봇: 갠트리 2축 + 손목 2축

부분 값(모두 가정값)
갠트리 로봇 쪽 끝선 38 cm 뒤(y = −1.75 m)의 평면에서 가로 x ±0.9 m, 높이 z −0.15–0.7 m
손목 yaw, pitch 두 축, ±1.4 rad. 라켓 면 중심은 pitch 축에서 0.15 m
한계 갠트리 4 m/s, 40 m/s², 힘 400 N(가로)·300 N(높이). 손목 20·30 rad/s, 400·600 rad/s², 20 N·m

3편의 하드웨어 계획에서 「레일 2축 + 손목 2축」(2·3단계)에 해당하는 모양입니다. 갠트리에는 깊이(y) 축이 없어서, 라켓이 닿을 수 있는 y 와 공의 길이 만나는 순간이 곧 타격 시각입니다.

3. 파이프라인: 단계마다 함수 하나

  1. 공 상태 추정. 카메라가 공의 위치만 본다고 두고(120 Hz, 잡음 σ 3 mm, 지연 30 ms), 최소제곱으로 위치·속도·회전을 맞춥니다. 회전은 궤적의 휨으로만 보이므로 사전값 쪽으로 당기는 항을 둡니다.
  2. 비행 예측. 중력, 항력, 마그누스 힘을 RK4 로 풀고, 탁자 바운드는 충격량 모델로 처리합니다. 계수는 2편에서 잰 시뮬레이터 값입니다.
  3. 타격 결정. 목표 착지점(상대 코트 가운데)으로 보낼 반사 속도를 사격법으로 구하고, 거울 법칙과 충격량 모델로 라켓 법선과 휘두를 속도를 정합니다.
  4. 역기구학. 손목 두 각은 법선에서 바로 나오고, 갠트리는 빼기 하나입니다(아래 코드).
  5. 관절 궤적. 현재 상태에서 타격 순간의 (위치, 속도, 가속도 0)까지 5차 다항식으로 잇습니다. pitch 의 타격 속도가 곧 휘두르기입니다.
  6. 관절 제어. 계산 토크(PD + 피드포워드)로 따라가고, 힘 한계에서 자릅니다.
  7. 다시 계획. 바운드 전 0.2 s 에 한 번 계획하고, 바운드 뒤에는 50 ms 마다 새 관측으로 다시 맞춰 궤적을 이어 붙입니다.
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

(TT Lab 실험 코드 ttsim.py 에서 발췌했고 독스트링과 주석은 줄였습니다.)

직교 갠트리는 두 축이 라켓 위치에 그대로 더해지므로 특이점, 다중해, 수치 역기구학이 없습니다. 6축 팔이라면 같은 일을 수치 최적화와 특이점 회피로 풀어야 합니다. pitch 를 돌리면 라켓 면 중심의 속도가 정확히 면의 법선 방향이 되어, 「어디로 향할지」(각도)와 「얼마나 세게 칠지」(pitch 속도)가 깔끔하게 갈립니다.

4. 결과

조건 카메라(주기·잡음·지연, 가정값) 플래너의 물리 계수 공 반환 성공 맞혔으나 실패 못 맞힘 계획 실패
참 상태 참 상태를 바로 앎 시뮬레이터 실측값 100 62% 16 2 20
120 Hz·지연 30 ms 120 Hz, 3 mm, 30 ms 시뮬레이터 실측값 100 60% 8 9 23
플래너만 문헌 계수 120 Hz, 3 mm, 30 ms 문헌(TT3D 항력·마그누스, 탁자 e 0.85·μ 0.3) 100 48% 11 11 30
120 Hz·지연 100 ms 120 Hz, 3 mm, 100 ms 시뮬레이터 실측값 50 26% 4 17 16
30 Hz·지연 100 ms 30 Hz, 10 mm, 100 ms 시뮬레이터 실측값 50 2% 0 17 32

「맞혔으나 실패」는 탁자 밖과 자기 코트를 합친 수입니다. 지연 100 ms 조건의 50개는 30 ms 조건 100개의 앞쪽 50개와 같은 공이고, 그 50개에서 30 ms 조건의 성공률도 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. 제어보다 작업 공간·지연이 실패를 가릅니다.
그림: 조건별 반환 성공과 실패 종류
조건 타격 시각 오차 중앙값 타격 시각의 공 예측 오차 중앙값 라켓 추종 오차 중앙값 성공한 공의 착지 오차 중앙값
참 상태 1.6 ms 1.9 cm 0.08 cm 21.3 cm
120 Hz·지연 30 ms 2.3 ms 3.8 cm 0.07 cm 18.5 cm
플래너만 문헌 계수 2.0 ms 3.3 cm 0.06 cm 12.4 cm
120 Hz·지연 100 ms 2.2 ms 9.7 cm 0.07 cm 21.0 cm
30 Hz·지연 100 ms 2.2 ms 34.6 cm 0.05 cm 12.4 cm(1개)

5. 무엇이 실패를 가르나

6. 한계

7. 다음 편으로

다음은 같은 공 표본, 같은 카메라 가정, 같은 로봇 한계에서 강화학습 두 가지(타격 파라미터만 배우는 하이브리드, 관절 목표를 직접 내는 방식)를 이 기준선과 나란히 놓는 것입니다(7편, 준비 중). 그 전에 6편에서 DeepMind 로봇의 한계를 원문으로 읽고 회전 문제를 시뮬레이터로 따져 봅니다. 실패 이유별 개수를 함께 남겨, 강화학습이 어느 실패를 줄였는지 보이게 하겠습니다.

티티 한마디. 팔은 0.7 mm 오차로 정확히 움직였는데도 열 개 중 넷을 놓쳤어요. 팔이 아니라 자리(작업 공간)와 눈(지연)이 문제였어요. 빨리 보는 눈부터 챙겨 주세요!

참고

모든 링크는 2026-10-18 에 열람해 열리는 것을 확인했습니다.

로그인하면 좋아요를 누를 수 있습니다

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다