1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

H∞制御理論_理論的解説5:ガンマイタレーション

Last updated at Posted at 2021-01-11

概要

ついに,終着駅に向かってまいりました.
長かったですが,まだまださらにかかります・・・

H∞制御とは

いろいろなところで,語られているので軽く

min \|T_{zw}\|_{\infty} 

を達成する,制御器$K$を設計し,制御に用いるということである.

計算方法:ガンマイタレーション

ガンマイタレーションという方法で計算する.LMIとかはまだ勉強していないが,有界実補題でLMIに変換すれば,可能だと思われる

次の定理を基本とした方法である.


 \|T_{zw}\|_{\infty} <\gamma

を満たす制御器が存在すること
⇔次の3つが成立
(1) $H_{\infty} \in dom(Ric)$かつ,解$X_{\infty}$が正定

H_{\infty}=\left(
    \begin{array}{ccc}
     A &\gamma^{-2}B_1B_1^*-B_2B_2^*\\
-C_1^*C_1&-A^*\\
    \end{array}
  \right)

$\gamma = \infty$ならば,(1,2)成分が負定になり,可制御・可観測ならば,$dom(Ric)$になる(証明は余裕があるときに).

(2) $J_{\infty} \in dom(Ric)$かつ,解$Y_{\infty}$が正定

J_{\infty}=\left(
    \begin{array}{ccc}
     A^* & \gamma^{-2}C_1^*C_1-C_2^*C_2\\
-B_1B_1^*&-A\\
    \end{array}
  \right)

(3)$\rho(A)$をAの最大ユークリッドノルムの固有値を示すとする.

\rho(A) = max_{1<i<n}\|\lambda_i\|

と定義する.この時,次を満たす.

\rho(X_{\infty}Y_{\infty} ) < \gamma^2

さらに,これらの条件が成立するとき,制御器の一つは

K_{sub}=\left(
    \begin{array}{c|c}
      \hat{A}_{\infty}&-Z_{\infty} L_{\infty}\\ \hline
      F_{\infty}&0\\
    \end{array}
  \right)\\
\hat{A}_{\infty} = A+ \gamma^{-2}B_1 B_1^* X_{\infty} +B_2F_{\infty} + Z_{\infty}L_{\infty}C_2\\
F_{\infty} = -B_2^*X_{\infty}\\
L_{\infty} = -Y_{\infty}C_2^*\\
Z_{\infty} = (I-\gamma^{-2}Y_{\infty}X_{\infty})^{-1}\\

となる.


この定理を用いて,

min \|T_{zw}\|_{\infty} 

を達成するには,

(1) 初期値$\gamma_1$を与え,3条件を満たすか確認する
(2) 満たす場合$\gamma_1$より小さい値で,3条件を満たすか確認する
(3) 満たさない場合,$\gamma_1$より大きい値で3条件を満たすか確認する

二分探索等の探索アルゴリズムを使用し,3条件を満たす,できるだけ小さい$\gamma$を計算する.
最後に,その時の$K_{sub}$を計算すれば,計算終了となる.ガンマ値を色々変えて繰り返すので,ガンマイタレーションと呼ばれる.

以降では,定理の証明をする.補題3つまず,証明し,定理を示す

ちなみに,すでに

\gamma > \| G \|_{\infty}

であると事と

R=\gamma ^2 I -D^*D\\
F=R^{-1}(B^*X+D^*C)\\
S=-C^*D\\
P=-C^*C\\

としたときのハミルトン行列H

H=
\left(
    \begin{array}{ccc}
      A+BR^{-1}S^*&-BR^{-1}B^*\\
-(P-SR^{-1}S^*)&-( A+BR^{-1}S^*)^*\\
    \end{array}
  \right)

が$H \in dom(Ric)$であることが

同値であることは示している.

Pythonで実装

証明は後にして,Scilabで設計したコントローラと,Pythonで自作した,ガンマイタレーションの結果の比較をしようと思います.


"""
二分探索で ガンマイタレーションを行い, 準最適制御器 を設計する.
"""


import numpy as np		#	Numpyライブラリ
import copy


