AEGLOSLAB 제어공학 종합 핸드북

제7부 실전: ROS2 Humble 프로젝트

7.10 실전 ⑥ 로봇팔 관절공간 제어 (계산토크법)

제7부 실전: ROS2 Humble 프로젝트 · 여섯 번째 프로젝트(보강 장). 7.3(이동로봇)·7.4(도립진자)에 이어 다관절 로봇팔을 세운다 — 7.8.4가 "로봇팔 관절 궤적·드론 경로의 표준"이라 지나가며 언급했던 그 대상을, 여기서 실제로 세운다. 6.2.4의 피드백 선형화(계산토크법)를 SISO에서 MIMO 매니퓰레이터로 그대로 확장하고, 4.5.12가 "짝지을까 한꺼번에 다룰까" 물었던 MIMO 질문에 계산토크법이 어떻게 답하는지 실측으로 보인다.

✅ 검증됨: 2링크 평면 로봇팔의 $M(q),C(q,\dot{q}),G(q)$를 라그랑주 역학으로 손으로 유도하고 sympy로 독립 재검증(verify/ce44_derive_sympy.py) — 표준 2링크 팔 공식과 정확히 일치, Ṁ−2C 반대칭(수동성) 확인. 독립 관절 PID+중력보상 vs 계산토크법을 ce-verify 도커에서 RK4 시뮬레이션으로 비교(verify/ce44_manipulator.py) — 완만한 궤적(2.0 s)에서 계산토크 RMS 오차가 PID 대비 최대 5937배 작고, 공격적 궤적(0.4 s)에서 PID 오차가 0.04→0.45 rad로 11~13배 급증하는 동안 계산토크는 실질적으로 정확히 추종.

이 장을 마치면 2링크 로봇팔의 운동방정식 $M(q)\ddot{q}+C(q,\dot{q})\dot{q}+G(q)=\tau$를 세우고, 독립 관절 PID+중력보상과 계산토크법(MIMO 피드백 선형화)을 실제로 시뮬레이션에서 비교하며, 계산토크법이 왜 6.2.4·4.5.12를 잇는 "모델 기반 디커플링의 완성형"인지 설명할 수 있어야 한다.

7.10.1 왜 로봇팔 — 완전구동 MIMO 비선형의 정수

지금까지 제7부의 두 프로젝트는 각각 다른 결을 보여줬다:

  • 7.3(이동로봇): 운동학 수준 제어 — 속도 명령을 순간적으로 실현한다고 가정하고 기하(Pure Pursuit)로 조향각을 정했다. 동역학(질량·관성)은 안 다뤘다.
  • 7.4(도립진자): 과소구동(underactuated) — 입력 하나($F$)로 상태 둘(카트 위치·막대 각)을 다뤄야 했다. 게다가 본질적으로 불안정.

로봇팔은 다른 유형이다. 관절마다 액추에이터가 있어 완전구동(fully actuated) — 입력 수(토크 $\tau_1,\tau_2,\ldots$)와 자유도 수(관절각 $q_1,q_2,\ldots$)가 같다. 불안정하지도 않다(입력이 없으면 중력 방향으로 처질 뿐, 발산하지 않는다). 그런데도 로봇팔 제어가 쉽지 않은 이유는 동역학 자체가 관절끼리 강하게 얽힌 MIMO 비선형이기 때문이다:

  • 관절1을 움직이면 관절2에서 본 유효 관성이 바뀐다(반대도 마찬가지) — $M(q)$가 $q$에 의존.
  • 한 관절의 속도가 다른 관절에 원심력·코리올리 힘으로 전달된다 — $C(q,\dot{q})\dot{q}$.
  • 자세마다 중력이 각 관절에 걸리는 토크가 다르다 — $G(q)$.

1.1.4가 "다물체계는 라그랑주 역학이 표준"이라 예고했던 바로 그 상황이고, 6.2.4가 "계산 토크 제어가 [피드백 선형화]다"라며 로보틱스를 한 문장으로 예고했던 그 대상이다. 이 장은 그 두 예고를 실제로 채운다.

7.10.2 2링크 평면 로봇팔 모델

