自抗扰控制(ADRC)—— python 实战「建议收藏」

自抗扰控制(ADRC)—— python 实战「建议收藏」文章目录 什么是自抗扰控制 龙格库塔 辅助函数 跟踪微分器 扩张状态观测器 未知真实状态 控制仿真 本文利用跟踪微分器 TD 扩张状态观测器 ESO 非线性 PID 实现了受外扰的未知系统的控制 使得受控系统输出了期望的信号 无超调 无震颤 参数好调节 堪称完美控制器 什么是自抗扰控制 自抗扰技术的提出是为了解决 PID 控制技术的几个缺点

文章目录

什么是自抗扰控制

龙格库塔

辅助函数

跟踪微分器

扩张状态观测器

未知真实状态

控制仿真

本文利用跟踪微分器(TD)+ 扩张状态观测器(ESO)+ 非线性 PID 实现了受外扰的未知系统的控制,使得受控系统输出了期望的信号。

无超调,无震颤,参数好调节,堪称完美控制器!!!

什么是自抗扰控制

自抗扰技术的提出是为了解决PID控制技术的几个缺点:

要求缓变的输出变量跟踪跳变的控制目标是不合理的;

误差的微分信号不好提取, 易受噪声影响;

P、I、D的线性组合不是最优的组合方式;

误差积分I的引入带来很多副作用, 比如使得闭环变得迟钝、产生震荡等.

针对以上问题, 在自抗扰控制中分别使用以下策略来克服:

安排控制目标的“过渡过程”;

使用跟踪微分器(Tracking Differentiator, TD)提取“微分”;

寻找合适的非线性组合;

使用扩张状态观测器来估计总扰动.

以上四点中, 1和3可以视为工程上的优化策略, 而2和4的核心技术都是跟踪微分器.

跟踪微分器的功能为: 输入信号 v ( t ) v(t) v(t), 输出 n n n个信号 z 1 ( t ) , … , z n ( t ) z_1(t),\ldots,z_n(t) z1​(t),…,zn​(t). 其中 z 1 ( t ) z_1(t) z1​(t)跟踪信号 v ( t ) v(t) v(t), 而 z i ( t ) = z ˙ i − 1 ( t ) , i = 2 , 3 , … , n z_i(t)=\dot{z}_{i-1}(t), i=2,3,\ldots,n zi​(t)=z˙i−1​(t),i=2,3,…,n.

扩张状态观测器本质上也是一个跟踪微分器.

自抗扰控制中主要讨论的控制对象为受外扰的不确定对象:
x ( n ) = f ( x , x ˙ , … , x ( n − 1 ) , t ) + w ( t ) + u ( t ) x^{(n)} = f(x,\dot{x},\ldots,x^{(n-1)},t) + w(t) + u(t) x(n)=f(x,x˙,…,x(n−1),t)+w(t)+u(t)其中 f ( x , x ˙ , … , x ( n − 1 ) , t ) f(x,\dot{x},\ldots,x^{(n-1)},t) f(x,x˙,…,x(n−1),t)为未知函数, w ( t ) w(t) w(t)为未知的外扰, u ( t ) u(t) u(t)为控制量.

通常把 x , x ˙ , … , x ( n − 1 ) x,\dot{x},\ldots,x^{(n-1)} x,x˙,…,x(n−1)作为系统状态, 而扩张状态就是把 x ( n ) x^{(n)} x(n)也视为系统状态.

若 y = x ( t ) y = x(t) y=x(t)为观测量, 那么 x ˙ , … , x ( n ) \dot{x},\ldots,x^{(n)} x˙,…,x(n)就是观测量的各阶导数. 利用跟踪微分器, 可以直接根据 y y y将系统的各阶导数估计出来, 即实现了扩张状态的观测.

而估计出 x ( n ) x^{(n)} x(n)等价于将系统的未知动态 f ( x , x ˙ , … , x ( n − 1 ) , t ) f(x,\dot{x},\ldots,x^{(n-1)},t) f(x,x˙,…,x(n−1),t)和外扰 w ( t ) w(t) w(t)的总和估计出来了.

