AEGLOSLAB 제어공학 종합 핸드북

제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$를 측정할 수 있으면, 그것이 출력에 닿기 전에 상쇄하는 입력을 더한다.
u_ff u 피드백 (−) r 피드포워드 F Σ 제어기 C Σ 플랜트 G y

핵심: 피드포워드는 폐루프 극을 바꾸지 않는다 — 루프 밖에서 더하므로 안정성·여유(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의 피드포워드와 구조가 다르다:

r′ e = r′ − y u (−) r 전치필터 F(s) Σ 피드백 C(s) 플랜트 G y

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) 제어 — 빠른 안쪽 + 느린 바깥

루프를 겹친다. *바깥(느린) 루프가 안쪽(빠른) 루프의 설정값을 만든다.* 모션 제어의 표준: 위치(바깥) → 속도(중간) → 전류/토크(안쪽).

v_ref u 속도 v (−) 위치 y (−) r Σ 바깥 C_o Σ 안쪽 C_i 안쪽 플랜트 (속도) 바깥 플랜트 (위치) y

왜 좋은가:

  • 내부 외란을 빨리 억제한다: 안쪽 루프가 빠르므로, 안쪽에 들어온 외란(부하 토크 등)을 바깥 루프로 전파되기 전에 제거.
  • 안쪽이 플랜트를 선형화·정규화: 바깥 루프 입장에서는 안쪽 폐루프가 단순한(빠르고 단위이득) 플랜트로 보여 설계가 쉬워진다.
  • 설계 순서: 안쪽부터(충분히 빠르게) → 바깥(안쪽을 순간 응답으로 근사). 대역폭 분리: 안쪽이 바깥보다 ~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 연습·생각해 볼 것

  1. 피드포워드와 안정성. 왜 피드포워드는 폐루프 극(안정성·여유)을 바꾸지 않나? 루프 안의 제어기 $C$와 무엇이 다른가? (7.7.2)
  2. 모델 역. 1차계 $G=K/(\tau s+1)$의 기준 피드포워드 u_ff를 구하라. 모델 $K,\tau$가 실제와 다르면 추종에 무슨 일이? 무엇이 보상하나? (7.7.2·7.7.5)
  3. 2자유도. 단일 PID가 외란에는 좋게 튜닝됐지만 기준 계단에서 오버슈트가 크다. 2자유도(설정점 가중)로 어떻게 외란 응답을 바꾸지 않고 오버슈트만 줄이나? (7.7.3, 2.5.6.4)
  4. 종속 설계 순서. 왜 안쪽 루프를 먼저 설계하나? 안쪽이 바깥보다 얼마나 빨라야 하며, 안 그러면 무슨 일이? (7.7.4)
  5. 종속의 이점. verify/ce41_cascade.py에서 안쪽 속도 루프 게인을 느리게 낮추면 외란 억제 우위가 어떻게 변하나? 왜? 직접 확인하라.
  6. (손으로) verify/ce41_cascade.py를 실행해 종속 vs 단일의 외란 응답을 재현하고, 기준 추종(외란 없이)도 비교해 보라. 피드포워드 항을 더하면 추종이 얼마나 빨라지나? (검증된 스크립트)

막히면 "피드포워드=아는 것은 미리(극 안 바꿈), 2자유도=추종·외란 분리, 종속=빠른 안쪽이 내부 외란을 먼저"로 돌아가라.