欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自抗扰控制(ADRC)—— 一阶系统

程序员文章站 2024-01-09 22:28:40
...

问题描述

使用 ADRC 控制任意一阶系统:
x˙=f(x,t)+u\dot{x} = f(x,t)+u其中ff表示系统所受的总扰动,包含未知的外扰和未建模的内部动态。

这里的仿真实验中测试的总扰动为:
f(x,t)=x2+0.5sign(sin(2t))+cos(xt)f(x,t) = x^2 + 0.5 \, \text{sign}(\sin(2t)) + \cos(xt)而且控制器不应该知道该具体形式。

????‍♀️

控制目标为使得xx输出如下形状的信号:
自抗扰控制(ADRC)—— 一阶系统

代码

总扰动和目标信号

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

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)

定义一个类保存时间序列,方便画图

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()     

一个常用的非线性误差函数,具有小误差大增益,大误差小增益的特性。

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)

自抗扰控制(ADRC)—— 一阶系统
使用欧拉积分做数值积分

logger = Logger()
h = 0.01
T = 30
N = int(T/h)

r0 = 5  # r0调控过渡的快慢

# 一些初值的设定
v1 = 0
z1,z2 = 0,0
x = 0
y = x
u = 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) 
    
    # ESO: z1 -> y, z2 = \dot{z1}
    e = y - z1
    fe = fal(e, 0.5, h)
    z1 += h*(z2 + 100*e + u)
    z2 += h*(300*fe)
    
    # 误差反馈
	# e1 = v1 - y 
    e1 = v1 - z1
    u = 10*fal(e1,0.5,0.1) - z2
    
    # 系统状态更新
    w = f(x,t)
    x += h*(w + u)
    
    # 输出 
    y = x

    logger.add('v1',v1)
    logger.add('y',y)
    logger.add('v',v)
    logger.add('u',u)
    logger.add('z2', z2)
    logger.add('w', w)

logger.plot(['v'])
logger.plot(['v','v1','y'])
logger.plot(['w','z2','u'])

结果展示如下,v代表真实目标信号,v1v_1是v的平滑过渡,y是实际输出
自抗扰控制(ADRC)—— 一阶系统
w 代表真实总扰动,z2z_2是对总扰动的跟踪,u是控制输入
自抗扰控制(ADRC)—— 一阶系统
下面我来增大 r0:510r_0:5\rightarrow 10,意味着过渡信号v1v_1更加逼近真实信号vv
自抗扰控制(ADRC)—— 一阶系统
自抗扰控制(ADRC)—— 一阶系统
过渡过程越短,意味着要在更短的时间做出同样的变化,自然就要求控制量uu的绝对值要增大,从上图可以看出这一点。