系统的未知动态和外扰之和称为总扰动.

在控制量 u ( t ) u(t) u(t)中将系统的总扰动抵消, 配合误差反馈, 就实现了自抗扰控制.

龙格库塔

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

def dxdt(F, X, t, h=1e-2):
assert(len(F)==len(X))
X = np.array(X)
K1 = np.array([f(X, t) for f in F])
dX = h*K1/2
K2 = np.array([f(X+dX, t+h/2) for f in F])
dX = h*K2/2
K3 = np.array([f(X+dX, t+h/2) for f in F])
dX = h*K3
K4 = np.array([f(X+dX, t+h) for f in F])

dX = (K1 + 2*K2 + 2*K3 + K4)*h/6

return dX, np.array([f(X, t) for f in F])

辅助函数

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


fal 函数具有小误差时高增益,大误差是低增益的特性,对抑制震颤发挥了重要作用。

跟踪微分器

期望输出为方波信号 v ( t ) v(t) v(t)

# target signal
def v(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 v1(X, t):
x1, x2 = X[0], X[1]
return x2

def v2(X, t):
x1, x2 = X[0], X[1]
return -R*sat(x1 - v(t) + np.abs(x2)*x2/(2*R), delta)

扩张状态观测器

# eso
# 极点配置
p = np.poly1d([-15,-15,-15],True)
_, b1, b2, b3 = tuple(p.coef)

def g1(X, t):
x1,x2,x3 = X[0], X[1], X[2]
return x2 - b1 * (x1 - y) # y is model output

def g2(X, t):
x1, x2, x3 = X[0], X[1], X[2]
return x3 - b2 * (x1 - y) + u

def g3(X, t):
x1, x2, x3 = X[0], X[1], X[2]
return -b3 * (x1 - y)

未知真实状态

x ¨ = − x 3 − x − 0.2 x ˙ + w ( t ) + u ( t ) \ddot{x} = -x^3-x-0.2\dot{x} + w(t) + u(t) x¨=−x3−x−0.2x˙+w(t)+u(t)
其中 w ( t ) w(t) w(t) 为外部扰动, u ( t ) u(t) u(t) 为控制输入。

# hidden uncertain model
def f1(X, t):
x, y = X[0], X[1]
return y

def f2(X, t):
x, y = X[0], X[1]
return -x*x*x - x -0.2*y + w(t) + u

def w(t):
return 0.2 * np.sign(np.cos(t)) # perturbation

控制仿真

R = 90  # params in sal
delta = 0.001 # params in sal
h = 0.01 # discrete time unit
T = 20 # total time
N = int(T/h) # num of points
V = [0., 0.] # TD signal
X = [0., 0.] # true state
Z = [0., 0., 0.] # ESO
u = 0 # initial control input

actual_output = []
expect_output = []
uncertain_dynamics = []

for i in range(N):
t = i*h # time

dX, _ = dxdt([f1,f2],X,t,h)
X = X + dX
y = X[0] # model output

dV, _ = dxdt([v1,v2],V,t,h)
V = V + dV

dZ, _ = dxdt([g1,g2,g3],Z,t,h)
Z = Z + dZ

e_p = V[0] - Z[0]
e_d = V[1] - Z[1]

fep, fed = fal(e_p), fal(e_d)

u = 10*fep + 50*fed - Z[2]

actual_output.append(y)
expect_output.append(V[0])
uncertain_dynamics.append(Z[2])


plt.plot(actual_output, color='black', label='output')
plt.plot(expect_output, color='red', linestyle='--',label='expect')
plt.plot(uncertain_dynamics, color='green', linestyle='--',label='uncertain state')
plt.legend(loc='lower right')
plt.show()


妈妈再也不用担心我调不好PID啦😎

编程小号
上一篇 2025-02-18 14:17
下一篇 2025-02-06 13:06

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/hz/126349.html