단순화(정직하게 밝힘): 실물 로봇팔(6+ 자유도 공간 팔)이 아니라 평면(2D) 2링크로 줄인다. 각 링크의 질량도 분포시키지 않고 링크 끝에 점질량으로 집중시킨다($lc1=l1, lc2=l2$, 링크 자체의 회전관성 $I=0$) — 교과서의 "이중진자(double pendulum)" 단순화와 같다. 실제 팔은 링크에 분포 질량·회전관성이 있어 $M,C,G$에 항이 더 붙지만(7.10.8), 구조는 동일하다.

  • 관절각 $q1, q2$ — +x축(수평) 기준으로 잰다(로보틱스 표준 관행). $q1=0$은 링크1이 수평, $q2=0$은 링크2가 링크1의 연장선.
  • 링크 길이 $l1, l2$, 점질량 $m1$(관절2 위치, 즉 링크1 끝)·$m2$(말단, 링크2 끝), 중력가속도 $g$.
  • 관절 토크 $\tau1, \tau2$가 제어 입력.
q1 q2 τ1 τ2 m2 g m1 g l1 l2 m1 m2
2링크 평면 로봇팔: 점질량·자유물체도

⚠️ 각 관례 주의: $q$를 수직 기준(7.4의 $\theta$처럼)이 아니라 수평 기준으로 정했다 — 그래서 중력항 $G(q)$에 cos가 나온다(7.4은 $\theta$ 근처 $\sin\theta\approx\theta$ 선형화라 다른 형태였다). 관례가 다르면 부호·삼각함수가 바뀌니, 다른 문헌과 비교할 때 이 정의부터 맞춰야 한다.

7.10.3 동역학 — 라그랑주 역학으로 M(q), C(q,q̇), G(q) (검증됨)

절차(라그랑주 역학, 1.1.4 예고): 점질량들의 위치 $(x1,y1),(x2,y2)$를 $q1,q2$로 쓰고, 운동에너지 $T$·위치에너지 $V$를 구해 L=T−V, 오일러-라그랑주 방정식 $d/dt(\partial L/\partial\dot{q}_i) - \partial L/\partial q_i = \tau_i$을 적용한다.

$$\begin{aligned} x_1 &= l_1 \cos(q_1) & x_2 &= l_1 \cos(q_1) + l_2 \cos(q_1+q_2) \\ y_1 &= l_1 \sin(q_1) & y_2 &= l_1 \sin(q_1) + l_2 \sin(q_1+q_2) \end{aligned}$$

$$\begin{aligned} T &= \tfrac{1}{2}m_1(\dot{x}_1^2+\dot{y}_1^2) + \tfrac{1}{2}m_2(\dot{x}_2^2+\dot{y}_2^2) \\ V &= m_1 g y_1 + m_2 g y_2 \end{aligned}$$

손으로 미분·정리하면(그리고 손 대수가 틀리기 쉬운 지점이라 sympy로 독립 재검증, verify/ce44_derive_sympy.py):

$$M(q) = \begin{bmatrix} (m_1+m_2)l_1^2 + m_2l_2^2 + 2m_2l_1l_2\cos(q_2) & m_2l_2^2 + m_2l_1l_2\cos(q_2) \\ m_2l_2^2 + m_2l_1l_2\cos(q_2) & m_2l_2^2 \end{bmatrix}$$

$$C(q,\dot{q}) = \begin{bmatrix} -h\cdot\dot{q}_2 & -h\cdot(\dot{q}_1+\dot{q}_2) \\ h\cdot\dot{q}_1 & 0 \end{bmatrix}, \quad h = m_2 l_1 l_2 \sin(q_2)$$

$$G(q) = \begin{bmatrix} (m_1+m_2)\,g\,l_1\cos(q_1) + m_2\,g\,l_2\cos(q_1+q_2) \\ m_2\,g\,l_2\cos(q_1+q_2) \end{bmatrix}$$

운동방정식(매니퓰레이터 방정식):

$$M(q) \ddot{q} + C(q,\dot{q}) \dot{q} + G(q) = \tau$$

