サイトマップ

はじめての現代制御理論 講義12 状態フィードバック制御とオブザーバの併合システムの設計

講義12 状態フィードバック制御とオブザーバの併合システムの設計

合わせて使う場合の注意点
当然だが、「観測」の方を先に収束させないと、「制御」は収束できない

オブザーバを用いた状態フィードバック制御系の構成

講義09の状態フィードバックと、講義11のオブザーバを合わせて使用する場合を考える

 \displaystyle
\begin{aligned}
\dot{x}(t) &= A x(t) + b u(t) \\
\dot{ \hat{x} }(t) &= A \hat{x}(t) + b u(t) + h \lbrace y(t) - c \hat{x}(t) \rbrace \\
u(t) &= - f \hat{x}(t)
\end{aligned}

状態変数線図は下図になる

b
b
A
A
c
c
u(t)
u(t)
+
+
+
+
x'(t)
x'(...
x(t)
x(t)
y(t)
y(t)
b
b
A
A
c
c
+
+
+
+
X'(t)
X'(...
X(t)
X(t)
+
+
-
-
h
h
+
+
f
f
-
-
X(t)
X(t)
Viewer does not support full SVG 1.1

併合システムの特性の解析

オブザーバの時と同様に 推定誤差 e(t) = \hat{x}(t) - x(t) を用いると、 \dot{x}(t) は下記になる

 \displaystyle
\begin{aligned}
\dot{x}(t) &= A x(t) + b u(t) \\
&= A x(t) - b f \hat{x}(t) \\
&= A x(t) - b f e(t) - b f x(t) \\
&= (A - b f) x(t) - b f e(t) 
\end{aligned}

一方、 \dot{e}(t) は下記になる

 \displaystyle
\begin{aligned}
\dot{e}(t) &= \dot{ \hat{x} }(t) - \dot{x}(t) \\
&= A \hat{x}(t) + b u(t) + h \lbrace y(t) - c \hat{x}(t) \rbrace - \lbrace A x(t) + b u(t) \rbrace  \\
&= A \hat{x}(t) - b f \hat{x}(t) + h \lbrace c x(t) - c \hat{x}(t) \rbrace - \lbrace A x(t) - b f \hat{x}(t) \rbrace  \\
&= A \hat{x}(t) - h c \lbrace \hat{x}(t) - x(t) \rbrace - A x(t) \\
&= A \lbrace \hat{x}(t) - x(t) \rbrace - h c \lbrace \hat{x}(t) - x(t) \rbrace \\
&= A e(t) - h c e(t) \\
&= (A - h c) e(t)
\end{aligned}

この2つを合わせると、下記の拡張システムになる

 \displaystyle
\frac{d}{dt}
\begin{bmatrix}
    x(t) \\
    e(t)
\end{bmatrix}
=
\begin{bmatrix}
    A - b f   &  - b f  \\
    0  &  A - h c
\end{bmatrix}
\begin{bmatrix}
    x(t) \\
    e(t)
\end{bmatrix}

固有値は、

 \displaystyle
\begin{vmatrix}
    \lambda I - (A - b f)   &  b f  \\
    0  &  \lambda I - (A - h c)
\end{vmatrix} = 0

となるが、下記の関係が成り立つため、

 \displaystyle
\begin{vmatrix}
    A  &  B  \\
    0  &  D
\end{vmatrix}
=
\begin{vmatrix}
    A  &  0  \\
    C  &  D
\end{vmatrix}
=
\begin{vmatrix} A \end{vmatrix} \begin{vmatrix} D \end{vmatrix}

結局、固有値の計算は、下記になる

 \displaystyle
\begin{vmatrix} \lambda I - (A - b f) \end{vmatrix}
\begin{vmatrix} \lambda I - (A - h c) \end{vmatrix} 
= 0

このことから、 A - bf A - hc固有値を独立して選ぶことができることがわかる
つまり、フィードバックゲイン f と オブザーバゲイン h を独立して設計できる

設計上の注意

オブザーバが収束してから、フィードバックで正しく制御できるため、
オブザーバの極を、フィードバックの極より複素平面の左に配置する必要がある

