← 강의 목록

Lecture 11. 모델 예측 제어 (MPC)

미래를 시뮬레이션해 보고, 가장 좋은 행동을 골라 실행한다. 현대 제어공학의 표준 언어이자, SAIL 연구실의 핵심 연구 주제.

목차

  1. 왜 MPC인가 — 최적화 기반 제어
  2. 고전 제어 vs MPC
  3. 제약이 MPC를 필요하게 만드는 이유
  4. 수학적 정식화 (OCP)
  5. 수신지평선 전략 — Plan & Do
  6. 설계 파라미터: 샘플시간·호라이즌·가중치
  7. 인터랙티브: 1D MPC 위치 추종
  8. CasADi 코드 예제
  9. 부드러운 경로: Cubic Spline
  10. iLQR — 비선형의 빠른 해법
  11. 배경: LQR (무한 호라이즌)
  12. 응용 사례 (ms ~ days)
  13. 더 깊이 공부하기

1. 왜 MPC인가 — 최적화 기반 제어

경주용 자동차가 서킷을 주행하는 장면을 떠올려 봅시다. 목표는 랩 타임 최소화이고, 지켜야 할 제약은 여러 가지입니다:

사람 운전자는 어떻게 할까요? 앞을 내다보고, 도로 상태·다가올 코너·차의 성능을 고려해 향후 몇 초 동안의 경로와 가·감속을 동시에 계획합니다. 그리고 그 계획대로 움직이다가, 코너를 도는 순간 새로운 정보(앞 차, 노면 상태)를 보고 다시 계획합니다.

MPC는 이 과정을 수학으로 적은 것입니다:

MPC 한 줄 요약 — "모델을 이용해 미래 $N$ 스텝의 최적 입력 시퀀스를 구하고, 첫 입력만 실제로 적용한 뒤, 다음 샘플 시점에 새로운 측정값으로 전 과정을 반복한다."

PID는 단순하고 강력하지만 제약(constraint)을 직접 다루지 못합니다. 모터의 최대 출력, 안전한 속도, 충돌 회피 같은 제약을 고려해야 한다면 MPC가 정답입니다.

2. 고전 제어 vs MPC

고전 제어 (PID · 주파수 영역)MPC (시간 영역 · 실시간 최적화)
설계 관점제어기 $C(s)$를 한 번 설계매 샘플 시점에 $u(t)$를 다시 계산
주로 다루는 문제외란 억제, 잡음 민감도, 모델 불확실성입력 제약(포화), 상태 제약(안전)
미래 정보사용 안 함참조 궤적·장애물 예측을 직접 반영
다중 입출력번거로움 (decoupling 필요)자연스럽게 벡터로 처리
계산 비용사실상 0매 스텝 QP/NLP 풀이 (수 ms ~ 수십 ms)

핵심 메시지 (Jones/Borrelli/Morari): 고전 설계는 "제어기를 설계하는" 문제인 반면, MPC는 "매 순간 최적 입력을 직접 선택하는" 문제입니다. 계산 파워가 충분해진 2000년대 이후로 MPC가 산업 현장의 표준이 되었습니다.

3. 제약이 MPC를 필요하게 만드는 이유

모든 실제 시스템에는 제약이 있습니다:

여기서 중요한 관찰: 최적 작동점은 제약 경계 근처에 있습니다. 예를 들어 화학 플랜트의 수익은 온도가 안전 상한에 가까울수록 좋고, 레이싱 카의 랩타임은 마찰 한계에 가까울수록 짧아집니다.

고전 제어의 해법은 "세트포인트를 제약에서 충분히 멀리 떨어뜨려" 제약을 건드리지 않는 것입니다 — 이는 명백히 차선입니다. MPC는 제약을 설계 안에 직접 녹여 최적점에서 운전할 수 있습니다.

제약 고전 제어: 세트포인트를 제약에서 멀리 제약 MPC: 제약 바로 아래에서 최적 운전
그림. 고전 설계는 제약에서 거리를 두어 안전한 대신 suboptimal. MPC는 제약을 최적화에 직접 포함해 최적점에서 작동.

4. 수학적 정식화 (OCP)

매 샘플 시점 $t$마다 MPC가 푸는 문제는 다음 유한 호라이즌 최적 제어 문제(FH-OCP)입니다:

$$ U_t^*(x(t)) \;=\; \arg\min_{U_t}\; \underbrace{p(x_{t+N})}_{\text{종단 비용}} \;+\; \sum_{k=0}^{N-1} \underbrace{q(x_{t+k},\, u_{t+k})}_{\text{단계 비용}} $$ $$ \text{s.t.}\quad x_t = x(t) \quad\text{(현재 상태 측정)} $$ $$ x_{t+k+1} = f(x_{t+k}, u_{t+k}) \quad \text{(시스템 모델)} $$ $$ x_{t+k} \in \mathcal{X},\;\; u_{t+k} \in \mathcal{U} \quad \text{(상태·입력 제약)} $$ $$ x_{t+N} \in \mathcal{X}_f \quad \text{(종단 제약)} $$

최적화 변수는 $U_t = \{u_t, u_{t+1}, \dots, u_{t+N-1}\}$, 즉 앞으로 $N$ 스텝의 입력 시퀀스입니다.

문제는 세 가지 요소로 정의됩니다:

4.1 이차 비용 LMPC — 가장 흔한 형태

모델이 선형이고 비용이 이차식이면 MPC는 볼록 이차계획법(QP)이 됩니다. 매 스텝 QP 한 번이면 되므로 수 ms 안에 풀립니다 — 이 경우를 Linear MPC (LMPC)라고 부릅니다.

$$ \min\; x_N^\top P x_N + \sum_{k=0}^{N-1} \bigl(x_k^\top Q x_k + u_k^\top R u_k\bigr) $$

가중치 행렬의 역할:

5. 수신지평선 전략 — Plan & Do

MPC는 매 샘플마다 다음을 반복합니다:

  1. 측정/추정 — 현재 상태 $x(t)$를 (칼만 필터 등으로) 알아낸다.
  2. 계획 (Plan) — OCP를 풀어 최적 입력 시퀀스 $U_t^* = \{u_t^*, \dots, u_{t+N-1}^*\}$를 얻는다.
  3. 실행 (Do)오직 첫 번째 입력 $u_t^*$만 실제 시스템에 보낸다.
  4. 이동 — 다음 샘플에서 호라이즌을 한 칸 밀고 1단계부터 다시.

나머지 $N-1$개 입력을 버리는 것이 아깝게 느껴지지만, 그 덕분에 피드백이 생깁니다. 예기치 못한 외란이 들어와도 다음 스텝에서 새 측정값으로 재계획되므로, open-loop 최적화가 closed-loop 피드백 제어로 승격됩니다.

t t+1 t+2 t에서의 계획 (N=4) t+1에서의 재계획 (외란 반영) 볼드 막대 = 실제 실행된 첫 입력
그림. Receding horizon의 핵심: 매 스텝 $N$개의 계획을 만들지만 첫 입력만 실행. 이 "버림"이 피드백을 만듭니다.

6. 설계 파라미터: 샘플시간·호라이즌·가중치

MPC를 실전에 적용할 때 엔지니어가 정해야 할 세 가지:

제어 호라이즌 $N_c \le N$을 따로 둬서 $k \ge N_c$ 이후에는 $u_k = u_{k-1}$로 묶으면(input blocking) 변수 수를 더 줄일 수 있습니다.

7. 인터랙티브: 1D MPC 위치 추종

2. 수신지평선 (Receding Horizon)

지금 N 스텝 예측 후 첫 행동만 실행

3. 최적화 문제

$$ \min_{u_0,\dots,u_{N-1}} \sum_{i=0}^{N-1} \|x_i - x_\text{ref}\|_Q^2 + \|u_i\|_R^2 $$ $$ \text{s.t.}\;\; x_{i+1} = A x_i + B u_i, \quad u_\text{min} \le u_i \le u_\text{max} $$

🎮 인터랙티브: 1D MPC 위치 추종

마우스로 목표 위치(빨강 점선)를 끌고 다녀보세요. MPC가 가속도 한계 안에서 최적으로 따라갑니다.

호라이즌 $N$이 클수록 멀리 내다보지만 계산량이 늘어납니다. $R$이 크면 부드럽게, 작으면 공격적으로 움직입니다.

8. 코드 예제 (CasADi)

import casadi as ca
import numpy as np

N, dt = 20, 0.1
x = ca.SX.sym('x', 2)            # [pos, vel]
u = ca.SX.sym('u')               # accel
f = ca.Function('f', [x,u], [ca.vertcat(x[0]+dt*x[1], x[1]+dt*u)])