검증 방법과 결과 — 원점 위치를 $q1,q2$로 미분해 $T,V$를 세우고 오일러-라그랑주를 sympy로 직접 전개(교과서 공식을 베끼지 않고 처음부터 다시 유도), 그 결과를:

  1. $M(q)$는 $\ddot{q}$의 계수로 자동 추출, $G(q)$는 $\dot{q}=0$일 때의 잔여항, $C(q,\dot{q})\dot{q}$는 나머지.
  2. 크리스토펠 기호(c_kj = Σᵢ ½(∂M_kj/∂qᵢ + ∂M_ki/∂qⱼ − ∂M_ij/∂qₖ)·q̇ᵢ)로 $C(q,\dot{q})$를 독립적으로 다시 구성 — 위 1번의 $C\cdot\dot{q}$와 정확히 일치(sympy.simplify로 차이 0 확인).
  3. 이렇게 얻은 $M,C,G$가 위 박스의 (표준 2링크 점질량 공식과 동일한) 식과 대수적으로 완전히 일치(차이 0).
  4. 수동성(passivity) 성질: $\dot{M}(q) - 2C(q,\dot{q})$가 반대칭($N+N^T=0$)임을 확인 — 로봇 동역학의 유명한 구조적 성질(에너지가 계산토크 등 특정 제어기 없이도 물리적으로 소산되지 않음을 보장, 적응/강인 로봇 제어 이론의 기반)이 이 특정 유도에서도 성립함을 실제로 검산한 것.
✅ 검증됨 (sympy, ce-verify 도커):
  M(q) - M_교과서공식  = 영행렬
  C(크리스토펠) - C_교과서공식 = 영행렬
  G(q) - G_교과서공식  = 영벡터
  Ṁ - 2C 의 (N + Nᵀ)  = 영행렬  (반대칭 확인)

6.2.4에서 ẍ=−sin(x)+u라는 스칼라 예제로 봤던 "비선형을 상쇄"가, 여기서는 $2\times2$ 행렬 $M(q)$와 행렬-벡터 $C(q,\dot{q})\dot{q}+G(q)$로 그대로 확장된다 — 다음 절의 핵심이다.

7.10.4 제어 A — 독립 관절 PID + 중력보상

가장 흔한 실무 접근: 관절마다 독립 SISO PID(2.5·3.3)를 두고, 지배적 비선형인 중력만 피드포워드로 보상한다.

$$\tau_i = K_p\cdot e_i + K_i\cdot\int e_i\,dt + K_d\cdot\dot{e}_i + G_i(q)$$ — $e_i = q_{d,i} - q_i$, 관절마다 독립

$G(q)$는 7.10.3에서 구한 정확한 중력항 — 이것만큼은 자세마다 계산해 넣는다(그러지 않으면 자세에 따라 정상상태 오차가 남는다, 2.5.6 실무 함정과 같은 내용). 나머지($M(q)$의 관절 간 결합, $C(q,\dot{q})\dot{q}$)는 무시하고 관절마다 고정 게인 $K_p,K_d$로 구동한다.

왜 저속에서는 되고 고속에서는 실패하나 — $M(q)$의 (1,1) 원소를 직접 보면 답이 나온다. $m1=m2=l1=l2=1$로 두면:

$$M_{11}(q_2) = (m_1+m_2)l_1^2 + m_2l_2^2 + 2m_2l_1l_2\cos(q_2) = 3 + 2\cos(q_2)$$ → $q_2=0$(팔을 편 자세)일 때 $M_{11}=5$, $q_2=\pi$(팔을 접은 자세)일 때 $M_{11}=1$

관절1에서 본 유효 관성이 자세만으로 5배 변한다(7.10.3에서 검증된 $M(q)$ 식에 대입한 결과). 고정 $K_p,K_d$는 이 변화를 전혀 모른다 — $M11=1$에 맞춘 게인은 $M11=5$에서 느려지고, 그 반대는 진동하기 쉽다. 여기에 더해 속도가 커지면 $C(q,\dot{q})\dot{q}$ 항(h=m2l1l2 sin(q2), 속도의 제곱·곱에 비례)이 무시 못 할 크기로 관절1↔2 사이에 전달된다 — 저속에서는 $\dot{q}$가 작아 $C(q,\dot{q})\dot{q}\approx0$이라 묻히지만, 고속·급가속에서는 이 항이 지배적이 된다. 7.10.6에서 이 열화를 실측한다.

7.10.5 제어 B — 계산토크법 (MIMO 피드백 선형화)

6.2.4의 발상 "비선형을 상쇄해 선형으로 만들자"를 행렬로 그대로 적용한다. 제어 입력을:

