똑바른 날개

[MPC책 공부 - 14] 2장 - Linear quadratic MPC예제 본문

제어/mpc

[MPC책 공부 - 14] 2장 - Linear quadratic MPC예제

Upright_wing 2025. 4. 2. 00:59

시스템 정의

$$
x^+ = f(x, u) := x - u
$$

즉, 다음 상태는 현재 상태에서 제어 입력을 뺀 값이다.

비용 함수

stage cost

$$
\ell(x, u) := \frac{1}{2}(x^2 + u^2)
$$

terminal cost

$$
V_f(x) := \frac{1}{2}x^2
$$

total cost(horizon =2 )

$$
V_N(x, u) = \frac{1}{2} \left( x(0)^2 + u(0)^2 + x(1)^2 + u(1)^2 + x(2)^2 \right)
$$

제어 제약 조건:

$$
u(k) \in [-1, 1] \quad \text{for } k = 0, 1
$$

두 가지 풀이 방식

방법 1: 상태와 입력 모두를 최적화 변수로 사용

구분방식 1: 상태와 입력을 모두 최적화 변수로 사용방식 2: 입력만 최적화 변수로 사용

구분 방식 1: 상태와 입력을 모두 최적화 변수로 사용방식 입력만 최적화 변수로 사용
변수 \( x(0),x(1),x(2),u(0),u(1) \) \( u(0),u(1) \)
등식 제약 \( x(0)=x_{\text{init}},\ x(1)=x(0)-u(0),\ x(2)=x(1)-u(1) \) 없음 (상태를 직접 식에 대입함)
목적 함수 위와 동일 상태를 없애고 \( x_{\text{init}} \)\( u \)만으로 표현

 

목적함수

$$
\frac{1}{2} \left( x(0)^2 + u(0)^2 + x(1)^2 + u(1)^2 + x(2)^2 \right)
$$

제약 조건

$$
\begin{aligned}
x(0) &= x \quad \text{(initial condition)} \\
x(1) &= x(0) - u(0) \quad \text{(system equation)} \\
x(2) &= x(1) - u(1) \\
u(0), u(1) &\in [-1, 1]
\end{aligned}
$$

이 방식은 상태와 입력을 모두 결정 변수로 다루고, 시스템 방정식은 equality constraint로 처리된다.

 

방법 2: 입력만 최적화 변수로 사용

이 방식은 상태들을 명시적으로 변수로 두지 않고, 시스템 방정식을 통해 상태를 계산한다.

상태는 다음과 같이 유도된다

$$
\begin{aligned}
x(1) &= x - u(0) \\
x(2) &= x - u(0) - u(1)
\end{aligned}
$$

목적 함수는 다음과 같다.

$$ \begin{aligned} V_N(x, u) &= \frac{1}{2} \left[ x^2 + u(0)^2 + (x - u(0))^2 + u(1)^2 + (x - u(0) - u(1))^2 \right] \\ &= \frac{3}{2}x^2 - 2x \cdot [1 \quad 1] u + \frac{1}{2} u^T H u \end{aligned} $$

$$
H = \begin{bmatrix}
3 & 1 \\
1 & 2
\end{bmatrix}
$$

제약 없는 최적 입력 계산

목적 함수를 \(u = [u(0), u(1)]^\top\)에 대해 미분하고 0으로 두면 다음과 같은 최적 입력이 나온다.

$$ u^\star(x) = \begin{bmatrix} \frac{3}{5}x \\ \frac{1}{5}x \end{bmatrix} $$

제약 조건

입력 제약 \(|u(k)| \le 1\)을 적용하면, 각각의 제어 입력을 [-1, 1] 범위로 잘라야 한다.

$$ \kappa_N(x) = \operatorname{sat}\left(\frac{3}{5}x\right) $$

$$ \operatorname{sat}(z) = \begin{cases} 1, & z > 1 \\ z, & -1 \le z \le 1 \\ -1, & z < -1 \end{cases} $$

최종적으로 제어 루프는 다음과 같이 된다.

$$ x^+ = x - \kappa_N(x) $$

  • saturation 함수

$$ \text{sat}(z) = \begin{cases} 1 & \text{if } z > 1 \\ z & \text{if } -1 \le z \le 1 \\ -1 & \text{if } z < -1 \end{cases} $$

 

결과

예제) 초기 상태 x = 10의 결과

1. \(u(0) = \operatorname{sat}(3 \cdot 10 / 5) = \operatorname{sat}(6) = 1\)

2. \(x(1) = 10 - 1 = 9\)

3. \(u(1) = \operatorname{sat}(3 \cdot 9 / 5) = \operatorname{sat}(5.4) = 1\)

4. \(x(2) = 9 - 1 = 8\)

총 비용:

$$ V_N(10) = \frac{1}{2}(10^2 + 1^2 + 9^2 + 1^2 + 8^2) = 124 $$

또한 해당 시스템은 시간에 따라 시스템의 변화가 생기는 구조가 아니다.즉, Time-invariant하다.

다시 정리해보면,

$$ x^+ = x + \kappa_N(x), \quad \kappa_N(x) = -\text{sat}\left(\frac{3x}{5}\right) $$

Python 코드로 구현

import numpy as np
import matplotlib.pyplot as plt

def sat(z):               
    return np.clip(z, -1, 1)

def kappa_N(x):           
    return sat(3*x/5)

# 초기 상태
x0 = 10
horizon = 14

x = x0
x_traj = [x]
u_traj = []

# 시뮬레이션 (horizon 길이만큼)
for _ in range(horizon):
    u = -kappa_N(x)
    u_traj.append(u)
    x = x + u
    x_traj.append(x)

k = np.arange(horizon + 1)

fig, axs = plt.subplots(1, 2, figsize=(14, 5))

# (a) Optimal control law
xs = np.linspace(-10, 10, 401)
axs[0].plot(xs, kappa_N(xs))
axs[0].set_title('Optimal Control Law')
axs[0].set_xlabel('x')
axs[0].set_ylabel(r'$\kappa_N(x)$')
axs[0].axhline(0, color='black', lw=0.5, ls='--')
axs[0].axvline(0, color='black', lw=0.5, ls='--')
axs[0].axhline(1, color='red', lw=0.5, ls='--')
axs[0].axhline(-1, color='red', lw=0.5, ls='--')
axs[0].set_xlim(-10, 10)
axs[0].set_ylim(-2, 2)
axs[0].set_xticks(np.arange(-10, 11, 2))
axs[0].set_yticks(np.arange(-2, 3, 1))
axs[0].grid(True)

# (b) State and input trajectories
axs[1].plot(k, x_traj, marker='o', label=r'$x(k)$')
axs[1].plot(k[:-1], u_traj, marker='s', label=r'$u(k)$')
axs[1].set_title(r'State and Control Input Trajectories ($x_0 = 10$)')
axs[1].set_xlabel('Time step k')
axs[1].grid(True)
axs[1].legend()

plt.tight_layout()
plt.show()