Pythonによる数値シミュレーション

2x2の以下のシステムでの併合システムを考える

以下のシステムの併合システムを考える

 \displaystyle
\begin{aligned}
\frac{d}{dt}
\begin{bmatrix}
  x_1 (t) \\
  x_2 (t)
\end{bmatrix}
&=
\begin{bmatrix}
  0   &  1  \\
  -6  &  -5
\end{bmatrix}
\begin{bmatrix}
  x_1 (t) \\
  x_2 (t)
\end{bmatrix}
-
\begin{bmatrix}
  0 \\
  1
\end{bmatrix}
u(t) \\

y(t) &=
\begin{bmatrix}
    1   &  0
\end{bmatrix}
\begin{bmatrix}
    x_1 (t) \\
    x_2 (t)
\end{bmatrix} \\

x(0)
&=
\begin{bmatrix}
  1 \\
  1
\end{bmatrix}
\end{aligned}

自由応答の極は  \lbrace-2, -3 \rbrace である

また、オブザーバの初期値は、 \hat{x}(0) = \lbrace 0, 0 \rbrace とする

例12.1 オブザーバが遅い場合

閉ループの極を  \lbrace -5, -6  \rbrace / フィードバックゲインは  \lbrace 24, 6  \rbrace
オブサーバの極を  \lbrace -2, -3 \rbrace / オブザーバゲインは  \lbrace -2, 6 \rbrace ^T

xhat1_arr = [0.0]
xhat2_arr = [0.0]
t = [0.0]
x1_arr = [1.0]
x2_arr = [1.0]
x1_fb_arr = [1.0]
x2_fb_arr = [1.0]

dt = 0.001
for i in range(10000):
    x1_arr += [x1_arr[-1] + (0  * x1_arr[-1] + 1  * x2_arr[-1] - 0.0 * (24 * xhat1_arr[-1] + 6 * xhat2_arr[-1])) * dt]
    x2_arr += [x2_arr[-1] + (-6 * x1_arr[-1] - 5  * x2_arr[-1] - 1.0 * (24 * xhat1_arr[-1] + 6 * xhat2_arr[-1])) * dt]
    t      += [t[-1] + dt]
    y = 1.0 * x1_arr[-1] + 0.0 * x2_arr[-1]

    xhat1_arr += [xhat1_arr[-1] + (0  * xhat1_arr[-1] + 1  * xhat2_arr[-1] - 0.0 * (24 * xhat1_arr[-1] + 6 * xhat2_arr[-1]) + (-2.0) * (y - (1.0 * xhat1_arr[-1] + 0.0 * xhat2_arr[-1]))) * dt]
    xhat2_arr += [xhat2_arr[-1] + (-6 * xhat1_arr[-1] - 5  * xhat2_arr[-1] - 1.0 * (24 * xhat1_arr[-1] + 6 * xhat2_arr[-1]) + ( 6.0) * (y - (1.0 * xhat1_arr[-1] + 0.0 * xhat2_arr[-1]))) * dt]

    x1_fb_arr += [x1_fb_arr[-1] + (0  * x1_fb_arr[-1] + 1  * x2_fb_arr[-1] - 0.0 * (24 * x1_fb_arr[-1] + 6 * x2_fb_arr[-1])) * dt]
    x2_fb_arr += [x2_fb_arr[-1] + (-6 * x1_fb_arr[-1] - 5  * x2_fb_arr[-1] - 1.0 * (24 * x1_fb_arr[-1] + 6 * x2_fb_arr[-1])) * dt]
fig = plt.figure(figsize=(9, 4))
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)

ax1.plot(t, x1_arr, '-',  label='$x_1$')
ax1.plot(t, x2_arr, '--', label='$x_2$')
ax1.plot(t, x1_fb_arr, ':',  label='$x_{sf1}$')
ax1.plot(t, x2_fb_arr, '-.', label='$x_{sf2}$')
ax1.grid()
ax1.legend()
ax1.set_xlim(0, 5)
ax1.set_ylim(-2.0, 1.5)