$$\tau = M(q) v + C(q,\dot{q}) \dot{q} + G(q) \qquad v = \ddot{q}_d + K_d\cdot\dot{e} + K_p\cdot e$$

로 두면($M(q)$가 가역이라 가정 — 특이 자세만 아니면 성립), 실제 플랜트에 대입해:

$$M(q)\ddot{q} + C(q,\dot{q})\dot{q} + G(q) = \tau = M(q)v + C(q,\dot{q})\dot{q} + G(q)$$

$$\to M(q)\ddot{q} = M(q)v \quad\to\quad \ddot{q} = v$$ — $M(q)$가 정확히 약분됨!

$v = \ddot{q}d + K_d\cdot\dot{e} + K_p\cdot e$를 대입하면 $\ddot{q} = \ddot{q}d + K_d\cdot\dot{e} + K_p\cdot e$, 즉:

$$\ddot{e} + K_d\cdot\dot{e} + K_p\cdot e = 0$$ — 오차 동역학 — 관절마다 완전히 분리된 2차 선형계

$K_p,K_d$가 대각행렬이면 이 식은 관절별로 완전히 독립이다 — 관절1 오차가 관절2 게인과 무관하게 $s^2+K_d,_1s+K_p,_1=0$을 그대로 따른다(1.3의 2차계 표준형). $M(q)$의 자세의존 관성도, $C(q,\dot{q})\dot{q}$의 속도결합도 전부 상쇄됐다 — 7.10.4가 무시했던 바로 그 두 항을, 계산토크법은 매 순간 정확히 계산해 지운다.

τ q, q̇ 기준 궤적 qd, q̇d, q̈d (7.8) 오차 e=qd−q, ė=q̇d−q̇ v = q̈d + Kd·ė + Kp·e q, q̇ (관절 상태) τ = M(q)·v + C(q,q̇)·q̇ + G(q) 2링크 로봇팔 M(q)q̈+C(q,q̇)q̇+G(q)=τ

4.5.12와의 연결: 4.5.12는 MIMO 플랜트를 "분산 SISO로 짝지을까, 전면적으로 다룰까" 묻고, 정상상태 이득행렬 $G(0)$만 보는 RGA로 짝짓기를 판단하거나, 최악에는 디커플링 보상기 $D(s)\approx G(s)^{-1}G_{\mathrm{desired}}(s)$로 루프를 인위적으로 풀라고 했다. 계산토크법은 그 디커플링 보상기의 극단형이다 — 정상상태 한 점의 선형 근사($G(0)$)가 아니라, 매 순간의 정확한 비선형 모델($M(q),C(q,\dot{q}),G(q)$)로 결합을 상쇄한다. 4.5.12가 "언제 전면적 MIMO로 가야 하나" 물었던 질문에 대한 실전 답 하나가 계산토크법이다.

⚠️ 6.2.4의 함정이 그대로 적용된다: 이 상쇄는 $M,C,G$가 정확할 때만 성립한다. 모델이 틀리면 잔여 비선형이 남는다 — 7.10.6에서 실측.

7.10.6 실측 검증 — PID+중력보상 vs 계산토크법

설정: $m1=m2=1.0 \,\mathrm{kg}, l1=l2=1.0 \,\mathrm{m}, g=9.81$. 관절공간 5차 다항식(퀸틱) 궤적(7.8.4 아이디어 재사용) — $q1,q2$ 모두 $0 \to\pi/2 \,\mathrm{rad}$(90°), 경계 속도·가속도 0. 두 소요시간으로 비교:

  • 완만한 궤적: $T=2.0\,\mathrm{s}$
  • 공격적 궤적: $T=0.4\,\mathrm{s}$

(5차 다항식의 속도는 $\Delta Q/T$, 가속도는 $\Delta Q/T^2$에 비례하므로 $T$를 5배 줄이면 속도 스케일 5배, 가속도 스케일 25배 커진다)

두 제어기 모두 같은 Kp=diag(225,225), Kd=diag(30,30)(계산토크 기준 $\omega_n=15 \,\mathrm{rad/s}, \zeta=1$ 임계감쇠, 1.3 표준형)를 쓴다 — PID+중력보상 쪽에 유리하게 봐주지 않는다(실무에서도 게인은 "대표 자세"에서 한 번 튜닝해 고정하지, $q$마다 바꾸지 않는다 — PID+중력보상은 Ki=diag(20,20)도 추가). RK4 적분, dt=0.0005 s.

