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

自抗扰控制(ADRC)—— python 实战「建议收藏」本文利用跟踪微分器(TD)、扩张状态观测器(ESO)和非线性PID实现了受外扰的未知系统的控制,使得受控系统输出了期望信号。

大家好,又见面了,我是你们的朋友全栈君。

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

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

什么是自抗扰控制

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

  1. 要求缓变的输出变量跟踪跳变的控制目标是不合理的;
  2. 误差的微分信号不好提取, 易受噪声影响;
  3. P、I、D的线性组合不是最优的组合方式;
  4. 误差积分I的引入带来很多副作用, 比如使得闭环变得迟钝、产生震荡等.

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

  1. 安排控制目标的“过渡过程”;
  2. 使用跟踪微分器(Tracking Differentiator, TD)提取“微分”;
  3. 寻找合适的非线性组合;
  4. 使用扩张状态观测器来估计总扰动.

以上四点中, 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˙i1(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(n1),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(n1),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(n1)作为系统状态, 而扩张状态就是把 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(n1),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)<delta else np.sign(x)

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)

在这里插入图片描述
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¨=x3x0.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啦?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144673.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 163邮箱收不到邮件怎么办苹果手机_163邮箱收不到epic邮件

    163邮箱收不到邮件怎么办苹果手机_163邮箱收不到epic邮件电子邮箱在我们工作生活中占有十分重要的地位。从个人使用个人邮箱,到公司企业使用企业邮箱,这些邮箱使用过程中都存在各种各样的疑问。其中163邮箱收不到邮件就是众多朋友的困扰之一。针对这一现象,今天来为大家分享一下,我们应该如何应对。我们首先要区分清楚163邮箱163邮箱包含两种:属于网易的163.com和属于TOM的163.net163.com邮箱介绍:163.com邮箱是中国早期的电子邮件服…

    2022年9月13日
    2
  • Identity标识列

    SQLServer中,经常会用到Identity标识列,这种自增长的字段操作起来的确是比较方便。但它有时还会带来一些麻烦。示例一:当表中被删除了某些数据的时候,自增长列的编号就不再是一个连线的数

    2021年12月22日
    48
  • ssl数字证书是什么意思_数字证书的内容是

    ssl数字证书是什么意思_数字证书的内容是本文转自 http://seanlook.com/2015/01/15/openssl-certificate-encryption/SSL/TLS介绍见文章 SSL/TLS原理详解。如果你想快速自建CA然后签发数字证书,请移步 基于OpenSSL自建CA和颁发SSL证书 。首先简单区分一下HTTPS、SSL、OpenSSL三者的关系:SSL是在客户端和服务器之间建立

    2025年6月2日
    4
  • 深度学习是什么

    深度学习是什么[toc]前言加里·卡斯帕罗夫vs深蓝(1997年)1997年,美国IBM公司的“深蓝”(DeepBlue)超级计算机以2胜1负3平战胜了当时世界排名第一的国际象棋大师卡斯帕罗夫

    2022年8月2日
    8
  • break 和 continue 的区别_continue的用法

    break 和 continue 的区别_continue的用法break和continue区别和用法的视频教程:https://ke.qq.com/course/149432?tuin=57912c43有技术问题或者面试方面想学习交流的加我个人微信renlliang2013,本人建了一个微信答疑群,有学习疑问的同学加我拉你进群。想搞清楚break和continue的用法以及区别必须要记住的两件两句话!我们大家先记住一句话:break再循环…

    2022年9月13日
    0
  • java stream流操作_java流式处理

    java stream流操作_java流式处理目录1、什么是流2、如何生成流3、流的操作类型3.1、中间操作3.2、终端操作4、流的使用4.1中间操作filter筛选distinct去重limit返回指定流个数skip跳过流中的元素map流映射flatMap流转换allMatch匹配所有元素anyMatch匹配其中一个noneMatch全部不匹配4.2终端操作count统计流中元素个数findFirst查找第一个findAny随机查找一个reduce将流中的元素组合min/max获取最小最大值sum/summingxxx

    2022年9月1日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号