ax2.plot(t, x1_arr, '-',  label='$x_1$')
ax2.plot(t, x2_arr, '--', label='$x_2$')
ax2.plot(t, xhat1_arr, ':',  label='$\hat{x}_1$')
ax2.plot(t, xhat2_arr, '-.', label='$\hat{x}_2$')
ax2.grid()
ax2.legend()
ax2.set_xlim(0, 5)
ax2.set_ylim(-2.0, 3.0)
fig.tight_layout()

状態ベクトルが観測できる場合と比べて、明らかに遅くなっている

例12.3 オブザーバが速い場合

閉ループの極を  \lbrace -5, -6  \rbrace / フィードバックゲインは  \lbrace 24, 6  \rbrace
オブサーバの極を  \lbrace -8, -9 \rbrace / オブザーバゲインは  \lbrace 12, 6 \rbrace ^T

xhat1_arr = [0.0]
xhat2_arr = [0.0]
t = [0.0]
x1_arr = [1.0]
x2_arr = [1.0]
x1_fb_arr = [1.0]
x2_fb_arr = [1.0]

dt = 0.001
for i in range(10000):
    x1_arr += [x1_arr[-1] + (0  * x1_arr[-1] + 1  * x2_arr[-1] - 0.0 * (24 * xhat1_arr[-1] + 6 * xhat2_arr[-1])) * dt]
    x2_arr += [x2_arr[-1] + (-6 * x1_arr[-1] - 5  * x2_arr[-1] - 1.0 * (24 * xhat1_arr[-1] + 6 * xhat2_arr[-1])) * dt]
    t      += [t[-1] + dt]
    y = 1.0 * x1_arr[-1] + 0.0 * x2_arr[-1]

    xhat1_arr += [xhat1_arr[-1] + (0  * xhat1_arr[-1] + 1  * xhat2_arr[-1] - 0.0 * (24 * xhat1_arr[-1] + 6 * xhat2_arr[-1]) + (12.0) * (y - (1.0 * xhat1_arr[-1] + 0.0 * xhat2_arr[-1]))) * dt]
    xhat2_arr += [xhat2_arr[-1] + (-6 * xhat1_arr[-1] - 5  * xhat2_arr[-1] - 1.0 * (24 * xhat1_arr[-1] + 6 * xhat2_arr[-1]) + ( 6.0) * (y - (1.0 * xhat1_arr[-1] + 0.0 * xhat2_arr[-1]))) * dt]

    x1_fb_arr += [x1_fb_arr[-1] + (0  * x1_fb_arr[-1] + 1  * x2_fb_arr[-1] - 0.0 * (24 * x1_fb_arr[-1] + 6 * x2_fb_arr[-1])) * dt]
    x2_fb_arr += [x2_fb_arr[-1] + (-6 * x1_fb_arr[-1] - 5  * x2_fb_arr[-1] - 1.0 * (24 * x1_fb_arr[-1] + 6 * x2_fb_arr[-1])) * dt]
fig = plt.figure(figsize=(9, 4))
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)

ax1.plot(t, x1_arr, '-',  label='$x_1$')
ax1.plot(t, x2_arr, '--', label='$x_2$')
ax1.plot(t, x1_fb_arr, ':',  label='$x_{sf1}$')
ax1.plot(t, x2_fb_arr, '-.', label='$x_{sf2}$')
ax1.grid()
ax1.legend()
ax1.set_xlim(0, 5)
ax1.set_ylim(-2.0, 1.5)

ax2.plot(t, x1_arr, '-',  label='$x_1$')
ax2.plot(t, x2_arr, '--', label='$x_2$')
ax2.plot(t, xhat1_arr, ':',  label='$\hat{x}_1$')
ax2.plot(t, xhat2_arr, '-.', label='$\hat{x}_2$')
ax2.grid()
ax2.legend()
ax2.set_xlim(0, 5)
ax2.set_ylim(-2.0, 3.0)
fig.tight_layout()

オブザーバの収束が速く、ほぼ理想的な状態フィードバックと同じ性能が確認できる

参考文献

この記事は以下の書籍を参考にしましたが、
私の拙い知識で書いておりますので、誤り等ありましたらご指摘ください