✅ 실측 결과 (verify/ce44_manipulator.py, ce-verify 도커):

--- 완만한 궤적 T=2.0s ---
  PID+중력보상   : RMS 오차 = [0.04035, 0.01650] rad   피크 = [0.07905, 0.03518] rad
  계산토크법     : RMS 오차 = [0.00001, 0.00001] rad   피크 = [0.00002, 0.00003] rad
  비율(PID/계산토크): 관절1 ×5937   관절2 ×1631

--- 공격적 궤적 T=0.4s ---
  PID+중력보상   : RMS 오차 = [0.44872, 0.21653] rad   피크 = [0.70914, 0.38535] rad
  계산토크법     : RMS 오차 = [0.00054, 0.00068] rad   피크 = [0.00123, 0.00168] rad
  비율(PID/계산토크): 관절1 ×839    관절2 ×316

--- 속도 민감도 (완만 → 공격, RMS) ---
  PID+중력보상   관절1: 0.04035 → 0.44872 rad  (×11.1)   관절2: 0.01650 → 0.21653 rad (×13.1)
  계산토크법     관절1: 0.00001 → 0.00054 rad  (×78.7)   관절2: 0.00001 → 0.00068 rad (×67.7)

읽는 법:

  • 완만한 궤적에서도 계산토크법이 PID+중력보상보다 3~4자릿수 정확하다 — 7.10.4에서 본 "자세만으로 5배 바뀌는 유효 관성"이 저속에서도 이미 오차를 만들고 있었다는 뜻(고속 전용 문제가 아니다).
  • 공격적 궤적에서 PID+중력보상의 절대 오차가 0.04→0.45 rad로 11~13배로 커진다 — 45도 가까운 오차로, 실전에서는 명백한 추종 실패다. 반면 계산토크법은 0.0005~0.0007 rad(0.03~0.04°) — 사실상 완벽한 추종을 유지한다.
  • 정직한 함정: 상대 배율만 보면 계산토크법의 오차도 완만→공격 사이 ×68~79로 PID(×11~13)보다 더 크게 증가한다. 하지만 절대 크기가 3~4자릿수 작아서 실무적으로는 무의미한 차이다 — 상대 배율 하나만 떼어 보면 오도된다는, 숫자 읽을 때 흔한 함정을 스스로 보여 준다.

7.10.6.1 정직 — 모델이 틀리면? (계산토크의 대가)

6.2.4·7.10.5의 경고 — "정확한 모델이 있어야 상쇄가 성립" — 를 직접 확인한다. 제어기가 $m2$를 실제보다 20% 크게 안다고 가정하고(m2_모델=1.2×m2_실제) 계산토크를 다시 실행하면:

✅ 검증됨 (모델 오차 20%, ce44_manipulator.py):
완만 T=2.0s: 계산토크(정확)  RMS=[0.00001,0.00001]   계산토크(20%오차) RMS=[0.00029,0.00787]
공격 T=0.4s: 계산토크(정확)  RMS=[0.00054,0.00068]   계산토크(20%오차) RMS=[0.03221,0.07198]

모델 오차 20%만으로도 계산토크의 오차가 완만 궤적에서 최대 787배, 공격 궤적에서 최대 60~106배 악화된다 — 6.2.4 함정 ①이 정확히 실측으로 재현됐다. 그래도 공격적 궤적에서 계산토크(모델 오차 20%)의 RMS(0.032, 0.072)는 PID+중력보상(0.449, 0.217)보다 여전히 3~14배 낫다 — "모델이 조금 틀려도 계산토크가 무용해지지는 않는다, 다만 우위가 압도적에서 상당한 수준으로 줄어든다"가 정직한 결론이다.

7.10.7 ROS2로 — ros2_control 다중관절 인터페이스

