제7부 실전: ROS2 Humble 프로젝트
7.7 제어 구조 — 피드포워드·2자유도·종속
제7부 실전 · 보강 장(v1 이후 추가)의 첫 장. 제2부~제4부의 설계 위에 서는 내용이라, 그 설계 장들 다음에 바로 읽어도 좋다. 단일 피드백 루프를 넘어선 제어 구조를 다룬다. 피드포워드(오차가 쌓이기 전 대응)·2자유도(추종과 외란을 따로 형성하기)·종속(cascade)(빠른 안쪽 + 느린 바깥) — 실무 모션·공정 제어의 대표적 구조다.
✅ 검증됨: 종속 제어의 내부 외란 억제 우위를
ros:humble컨테이너에서 실행해 검증(verify/ce41_cascade.py) — 단일 루프 대비 위치 이탈 1.9배 감소.
이 장을 마치면 피드포워드가 왜 안정성에 영향을 주지 않으며 추종을 개선하는지, 2자유도가 추종·외란을 어떻게 분리하는지, 종속 구조가 왜 내부 외란을 빨리 억제하는지 설명해야 한다.
7.7.1 단일 루프를 넘어 — 제어 구조
지금까지(2.5·4.3·4.5)는 대개 하나의 피드백 루프였다: 오차를 보고 보정. 하지만 피드백은 오차가 생긴 뒤에야 움직인다(사후 대응). 더 잘하려면 구조를 바꾼다:
- 피드포워드: 아는 정보(기준·측정된 외란)로 미리 대응 → 오차가 쌓이기 전에.
- 2자유도: 추종(기준 따라가기)과 외란 억제를 따로 설계.
- 종속: 루프를 겹쳐 빠른 안쪽이 외란·비선형을 먼저 처리.
이들은 피드백을 대체하지 않고 보강한다. 피드백은 여전히 모델 오차·미지 외란을 보상하는 최종 수단이다.
7.7.2 피드포워드 — 오차가 쌓이기 전에
피드백이 "보고 고친다"면 피드포워드는 "알고 미리 준다".
- 기준 피드포워드: 원하는 출력 $r$을 내려면 어떤 입력이 필요한지 모델로 계산해 바로 준다 — 이상적으로는 모델 역(inverse)
u_ff = G⁻¹·r. 모델이 정확하면 완벽 추종. 예: 1차계 $G=K/(\tau s+1)$이면u_ff = (τṙ + r)/K. - 외란 피드포워드: 외란 $d$를 측정할 수 있으면, 그것이 출력에 닿기 전에 상쇄하는 입력을 더한다.
핵심: 피드포워드는 폐루프 극을 바꾸지 않는다 — 루프 밖에서 더하므로 안정성·여유(2.4)에 영향이 없다. 그래서 안전하게 추종·외란 억제를 개선한다. 피드백은 모델 오차를 보상하고, 피드포워드는 응답을 앞당긴다 — 둘의 분업.
7.7.3 2자유도(2-DOF) 제어 — 추종과 외란을 따로
단일 루프 PID는 하나의 $C$로 추종과 외란 억제를 동시에 책임진다 → 타협이 생긴다(빠른 추종 튜닝이 외란에는 과할 수 있음). 2자유도는 둘을 분리한다:
- 피드백 $C$: 외란 억제·강인성 담당(감도 $S$ 형성, 1.2.6).
- 전치필터(prefilter)·피드포워드 $F$: 기준에 대한 응답 모양만 담당(오버슈트·속도).
2.5.6.4의 설정점 가중(P·D항에 $b,c$ 가중)이 가장 단순한 2자유도다 — 외란 응답은 그대로 두고 추종 오버슈트만 줄인다. 더 일반적으로는 기준 앞에 전치필터를 둔다 — 이때의 결선은 7.7.2의 피드포워드와 구조가 다르다:
7.7.2의 피드포워드는 합산점이 둘이었다 — 오차 합산점($r$과 $y$를 비교)과 $u$ 합산점(그 오차의 제어기 출력에 u_ff를 더함). 여기 2자유도는 합산점이 하나뿐이고, $F(s)$가 기준 경로 위에서 합산점 앞에만 위치한다 — $y$는 변경하지 않고 $r$만 성형해 $r'$을 만들고, 그 $r'$과 $y$의 차이(오차 $e$)를 $C(s)$ 하나가 받아 $u$를 낸다. 그래서 $C(s)$는 오차만 보고 외란 억제·강인성에 맞게 얼마든지 공격적으로 튜닝해도 되고, $F(s)$는 그 오차의 기준 쪽 성분만 성형해 오버슈트·응답 속도를 조절한다 — "$C$는 얼마나 강하게 보정하는가(외란), $F$는 무엇을 목표로 구동하는가(추종 모양)"의 분업이다.
효과: "외란에는 공격적, 기준에는 부드럽게"를 동시에. 단일 루프의 타협을 푼다.
7.7.4 종속(cascade) 제어 — 빠른 안쪽 + 느린 바깥
루프를 겹친다. *바깥(느린) 루프가 안쪽(빠른) 루프의 설정값을 만든다.* 모션 제어의 표준: 위치(바깥) → 속도(중간) → 전류/토크(안쪽).
왜 좋은가:
- 내부 외란을 빨리 억제한다: 안쪽 루프가 빠르므로, 안쪽에 들어온 외란(부하 토크 등)을 바깥 루프로 전파되기 전에 제거.
- 안쪽이 플랜트를 선형화·정규화: 바깥 루프 입장에서는 안쪽 폐루프가 단순한(빠르고 단위이득) 플랜트로 보여 설계가 쉬워진다.
- 설계 순서: 안쪽부터(충분히 빠르게) → 바깥(안쪽을 순간 응답으로 근사). 대역폭 분리: 안쪽이 바깥보다 ~3~5배 빨라야(안 그러면 두 루프가 간섭).
구현은 게인 두 세트를 분리하는 것뿐이다 — 바깥은 위치 오차를 속도 설정값으로, 안쪽은 그 속도 오차를 받아 실제 명령 $u$를 낸다(verify/ce41_cascade.py에서 발췌):
# 종속(cascade): 바깥 위치 P → 안쪽 속도 PI (안쪽이 훨씬 빠르게 튜닝됨)
Kpp = 8.0 # 위치 P (바깥, 느림)
Kpv, Kiv = 4.0, 30.0 # 속도 PI (안쪽, 빠름)
vref = Kpp * (xr - x) # 바깥 루프: 위치 오차 → 속도 설정값
ev = vref - v
I += Kiv * ev * dt
u = Kpv * ev + I # 안쪽 루프: 속도 오차 → 명령 u
# 단일 루프: 위치 PID 하나가 전부 책임
Kp1, Ki1, Kd1 = 20.0, 40.0, 8.0
e = xr - x
I += Ki1 * e * dt
u = Kp1*e + I - Kd1*v # 미분항은 속도 측정으로 대체
두 코드 모두 같은 플랜트($\dot{v}=-a\cdot v+b\cdot(u+d)$, $d$=내부 외란)에 $t=1s$에서 외란 계단을 주입해 위치 이탈을 비교한다.
검증 결과 (내부 외란 계단에 대한 위치 이탈):
단일 루프 외란 후 최대 위치 이탈 = 0.0306
종속 루프 외란 후 최대 위치 이탈 = 0.0158 → 1.9배 적음
→ CE41_CASCADE_PASS
안쪽 속도 루프가 외란을 먼저 받아쳐, 같은 외란이 위치에 미치는 영향을 절반으로 줄였다. 7.2.5·7.4.5(밸런싱 로봇)의 종속 구조가 이 원리다.
7.7.5 정직 — 모델·센서·한계
- 피드포워드는 모델에 의존: 모델 역 $G^{-1}$이 부정확하면 피드포워드도 어긋난다(피드백이 보상하지만 완벽하지 않음). 비최소위상·불안정 시스템은 정확히 역을 구하지 못한다(1.2.2.3·1.2.2.9) — 근사·필터된 역을 쓴다.
숫자로: 7.7.2의 1차계 $G=K/(\tau s+1)$, u_ff=(τṙ+r)/K를 예로 들자. 실제 플랜트 $K=2.0, \tau=0.5$, 기준은 램프 $r(t)=v\cdot t$ ($v=1$, 즉 t초에 목표가 t만큼 전진). 오직 피드포워드만으로(피드백 없이) 구동했을 때, 모델 추정치 $\hat{K},\hat{\tau}$가 실제와 $\pm20\%$ 어긋나면 정상상태 추종 오차 e=r−y는 다음처럼 커진다(오일러 적분으로 검증):
- $\hat{K}$만 $+20\%$ ($\hat{K}=2.4$) — $e(10\,\mathrm{s}) = 1.667$ → 계속 커짐(기울기 0.167/s, 무한정 발산)
- $\hat{K}$만 $-20\%$ ($\hat{K}=1.6$) — $e(10\,\mathrm{s}) = -2.500$ → 계속 커짐(기울기 −0.250/s, 무한정 발산)
- $\hat{\tau}$만 $+20\%$ ($\hat{\tau}=0.6$) — $e(10\,\mathrm{s}) = -0.100$ → 더 안 커짐(상수 오프셋)
- $\hat{\tau}$만 $-20\%$ ($\hat{\tau}=0.4$) — $e(10\,\mathrm{s}) = +0.100$ → 더 안 커짐(상수 오프셋)
해석식도 일치한다: e_ss(t) = v·t·(1−K/K̂) − (Kv/K̂)·(τ̂−τ). $\hat{K}$ 오차는 시간에 비례해 무한정 커지는 오차(램프를 따라가는 기울기 자체가 틀리므로)를 낳고, $\hat{\tau}$ 오차는 유계인 상수 오프셋(과도응답의 타이밍만 어긋나므로)만 낳는다 — 같은 $\pm20\%$라도 이득 오차가 훨씬 치명적이다. 실전에서 피드백이 이 오차를 보상하지만(적분기가 있다면 정상상태 오차를 0으로), 피드포워드 자체는 모델이 틀리면 이렇게 어긋난다는 것을 숫자로 보여준다. (검증: docker run ce-verify, 오일러 적분 dt=0.0005, 해석식과 소수점 4자리까지 일치)
- *외란 피드포워드는 외란을 측정해야* 한다 — 못 재는 외란에는 무용(그때는 피드백·외란관측기).
- 종속은 안쪽 센서가 필요: 속도/전류 측정이 있어야 한다. 대역폭 분리가 안 되면 두 루프가 간섭해 오히려 악화된다.
- 여전히 피드백이 최종 보상 수단: 모든 구조는 피드백 위에 더한다 — 피드포워드·종속이 미지 외란·모델 오차를 모두 제거하지는 못한다.
7.7.6 정리 — 그리고
- 피드백은 사후 대응 — 피드포워드(아는 정보로 미리)·2자유도(추종/외란 분리)·종속(빠른 안쪽)으로 보강한다(7.7.1).
- 피드포워드는 폐루프 극을 안 바꿔 안전하게 추종·외란 억제를 개선(7.7.2). 2자유도는 단일 루프의 추종-외란 타협을 푼다(7.7.3, 설정점 가중이 그 예).
- 종속은 빠른 안쪽 루프로 내부 외란을 빨리 억제하고(검증: 1.9배) 플랜트를 정규화한다 — 안쪽부터·대역폭 분리(7.7.4).
- 모두 모델·센서에 의존하며 피드백이 최종 보상 수단(7.7.5).
이 구조들은 제7부 실전(7.2 종속 속도-위치, 7.4 밸런싱)에서 이미 쓰였다. 단일 루프로 부족할 때 구조를 바꾸는 것이 다음 카드다.
7.7.7 연습·생각해 볼 것
- 피드포워드와 안정성. 왜 피드포워드는 폐루프 극(안정성·여유)을 바꾸지 않나? 루프 안의 제어기 $C$와 무엇이 다른가? (7.7.2)
- 모델 역. 1차계 $G=K/(\tau s+1)$의 기준 피드포워드
u_ff를 구하라. 모델 $K,\tau$가 실제와 다르면 추종에 무슨 일이? 무엇이 보상하나? (7.7.2·7.7.5) - 2자유도. 단일 PID가 외란에는 좋게 튜닝됐지만 기준 계단에서 오버슈트가 크다. 2자유도(설정점 가중)로 어떻게 외란 응답을 바꾸지 않고 오버슈트만 줄이나? (7.7.3, 2.5.6.4)
- 종속 설계 순서. 왜 안쪽 루프를 먼저 설계하나? 안쪽이 바깥보다 얼마나 빨라야 하며, 안 그러면 무슨 일이? (7.7.4)
- 종속의 이점.
verify/ce41_cascade.py에서 안쪽 속도 루프 게인을 느리게 낮추면 외란 억제 우위가 어떻게 변하나? 왜? 직접 확인하라. - (손으로)
verify/ce41_cascade.py를 실행해 종속 vs 단일의 외란 응답을 재현하고, 기준 추종(외란 없이)도 비교해 보라. 피드포워드 항을 더하면 추종이 얼마나 빨라지나? (검증된 스크립트)
막히면 "피드포워드=아는 것은 미리(극 안 바꿈), 2자유도=추종·외란 분리, 종속=빠른 안쪽이 내부 외란을 먼저"로 돌아가라.