LADRC的离散化实现(Mark一下,重新开始)

LADRC的离散化实现

一、感慨

  上一次写博客是两年前了,现在已经过了那么久,期间经历了许多事,有好有坏,不多大多时候是丧的。到了现在,终究让我想通了一件事情,深刻理解并追求自己想要做的事情是会幸福的。通过读了许多书,看了许多视频,通过自身经历,总结得到了一个学习新的方法,以后还会不断的更新迭代。用模型,抽象的方法来观察和看待这是世界,但是前提我需要理解深刻。因此,在处于还有一年就毕业的状态下,打算恶补计算机知识,先提升自己理解知识的深度和广度,再形成看待世界的方法。

  为了填补两年前的坑,我在一年半以前把离散化 LADRC 写出来了,但是我在课题中一直没有用上,放着也觉得浪费,因此打算分享出来。期间也看到过别人用 C 语言啊等等写过离散的 ADRC,但是为了保证自己写博客的完善性,我决定还是放出来,算是有一段结束,再进行新的开始。

二、LADRC离散实现

  直接进入正题,因为是一年半以前写的了,过程和期间考虑的也忘记了,这次仅仅做一个总结,不能太保证准确性,同时自己工作重心也不想放这上面了(Xin Lei),但是框架和方向肯定是没错的。选择一个简单的对象进行实验,对于一个传递函数,
G ( s ) = 1 s 2 + 2 s + 4 (1) G(s) = \frac{1}{s^2+2s+4} \tag{1} G(s)=s2+2s+41(1)
  采样时间选择0.001s,因此得到z变换的传递函数为,
G ( z ) = 4.997 ∗ 1 0 − 7 z + 4.993 ∗ 1 0 − 7 z 2 − 1.998 z + 0.998 (2) G(z) = \frac{4.997*10^{-7}z+4.993*10^{-7}}{z^2-1.998z+0.998} \tag{2} G(z)=z21.998z+0.9984.997107z+4.993107(2)
  接下来基于LADRC的框架进行离散化,其中LESO部分离散化为,

%% 包含了初始化部分和迭代部分
% 初始化部分
z1 = zeros(1, len);
z2 = zeros(1, len);
z3 = zeros(1, len);

% Future z(i-1)   now z(i-2)   before  z(i-3)
z1(2) = z1(1) + sampleTime*(3*omega_o*(y(3) - z1(1)) + z2(1));
z2(2) = z2(1) + sampleTime*(3*omega_o^2*(y(3) - z1(1)) + b0*u(2) + z3(1));
z3(2) = z3(1) + sampleTime*(omega_o^3*(y(3) - z1(1)));

%% 迭代部分
for i = 1:len-1
    % Future z(i-1)   now z(i-2)   before  z(i-3)
    z1(i+2) = z1(i+1) + sampleTime*(3*omega_o*(y(i+3) - z1(i+1)) + z2(i+1));
    z2(i+2) = z2(i+1) + sampleTime*(3*omega_o^2*(y(i+3) - z1(i+1)) + b0*u(i+2) + z3(i+1));
    z3(i+2) = z3(i+1) + sampleTime*(omega_o^3*(y(i+3) - z1(i+1)));
    
    z1(i+1) = z1(i+2);
    z2(i+1) = z2(i+2);
    z3(i+1) = z3(i+2);
end

  PD控制器部分,

%% 初始化部分
% y(k) = -1.998*y(k-1) - 0.998*y(k-2) + 4.997e-7*u(k) + 4.993e-7*u(k - 1)
y = zeros(1, len);
u = zeros(1, len);

% Initialize all
e1(1) = input_signal(1) - z1(1);
u0(1) = Kp*e1(1) - Kd*z2(1);
e2(1) = u0(1) - z3(1);

u(1) = 0;
u(2) = e2(1) / b0;

% G(s) = 1/(s^2 + 2*s + 4);
% Gz = c2d(G, sampleTime) -----> Y/U = (4.997e-07 z + 4.993e-07) / (z^2 - 1.998 z + 0.998)
y(3) = 1.998*y(2) - 0.998*y(1) + 4.997e-7*u(2) + 4.993e-7*u(1);
error = 0;