7.1.5의 controller_manager/hardware_interface가 다관절 팔에서는 이렇게 대응한다(재유도하지 않고 이 장의 토크식이 어디에 꽂히는지만 본다):

  • 7.10.4(PID+중력보상)의 자연스러운 자리: joint_trajectory_controller를 effort 커맨드 인터페이스로 구성하면, 컨트롤러가 관절마다 gains.<joint>.{p,i,d} 파라미터로 독립 PID를 구동하고 궤적의 위치·속도를 추종한다 — 구조적으로 7.10.4와 결이 같다(단, 표준 joint_trajectory_controller가 이 장의 $G(q)$ 같은 명시적 중력 피드포워드까지 자동으로 넣어 주는 것은 아니다 — 필요하면 직접 추가하거나 커스텀 컨트롤러로 간다).
  • 7.10.5(계산토크법)의 자리: 관절 하나만 보는 표준 컨트롤러로는 안 된다 — $M(q),C(q,\dot{q}),G(q)$를 계산하려면 모든 관절의 위치·속도를 한 번에 봐야 한다. 실전에서는 state_interfaces(모든 관절의 position,velocity)를 구독하고 command_interfaces(모든 관절의 effort)에 쓰는 커스텀 ros2_control 컨트롤러 플러그인을 작성해, 내부에서 동역학 라이브러리(KDL·Pinocchio 등 — 이 책 범위 밖, 7.10.8)로 $M,C,G$를 계산한다.
# (개념 코드 — 커스텀 컨트롤러의 update() 골격, 검증 필요/독자 환경)
def update(self, time, period):
    q  = np.array([self.state_interfaces[f'joint{i}/position'].get_value() for i in (1,2)])
    qd = np.array([self.state_interfaces[f'joint{i}/velocity'].get_value() for i in (1,2)])
    qref, qdref, qddref = self.trajectory.sample(time)      # 7.8 생성기
    e, ed = qref - q, qdref - qd
    v = qddref + self.Kd @ ed + self.Kp @ e
    tau = M(q) @ v + C(q, qd) @ qd + G(q)                    # 7.10.3/7.10.5
    for i, ti in zip((1,2), tau):
        self.command_interfaces[f'joint{i}/effort'].set_value(ti)

⚠️ 이 절의 인터페이스 구조는 ROS2 Humble ros2_control 표준 동작에 근거해 정확히 서술했으나(7.1.5.1과 같은 정직), 이 책의 헤드리스 컨테이너 검증은 실제 joint_trajectory_controller 파라미터·커스텀 플러그인 빌드까지는 다루지 않는다. 이 장이 실측 검증한 것은 제어 법칙(7.10.4·7.10.5)과 그 성능(7.10.6) 이지, ROS2 통합 코드 자체가 아니다.