opti = ca.Opti()
X = opti.variable(2, N+1)
U = opti.variable(1, N)
x0 = opti.parameter(2); ref = opti.parameter()

J = 0
for k in range(N):
    J += 10*(X[0,k]-ref)**2 + 0.3*U[0,k]**2
    opti.subject_to(X[:,k+1] == f(X[:,k], U[0,k]))
opti.subject_to(X[:,0] == x0)
opti.subject_to(opti.bounded(-3, U, 3))

opti.minimize(J)
opti.solver('ipopt')
opti.set_value(x0, [0,0]); opti.set_value(ref, 5)
sol = opti.solve()
u0 = sol.value(U[0,0])           # 첫 명령만 실제로 적용

9. 부드러운 경로 만들기 — Cubic Spline

MPC에 넣을 참조 경로는 보통 몇 개의 웨이포인트(waypoint)로만 주어집니다. 그 사이를 부드럽게 잇는 가장 흔한 방법은 3차 스플라인입니다. PythonRobotics의 CubicSpline 모듈이 표준 구현입니다.

$$ S_i(x) = a_i + b_i(x - x_i) + c_i(x - x_i)^2 + d_i(x - x_i)^3 $$

각 구간이 3차 다항식이고, 이웃 구간끼리 0차·1차·2차 도함수가 모두 연속입니다. 그 결과 사람이 그린 듯한 부드러운 곡선이 나옵니다.

🎮 인터랙티브: 웨이포인트 → 부드러운 경로

웨이포인트(빨강)를 드래그해 옮기거나 클릭으로 추가하세요. 3차 스플라인이 즉시 부드러운 경로(파랑)를 만듭니다.

왼쪽 클릭: 점 추가 · 오른쪽 클릭: 점 제거 · 드래그: 이동

10. iLQR — 큰 비선형 문제의 빠른 해법

일반 MPC는 매 스텝 비선형 최적화를 풀어야 해 느릴 수 있습니다. iterative LQR (iLQR)은 명목 궤적 주변을 LQR로 선형화한 뒤 반복적으로 개선합니다. PythonRobotics의 ModelPredictiveTrajectoryGenerator가 이런 방식의 한 예입니다.

비선형 차량 모델에서도 수십 ms 안에 수렴해, 자율주행 차량과 드론에 널리 쓰입니다.

11. 배경: LQR (무한 호라이즌, 제약 없음)

MPC의 "조상"은 LQR입니다. 선형 시스템 $x_{k+1} = Ax_k + Bu_k$에 이차 비용 $\sum x^\top Q x + u^\top R u$를 두고 무한 호라이즌으로 풀면, 최적 제어는 단순한 상태 피드백 $u_k = -Kx_k$가 됩니다. 여기서 $K$는 이산 리카티 방정식의 해입니다:

$$ P = A^\top P A - A^\top P B (R + B^\top P B)^{-1} B^\top P A + Q, \qquad K = (R + B^\top P B)^{-1} B^\top P A $$

제약이 없고 모델이 선형이면 LQR이 MPC와 같은 답을 줍니다. 즉 MPC는 "제약과 비선형을 다룰 수 있는 LQR"이라고 볼 수 있습니다.

12. 응용 사례 — ms부터 days까지

MPC는 다양한 시간 스케일의 시스템에 적용됩니다. Jones/Borrelli/Morari의 ETH 강의노트에 나오는 대표 예시들입니다.

시간 스케일응용특징
msBall on Plate, 전력 전자, 드론 자세샘플시간 10 ms 이하, 선형 MPC + QP
sub-secondETH 쿼드콥터 곡예 비행, dNaNo 미니 레이싱카비선형 MPC, 하드웨어 실시간 제약
초 (s)자동차 트랙션·ACC·차선 유지, 로봇 조작저장된 맵·예측 궤적을 활용
분~시건물 난방·냉방(energy-efficient building), 화학 플랜트날씨 예보·에너지 가격을 참조 입력으로
일~주공급망 계획, 전력 계통 디스패치, 인력 배치경제 MPC, 확률적 수요 예측

SAIL 연구실이 직접 다루는 범위는 주로 sub-second ~ 초 단위입니다 — 자율수상선(ASV), 자율 차량, 멀티 로봇 시스템에서 안전 보장이 필요한 MPC.

13. 더 깊이 공부하기