%% 迭代部分
    e1(i+1) = input_signal(i+1) - z1(i+1);
    u0(i+1) = Kp*e1(i+1) - Kd*z2(i+1);
    e2(i+1) = u0(i+1) - z3(i+1);
    
    error = error + abs(e1(i+1));
    u(i+2) = e2(i+1) / b0;
    % G(s) = 1/(s^2 + 2*s + 4);
    
    % Gz = c2d(G, sampleTime) -----> Y/U = (4.997e-07 z + 4.993e-07) / (z^2 - 1.998 z + 0.998)
    y(i+3) = 1.998*y(i+2) - 0.998*y(i+1) + 4.997e-7*u(i+2) + 4.993e-7*u(i+1);

    y(i+1) = y(i+2);
    y(i+2) = y(i+3);
    
    u(i+1) = u(i+2);

  LADRC整体结构构建程序

% step 1: transfer function descrete.
% step 2: assemble all

clear
clc

%% Set sample time and end time, note: shanno sampling theory
sampleTime = 0.001;
offset = 0;

% 1.0
endtime = 1.5;
len = endtime / sampleTime;
t = sampleTime:sampleTime:endtime;

%% Parameter

%%% 0.019   15   180
%%% 0.05    15   90

b0 = 0.019;      % bo greater than or equal to b
omega_c = 15;
omega_o = 187.6250;

b0 = 0.019;      % bo greater than or equal to b
omega_c = 20;
omega_o = 187;

Kp = omega_c.^2;
Kd = 2*omega_c;

%% Set input signal
switch(1)
    case 1
        stepTime = 0.1;
        Temp = stepTime / sampleTime;
        input_signal(1:Temp) = 0;
        input_signal(Temp:len+1) = 1;
    case 2
        input_signal = impluse();
    case 3
        input_signal = wave();
    case 4
        input_signal = userDefine();
end

%% Descrete transfer function
% G(s) = 1/(s^2 + 2*s + 4);
% Gz = c2d(G, sampleTime) -----> Y/U = (4.997e-07 z + 4.993e-07) / (z^2 - 1.998 z + 0.998)
% Z^(-1) --->  y(k+2) - 1.998*y(k+1) + 0.998*y(k) = 4.997e-7*u(k+1) + 4.993e-7*u(k)
%        --->  y(k) = 1.998*y(k-1) - 0.998*y(k-2) + 4.997e-7*u(k-1) + 4.993e-7*u(k-2)

%% Initialize all
u0 = zeros(1, len);

z1 = zeros(1, len);
z2 = zeros(1, len);
z3 = zeros(1, len);

e1 = zeros(1, len);
e2 = zeros(1, len);

% Up to Gp(s) transfer function.
% y(k) = -1.998*y(k-1) - 0.998*y(k-2) + 4.997e-7*u(k) + 4.993e-7*u(k - 1)
y = zeros(1, len);
u = zeros(1, len);

%% Initialize all
e1(1) = input_signal(1) - z1(1);
u0(1) = Kp*e1(1) - Kd*z2(1);
e2(1) = u0(1) - z3(1);

u(1) = 0;
u(2) = e2(1) / b0;

% G(s) = 1/(s^2 + 2*s + 4);
% Gz = c2d(G, sampleTime) -----> Y/U = (4.997e-07 z + 4.993e-07) / (z^2 - 1.998 z + 0.998)
y(3) = 1.998*y(2) - 0.998*y(1) + 4.997e-7*u(2) + 4.993e-7*u(1);

% Future z(i-1)   now z(i-2)   before  z(i-3)
z1(2) = z1(1) + sampleTime*(3*omega_o*(y(3) - z1(1)) + z2(1));
z2(2) = z2(1) + sampleTime*(3*omega_o^2*(y(3) - z1(1)) + b0*u(2) + z3(1));
z3(2) = z3(1) + sampleTime*(omega_o^3*(y(3) - z1(1)));

error = 0;
%% Pro proccessing and update
for i = 1:len-1
    e1(i+1) = input_signal(i+1) - z1(i+1);
    u0(i+1) = Kp*e1(i+1) - Kd*z2(i+1);
    e2(i+1) = u0(i+1) - z3(i+1);

    error = error + abs(e1(i+1));
    u(i+2) = e2(i+1) / b0;
    
    % G(s) = 1/(s^2 + 2*s + 4);
    % Gz = c2d(G, sampleTime) -----> Y/U = (4.997e-07 z + 4.993e-07) / (z^2 - 1.998 z + 0.998)
    y(i+3) = 1.998*y(i+2) - 0.998*y(i+1) + 4.997e-7*u(i+2) + 4.993e-7*u(i+1);
    
    % Future z(i-1)   now z(i-2)   before  z(i-3)
    z1(i+2) = z1(i+1) + sampleTime*(3*omega_o*(y(i+3) - z1(i+1)) + z2(i+1));
    z2(i+2) = z2(i+1) + sampleTime*(3*omega_o^2*(y(i+3) - z1(i+1)) + b0*u(i+2) + z3(i+1));
    z3(i+2) = z3(i+1) + sampleTime*(omega_o^3*(y(i+3) - z1(i+1)));
    
    y(i+1) = y(i+2);
    y(i+2) = y(i+3);
    
    z1(i+1) = z1(i+2);
    z2(i+1) = z2(i+2);
    z3(i+1) = z3(i+2);
    
    u(i+1) = u(i+2);