7.10.8 정직 — 이 모델이 놓친 것들

  • 강체·마찰 없음: 관절 마찰(쿨롱·점성)·기어박스 백래시·링크 유연성을 전혀 모델링하지 않았다. 실물 팔, 특히 하모닉드라이브 감속기가 있는 팔은 마찰·비선형 백래시가 상당해 이 장의 "이상적 상쇄"가 그대로는 안 맞는다.
  • 2링크 평면 vs 실물 공간 팔: 실제 산업/협동로봇 팔은 6+ 자유도 공간(3D) 구조라 $M(q),C(q,\dot{q}),G(q)$를 손으로(또는 이 장의 sympy 방식으로) 유도하는 것이 비현실적이다 — 실전에서는 재귀 뉴턴-오일러(RNE) 같은 계산적 방법이나 KDL·Pinocchio 같은 동역학 라이브러리로 자동 계산한다(이 책 범위 밖).
  • 점질량 단순화: 링크의 분포 질량·회전관성($I1,I2$)을 뺐다 — 넣으면 $M,C,G$에 항이 늘지만 구조(오일러-라그랑주 절차, 계산토크 상쇄 논리)는 동일하다.
  • 감속비를 무시: 실무 산업로봇 팔은 대개 큰 감속비(50:1~200:1) 하모닉드라이브·사이클로 감속기를 쓴다 — 모터 축에서 보면 반사된 부하 관성이 감속비 제곱으로 작아 보여서, $M(q)$의 자세 의존 변화가 상대적으로 덜 드러난다. 그래서 감속비가 큰 산업로봇은 관절별 독립 PID만으로도 실무에서 대체로 충분하다 — 이 장의 7.10.4가 "저속에서는 허용할 만하다"고 한 것이 산업 현장에서는 "거의 항상 허용할 만하다"로 완화되는 이유다. 반대로 감속비가 작은 직접구동(direct-drive)·협동로봇, 또는 빠르고 역동적인 동작(스포츠·던지기·고속 픽앤플레이스)을 요구할수록 계산토크법 같은 모델 기반 제어의 이득이 커진다 — "어느 쪽이 항상 옳다"가 아니라 감속비·속도 요구가 선택을 결정한다.
  • GUI·실물 검증은 범위 밖: Gazebo 팔 시뮬레이션·MoveIt 모션 플래닝·실물 구동은 이 책의 헤드리스 컨테이너 자동 검증 밖이다(7.4.6과 같은 한계) — 이 장이 검증한 것은 동역학 유도(sympy)·제어 법칙과 그 실측 성능(RK4 시뮬레이션) 이지, 3D 물리·GUI·실제 하드웨어가 아니다.
  • 특이 자세(singularity)는 $M(q)$가 아니라 자코비안 문제: 계산토크법이 쓰는 관절공간 질량행렬 $M(q)$를 7.10.3의 원소로 직접 전개하면 $\det(M) = M11\cdot M22 - M12^2 = m2\cdot l1^2\cdot l2^2\cdot(m1 + m2\cdot\sin^2(q2))$다. $m1,m2,l1,l2>0$인 한 이 값은 어떤 $q2$에서도 0이 되지 않는다($q2=0$·$\pi$에서도 $\sin^2=0$이지만 $m1$ 항이 남아 $\det(M)=m1m2l1^2l2^2>0$) — 우연이 아니라, 운동에너지 $T=\tfrac{1}{2}\dot{q}^TM\dot{q}$가 항상 양수라는 물리적 이유로 관절공간 질량행렬은 모든 자세에서 예외 없이 양의 정부호이기 때문이다(7.10.3이 검증한 Ṁ−2C 반대칭 수동성도 이 정부호성을 전제한다). 따라서 이 장의 계산토크법($\tau=M(q)v+C(q,\dot{q})\dot{q}+G(q)$, 7.10.5)엔 역행렬로 인한 특이점이 없다 — 애초에 $M(q)$만 쓰고 자코비안은 등장하지 않는다.

실제로 $q2=0$(펴짐)·$\pi$(완전히 접힘)에서 특이해지는 것은 이 팔의 기구학적 자코비안(관절속도 → 말단속도 매핑) $J$다: $\det(J) = l1\cdot l2\cdot\sin(q2)$로 그 두 자세에서 정확히 0이 된다. 이것은 역기구학·분해속도(resolved-rate) 제어·말단 힘↔관절 토크 매핑처럼 $J$의 역행렬을 구해야 하는 다른 기법에 영향을 준다 — 실전에서 그런 경우에는 특이 자세 근처를 피하거나 감쇠최소제곱(damped least-squares) 역행렬을 쓴다. 이 장이 검증한 계산토크법 자체는 이 문제를 겪지 않는다.

7.10.9 정리 — 그리고

  • 로봇팔은 7.3(운동학)·7.4(과소구동)과 다른 세 번째 유형 — 완전구동이지만 강하게 결합된 MIMO 비선형(7.10.1).
  • 2링크 평면·점질량 단순화로 $M(q)\ddot{q}+C(q,\dot{q})\dot{q}+G(q)=\tau$를 라그랑주 역학으로 세우고 sympy로 독립 재검증(교과서 공식과 완전 일치, 수동성 반대칭까지 확인)(7.10.2·7.10.3).
  • 독립 관절 PID+중력보상은 자세 의존 관성($M(q)$)·속도 결합($C(q,\dot{q})\dot{q}$)을 무시한다 — 저속에서도 자릿수 단위 오차를, 고속에서는 11~13배 더 큰 오차를 낸다(7.10.4, 실측 7.10.6).
  • 계산토크법(6.2.4의 MIMO 확장, 4.5.12가 가리켰던 디커플링의 완성형)은 $M,C,G$를 정확히 상쇄해 관절별 독립 2차 선형계 $\ddot{e}+K_d\cdot\dot{e}+K_p\cdot e=0$으로 만든다 — 실측 오차가 PID 대비 최대 5937배 작다(7.10.5·7.10.6).
  • 정직: 모델 오차(20%)가 계산토크 오차를 최대 787배 증가시키지만 그래도 PID보다는 낫다(7.10.6.1). 감속비가 큰 실물 산업로봇은 이 장의 결론이 완화된다 — "언제나 계산토크가 우세하다"가 아니라 속도·감속비가 답을 결정한다(7.10.8).