def check(gamma,A,B1,B2,C1,C2):
    """
    ハミルトン行列の生成
    """
    
    H=copy.deepcopy(A)
    hoge = np.dot(B1,B1.conj().T) / (gamma**2) - np.dot(B2,B2.conj().T) 
    H = np.append(H,hoge,axis = 1)
    hoge2 =  -1 * np.dot(C1.conj().T,C1) 
    hoge2 = np.append(hoge2,-1*A.conj().T ,axis =1 )
    H = np.append(H,hoge2,axis = 0)
    
    J=copy.deepcopy(A.conj().T)
    hoge = np.dot(C1.conj().T,C1) / (gamma**2) - np.dot(C2.conj().T,C2) 
    J = np.append(J,hoge,axis = 1)
    hoge2 =  -1 * np.dot(B1,B1.conj().T) 
    hoge2 = np.append(hoge2,-1*A ,axis =1 )
    J = np.append(J,hoge2,axis = 0)
    
    
    """
    H
    
    ハミルトン行列に固有値0を持たない,ハミルトン行列の解を求める,
    """
    H=H.astype(np.float64)
    Hw,Hv = np.linalg.eig(H) 
    
    for i in range(len(Hw)):        
        if Hw[i].real == 0:
            print("H have pole 0")            
            return 0,0,0
            
    v_num = 0 
    for i in range(len(Hw)): 
        if Hw[i].real < 0:
            if v_num == 0:
                V = Hv[:,i].reshape(H.shape[0],1)
                v_num = v_num+1
            else:
                V = np.append(V,Hv[:,i].reshape(H.shape[0],1),axis = 1)
                v_num = v_num+1
    
    n=A.shape[0]
    X1_H = V[0:n,0:n]
    X2_H = V[2:n+2,0:n]
    
    if np.linalg.det(X1_H) == 0:
        print("H doesn't have Hojyuu seisitu")
        return 1,0,0
    else:
        X_H = np.dot(X2_H,np.linalg.inv(X1_H))
        
    """
    さらに,解の正定性を確認
    """
    if np.all(np.linalg.eigvals(X_H) > 0):
        print("X of H is positive")
    else:
            return 2,0,0
    
    """
    リカッチ方程式の確認
    """
    hoge = np.dot(A.conj().T,X_H)
    hoge = hoge + np.dot(X_H,A)
    R=np.dot(B1,B1.conj().T) / (gamma**2) - np.dot(B2,B2.conj().T) 
    hoge = hoge + np.dot(X_H,np.dot(R,X_H))
    hoge = hoge + np.dot(C1.conj().T,C1)
    #print(hoge)
    #print(" is 0? Is riccati correct ?")
    
    
    
    """
    J
    
    ハミルトン行列に固有値0を持たない,ハミルトン行列の解を求める,
    """
    J=J.astype(np.float64)
    Jw,Jv = np.linalg.eig(J) 
    
    for i in range(len(Jw)):        
        if Jw[i].real == 0:
            print("J have pole 0")
            return 7,0,0
            
    v_num = 0 
    for i in range(len(Jw)): 
        if Jw[i].real < 0:
            if v_num == 0:
                V = Jv[:,i].reshape(J.shape[0],1)
                v_num = v_num+1
            else:
                V = np.append(V,Jv[:,i].reshape(J.shape[0],1),axis = 1)
                v_num = v_num+1
    
    n=A.shape[0]
    X1_J = V[0:n,0:n]
    X2_J = V[2:n+2,0:n]
    
    if np.linalg.det(X1_J) == 0:
        print("J doesn't have Hojyuu seisitu")
        return 3,0,0
    else:
        X_J = np.dot(X2_J,np.linalg.inv(X1_J))
        
    """
    さらに,解の正定性を確認
    """
    if np.all(np.linalg.eigvals(X_J) > 0):
        print("X of J is positive")
    else:
        return 4,0,0
    
    """
    リカッチ方程式の確認
    """
    hoge = np.dot(A,X_J)
    hoge = hoge + np.dot(X_J,A.conj().T)
    R=np.dot(C1.conj().T,C1) / (gamma**2) - np.dot(C2.conj().T,C2)
    hoge = hoge + np.dot(X_J,np.dot(R,X_J))
    hoge = hoge + np.dot(B1,B1.conj().T) 
    #print(hoge)
    #print(" is 0? Is riccati correct ?")
    
    
    """
    スペクトル半径が gamma^2 以下である事の確認
    """
    hoge = np.dot(X_H,X_J)
    spectro_radius = max(np.abs(np.linalg.eigvals(hoge)))
    
    if spectro_radius < gamma**2:
        print("spectro radius < gamma^2")
        return 6,X_H,X_J
    else:
        print("spectro radius  error")
        return 5,0,0

A=np.array([[-1,10],[2,-0.1]])

w,v = np.linalg.eig(A) 

for i in range(len(w)):
    if w[i].real < 0:
        print("A is unstable")
        
    if w[i].real == 0:
        print("A have pole 0")
        