end

error = error / length(u);

% input_signal = input_signal(1:len);
% u = u(1:len);
% y = y(1:len);
% z1 = z1(1:len);
% z2 = z2(1:len);
% z3 = z3(1:len);

%%
subplot(311)
plot(t, input_signal(1:len), t, y(1:len), t, z1(1:len),'--');
xlabel('Time array');
ylabel('set and y');
legend('set', 'y', 'z1')
subplot(312)
plot(t, z2(1:len))
xlabel('Time array');
ylabel('z2 Value');
legend('z2');
subplot(313)
plot(t, z3(1:len))
xlabel('Time array');
ylabel('z3 Value');
legend('z3');

三、结果

  其中LADRC参数选择为 b 0 = 0.019 , ω c = 15 , ω o = 187.6250 b_0=0.019,\omega_c=15,\omega_o=187.6250 b0=0.019,ωc=15,ωo=187.6250,最后运行结果如下,
在这里插入图片描述
  这里第一幅图为响应曲线,第二个为LESO估计的y的导数,第三个为LESO估计的总扰动。

四、总结

  通过离散化以后发现,在Matlab中使用Simulink仿真实际上是被优化过的,在现实应用中,LADRC受到了采样时间和噪声的约束。希望以后有机会能在工程中真的应用一下检测它的极限在哪些地方。

  • 10
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
LADRC是一种控制算法,其C语言实现可以如下所示: ```c #define N 3 // 系统状态变量的数量 #define M 1 // 控制信号的数量 float x[N]; // 系统状态变量 float u[M]; // 控制信号 float r[N]; // 参考信号 float q[N][N]; // 状态误差加权系数矩阵 float p[N][N]; // 状态协方差矩阵 float k[N][M]; // 控制增益矩阵 float a[N][N]; // 系统矩阵 float b[N][M]; // 输入矩阵 float c[N][N]; // 观测矩阵 float d[M][M]; // 输入协方差矩阵 float e[N][N]; // 状态协方差矩阵 void ladrc_control(float *y, float *x, float *u) { float z[N]; // 观测向量 float v[M]; // 测量噪声 float w[N]; // 状态噪声 float kk[N][N]; // Kalman增益矩阵 // 计算观测向量 for (int i = 0; i < N; i++) { z[i] = c[i][0] * y[0]; for (int j = 1; j < N; j++) { z[i] += c[i][j] * x[j]; } } // 计算控制增益矩阵 for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { k[i][j] = 0; for (int l = 0; l < N; l++) { k[i][j] += q[i][l] * c[l][j]; } k[i][j] /= d[j][j]; } } // 计算状态协方差矩阵 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { e[i][j] = 0; for (int l = 0; l < N; l++) { e[i][j] += a[i][l] * p[l][j]; } for (int l = 0; l < M; l++) { e[i][j] += b[i][l] * d[l][l] * b[j][l]; } } } // 计算Kalman增益矩阵 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { kk[i][j] = 0; for (int l = 0; l < N; l++) { kk[i][j] += e[i][l] * c[l][j]; } kk[i][j] /= (d[0][0] + kk[0][0]); } } // 计算状态估计值 for (int i = 0; i < N; i++) { x[i] = z[i]; for (int j = 0; j < N; j++) { x[i] -= kk[i][j] * z[j]; } } // 计算控制信号 for (int i = 0; i < M; i++) { u[i] = 0; for (int j = 0; j < N; j++) { u[i] += k[j][i] * (r[j] - x[j]); } } // 更新状态协方差矩阵 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { p[i][j] = e[i][j]; for (int l = 0; l < N; l++) { p[i][j] -= kk[i][l] * c[l][j] * e[0][0]; } } } } ``` 其中,`x`、`u`、`r`分别表示系统状态变量、控制信号和参考信号,`q`表示状态误差加权矩阵,`p`表示状态协方差矩阵,`k`表示控制增益矩阵,`a`、`b`、`c`、`d`分别表示系统矩阵、输入矩阵、观测矩阵和输入协方差矩阵,`e`表示状态协方差矩阵。函数`ladrc_control`表示LADRC控制算法的实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值