이로써 제7부(7.1~7.6)와 보강 장(7.7~7.9)에 이어, 완전구동 다관절 MIMO 유형의 실전 프로젝트가 더해진다. 이 책의 이론(1.1 라그랑주 예고·4.5.12 MIMO·6.2.4 피드백 선형화)이 로봇팔이라는 한 플랜트에서 다시 수렴했다.

7.10.10 연습·생각해 볼 것

  1. 완전구동 vs 과소구동. 7.4(도립진자)은 입력 1개로 상태 4개를, 이 장의 로봇팔은 입력 2개로 상태 4개($q1,q2,\dot{q}1,\dot{q}2$)를 다룬다. "완전구동"이 정확히 무엇을 뜻하는지, 그것이 안정성과 무슨 상관인지(또는 상관없는지) 설명하라. (7.10.1)
  2. M(q) 손 대입. $m1=m2=l1=l2=1$일 때 $M(q)$의 (1,2) 원소를 $q2=0, \pi/2, \pi$에서 각각 계산하라. 값이 왜 이렇게 변하는지, $C(q,\dot{q})$의 h=m2l1l2 sin(q2)가 $q2=0$에서 0이 되는 이유와 연결해 설명하라. (7.10.3)
  3. 계산토크 유도. $\tau=M(q)v+C(q,\dot{q})\dot{q}+G(q)$를 매니퓰레이터 방정식에 대입해 $\ddot{e}+K_d\cdot\dot{e}+K_p\cdot e=0$이 나오는 과정을 손으로 다시 써 보라. 어느 단계에서 $M(q)$가 약분되는가? (7.10.5)
  4. 4.5.12 연결. 4.5.12의 RGA·디커플링 보상기 $D(s)\approx G(s)^{-1}G_{\mathrm{desired}}(s)$와 계산토크법 $\tau=M(q)v+C \dot{q}+G$가 "같은 발상의 다른 정밀도"인 이유를 설명하라. RGA는 왜 정상상태 한 점만 보는데 계산토크는 그러지 않은가? (7.10.5)
  5. 속도 민감도 숫자. 7.10.6의 "완만→공격 배율"에서 PID+중력보상은 ×11~13인데 계산토크법은 ×68~79로 더 크다. 그런데도 왜 계산토크법이 실무적으로 훨씬 낫다고 하는가? 배율만 보고 판단하면 안 되는 이유를 한 문장으로. (7.10.6)
  6. 모델 오차 트레이드오프. $m2$ 20% 오차 실험(7.10.6.1)에서 계산토크의 우위가 압도적(수천 배)에서 몇 배 수준으로 줄었다. 실무에서 이 우위를 다시 넓히려면(모델을 더 정확히 아는 것 외에) 무엇을 할 수 있나? (6.3 강인 제어·6.4 적응 제어를 떠올려 보라.) (7.10.6.1, 6.3·6.4)
  7. 감속비와 설계 선택. 감속비 100:1인 산업로봇 팔과 감속비 5:1인 협동/직접구동 팔이 있다. 각각에 7.10.4(PID+중력보상)와 7.10.5(계산토크법) 중 무엇을 우선 검토하겠나? 그 판단 근거는? (7.10.8)
  8. (손으로) verify/ce44_manipulator.py로 결과를 재현하고, $T$(궤적 시간)를 더 줄이거나(예: 0.2s) $K_p,K_d$를 바꿔 가며 두 제어기의 오차가 어떻게 변하는지 관찰하라. verify/ce44_derive_sympy.py도 실행해 $M,C,G$ 유도·수동성 검산을 직접 확인하라. (검증된 스크립트)

막히면 "계산토크=M,C,G를 정확히 상쇄해 관절별 선형계로(6.2.4의 MIMO판), PID+중력보상=자세의존 관성·속도결합을 무시해 고속에서 성능 저하, 실물은 감속비가 이 격차를 완화"로 돌아가라.