B1=np.array([[1,0],[2,0]])
B2=np.array([[1],[2]])

C1=np.array([[1,3],[0,0]])
C2=np.array([[1,3]])

D12 = np.array([[0],[1]])

D21= np.array([[0,1]])

"""
仮定の確認
"""

hoge = np.dot(D12.conj().T,D12)
I=np.diag(np.ones( np.shape(D12)[1] ))

if ( hoge == I).all:
    print("D12* D12 = I OK")
else:
    print("D12* D12 = I error")

hoge = np.dot(D21,D21.conj().T)
I=np.diag(np.ones( np.shape(D21)[0] ))

if (hoge == I).all():
    print("D21 D21* = I OK")
else:
    print("D21 D21* = I error")
    
hoge = np.dot(D12.conj().T,C1)
zeros = np.zeros(hoge.shape)

if (hoge == zeros).all():
    print("D12* C1 = 0 OK")
  

hoge = np.dot(B1,D21.conj().T)
zeros = np.zeros(hoge.shape)

if (hoge == zeros).all():
    print("B1 D21* = 0 OK")
    
    
"""
可制御・可観測の確認
"""

VC = copy.deepcopy(B1)
hoge = copy.deepcopy(A)
for i in range(A.shape[0]-1):
    hoge = np.dot(hoge,B1)
    VC=np.append(VC,hoge,axis = 1)  #横につなげる
    
if A.shape[0] == np.linalg.matrix_rank(VC):
    print("A B1 is controllable")
    
VC = copy.deepcopy(B2)
hoge = copy.deepcopy(A)
for i in range(A.shape[0]-1):
    hoge = np.dot(hoge,B2)
    VC=np.append(VC,hoge,axis = 1)  #横につなげる
    
if A.shape[0] == np.linalg.matrix_rank(VC):
    print("A B2 is controllable")
    

VO = copy.deepcopy(C1)
hoge = copy.deepcopy(A)
for i in range(A.shape[0]-1):
    hoge = np.dot(C1,hoge)
    VO=np.append(VO,hoge,axis = 0)  #横につなげる
    
if A.shape[0] == np.linalg.matrix_rank(VO):
    print("C1 A is observable")
    
VO = copy.deepcopy(C2)
hoge = copy.deepcopy(A)
for i in range(A.shape[0]-1):
    hoge = np.dot(C2,hoge)
    VO=np.append(VO,hoge,axis = 0)  #横につなげる
    
if A.shape[0] == np.linalg.matrix_rank(VO):
    print("C2 A is observable")

"""
ガンマイタレーションの開始
"""
gamma_up = 10**10
gamma_down = 0

while True:
    if gamma_up - gamma_down <0.001:
        break
    
    gamma = (gamma_up - gamma_down)/2 + gamma_down
    
    flag,X_H,X_J = check(gamma,A,B1,B2,C1,C2)
    
    if flag == 6:        #条件を満たす
        gamma_up = gamma
    else:                #条件を満たさない
        gamma_down = gamma
    
    print(gamma,flag )

print("gamma_up",gamma_up)

print("gamma_down",gamma_down)

gamma = (gamma_up - gamma_down)/2 + gamma_down


F = -1*np.dot(B2.conj().T,X_H)
n=A.shape[0]
eye = np.diag(np.ones(n))
Z = np.linalg.inv(eye - np.dot(X_J,X_H)/(gamma**2))
L = -1*np.dot(X_J,C2.conj().T)

A_K = A + np.dot(B1,np.dot(B1.conj().T,X_H))/(gamma**2)+np.dot(B2,F)+np.dot(Z,np.dot(L,C2))
B_K = -1*np.dot(Z,L)
C_K = F
D_K = 0

print("A_K",A_K)
print("B_K",B_K)
print("C_K",C_K)
print("D_K",D_K)

scilab

A=[-1 10
   2 -0.1]

B=[1 0 1
   2 0 2]

C=[1 3
   0 0
   1 3]
   
D=[0 0 0
   0 0 1
   0 1 0]

x0=[0
0.05]

sl = syslin('c',A,B,C,D,x0);

gopt = gamitg(sl,[1,1])

//[K,ro] = h_inf(sl,[1,1],0,100,100)

K=ccontrg(sl,[1,1],100);

ガンマの最適値はほぼ一致しますが,設計されるコントローラが一致しません・・・

やめます

途中ですが,こんなことを頑張る意味がない気がしてきました.
理論がわからなくても何とかなりますし,時間をかける必要がない気がしてきました.

もう,やめます.

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?