自抗擾控制(ADRC)—— 多級串聯型系統

問題描述

對如下的多級串聯型系統的控制問題

{x˙1=f1+x2,x˙2=f2+x3,x˙n1=fn1+xn,x˙n=fn+u,y=x1 \left\{ \begin{array}{ll} \dot{x}_1 &=f_1 + x_2, \\ \dot{x}_2 &= f_2 + x_3, \\ &\vdots \\ \dot{x}_{n-1} &= f_{n-1} + x_n, \\ \dot{x}_n &= f_n + u, \\ y &= x_1 \end{array} \right.
可以轉化成 n 個一階控制器設計問題,如圖
在這裏插入圖片描述
即首先用系統的輸出 y=x1y=x_1 去逼近目標信號 v(t)v(t),對變量x1x_1而言,需要的控制量爲 u1u_1

接下來遞歸地轉化成子問題:用x2x_2去逼近u1u_1,求出u2u_2; 用x3x_3去逼近u2u_2,……,求出 uu

仿真實驗

考慮二階被控對象:
{x˙1=f1(x1,t)+x2,x˙2=f2(x2,t)+u,y=x1 \left\{ \begin{array}{rl} \dot{x}_1 &=f_1(x_1, t) + x_2, \\ \dot{x}_2 &= f_2(x_2, t) + u, \\ y &= x_1 \end{array} \right.
其中f1,f2f_1,f_2對控制器而言未知,仿真時使用如下函數:
f1(x,t)=x2+cos(t)f2(x,t)=0.5sign(sin(2x))+sin(cos(t)) \begin{array}{l} f_1(x,t) = x^2 + cos(t) \\ f_2(x,t) = 0.5\,\text{sign}(\sin(2*x)) + \sin(\cos(t)) \end{array}

def f1(x,t):
    return x**2 + np.cos(t)

def f2(x,t):
    return 0.5*np.sign(np.sin(2*x)) + np.sin(np.cos(t))

有點複雜吧 🤷‍♀️

沒關係,ADRC 不怕非線性!

目標信號:

def target(t):
    if t < 10:
        return np.sign(np.sin(0.8*t))  
    elif t < 20:
        return 2*(0.5*t-int(0.5*t)-0.5)
    else:
        return np.sin(0.8*t)

在這裏插入圖片描述
非線性誤差

def fal(x, alpha=0.5, delta=0.1):
    return  x/np.power(delta,1-alpha) if np.abs(x)<delta else np.power(np.abs(x), alpha)*np.sign(x)

記錄時間序列的類,方便畫圖

class Logger:
    def __init__(self):
        self.data = {}
    
    def add(self, key, value):
        if key not in self.data:
            self.data[key] = []
        self.data[key].append(value)
      
    def plot(self, keys=None):
        plt.figure(figsize=(20,10))
        if keys is None:
            for k in self.data:
                plt.plot(self.data[k], label=k)     
        else:
            for k in keys:
                plt.plot(self.data[k], label=k)
        plt.legend()
        plt.show()     
logger = Logger()
h = 0.01
T = 30
N = int(T/h)

# 可調參數
r0 = 5
alpha1, alpha2 = 0.5, 0.9
beta1, beta2 = 10, 50

# 初值
v1 = 0
z11,z12,z21,z22 = 0,0,0,0
x1,x2 = 0,0
y = x1
u1,u = 0,0
for i in range(N):
    t = i*h
    
    # 目標信號
    v = target(t)

    # 過渡過程 v1 -> v, v1的過渡比v更加平緩
    v1 += h*r0*fal(v-v1, 0.5, h) 
    
    # ADRC1
    e = y - z11
    fe = fal(e, 0.5, h)
    z11 += h*(z12 + 100*e + u1)
    z12 += h*(100*fe)
    u1 = beta1*fal(v1 - z11, alpha1, 0.1) - z12
    
    # ADRC2
    e = x2 - z21
    fe = fal(e, 0.5, h)
    z21 += h*(z22 + 100*e + u)
    z22 += h*(100*fe)
    u = beta2*fal(u1 - z21, alpha2, 0.1) - z22
	
	# 系統狀態更新
    x1 += h*(f1(x1,t) + x2)
    x2 += h*(f2(x2,t) + u)
    y = x1


    logger.add('v1',v1)
    logger.add('y',y)
    logger.add('v',v)
    logger.add('u1',u1)
    logger.add('u',u)
    logger.add('f1',z12)
    logger.add('f2',z22)

logger.plot(['v','v1','y'])
logger.plot(['u','u1'])
logger.plot(['f1','f2'])

結果如下
在這裏插入圖片描述
所需的控制量:
在這裏插入圖片描述
系統的內部總擾動 f1,f2f_1, f_2
在這裏插入圖片描述
調了一個小時的參數 🤦‍♀️

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章