这两天看了一下LADRC的。学习深度不够,从理论和原理,没法评论什么。从个人感受上,它会从另一种角度去解释一些的控制的东西。从工程使用上,还是很有参考价值的,参数意义比较明确,整定参数比较容易。
参考:
- 古典控制与低阶LADRC参数整定(https://www.bilibili.com/video/BV1UD4y117yB/?spm_id_from=333.999.0.0&vd_source=1f88f15c4a8c95c1d720fa4c6218bc54)
- https://zhuanlan.zhihu.com/p/585324684
一阶LADRC
一阶被控对象
y
˙
=
b
0
u
+
f
\dot{y}=b_0u+f
y˙=b0u+f
扩张state-space:
{
x
˙
1
=
x
2
+
b
0
u
x
˙
2
=
f
˙
y
=
x
1
\left\{ \begin{array}{l} \dot{x}_1=x_2+b_0u\\ \dot{x}_2=\dot{f}\\ y=x_1\\ \end{array} \right.
⎩
⎨
⎧x˙1=x2+b0ux˙2=f˙y=x1
LESO:
{
z
˙
1
=
β
1
(
y
−
z
1
)
+
z
2
+
b
0
u
z
˙
2
=
β
2
(
y
−
z
1
)
\left\{ \begin{array}{l} \dot{z}_1=\beta_1 (y-z_1)+z_2+b_0u \\ \dot{z}_2=\beta_2(y-z_1)\\ \end{array} \right.
{z˙1=β1(y−z1)+z2+b0uz˙2=β2(y−z1)
控制器:
u
=
1
b
0
[
l
1
(
r
e
f
−
z
1
)
−
z
2
]
u=\frac{1}{b_0}[l_1(ref-z_1)-z_2]
u=b01[l1(ref−z1)−z2]
其中
l
1
=
ω
c
,
β
1
=
2
ω
o
,
β
2
=
ω
o
2
l_1=\omega_c, \beta_1=2\omega_o, \beta_2=\omega_o^2
l1=ωc,β1=2ωo,β2=ωo2
ω c \omega_c ωc是控制器带宽, ω o \omega_o ωo是观测器带宽。一般选取 ω o = 2 − 10 ω c \omega_o = 2-10\omega_c ωo=2−10ωc。 b 0 b_0 b0跟系统的一些参数有关。
其框图结构:
代码实现:
代码实现也很简单,计算量很小。放mcu上,再简单优化一下,也就只比PI多几个乘法和加法。
hpp:
/**
* @copyright Copyright wangchongwei
* @license: GNU GPLv2
* @brief: adrc 1st
* @date 2023.03.05
* @changelog:
* date author notes
* 2023.03.05 wangchongwei create file
**/
#ifndef _LADRC_1ST_H_
#define _LADRC_1ST_H_
class LADRC_1st
{
public:
LADRC_1st(/* args */);
~LADRC_1st();
void setCtrlParm(double wc, double wo, double b0,double ts);
void setClampParm(double out_up, double out_low);
void reset(void);
double ladrc_1st(double ref,double fb);
private:
double ts;
double wc;
double wo;
double b0;
double out_up;
double out_low;
double out;
// observer
double z[2];
double dz[2];
};
#endif
cpp:
void LADRC_1st::setCtrlParm(double wc, double wo, double b0,double ts)
{
this->b0 = b0;
this->wc = wc;
this->wo = wo;
this->ts = ts;
}
void LADRC_1st::setClampParm(double out_up, double out_low)
{
this->out_up = out_up;
this->out_low = out_low;
}
double LADRC_1st::ladrc_1st(double ref,double fb)
{
// leso
dz[0] = 2*wo*(fb-z[0])+z[1]+b0*out;
dz[1] = wo*wo*(fb-z[0]);
z[0] += ts*dz[0];
z[1] += ts*dz[1];
// controller
out = (wc*(ref-z[0])-z[1])/b0;
if (out > out_up) out = out_up;
if (out < out_low) out = out_low;
return out;
}
github地址:
https://github.com/chongweiwang/CtrlSim/tree/main/lib/controller/adrc