如何解决simulink控制系统仿真中的代数环

目录

 1. 什么是代数环

  2. 如何解决代数环

  3. 多个s函数导致的代数环

  4. 源代码

1. 什么是代数环

         在simulink仿真过程中,当输入信号直接取决于输出信号,同时输出信号也直接取决于输入信号时,由于数字计算的时序性,而出现的由于没有输入无法计算输出,没有输出也无法得到输入的“死循环” ,称之为代数环

        如下图所示,output = func(input+output)。初始时,由于没有output,所以不能计算func函数;但是为了得到output,又必须要计算func。如此往复就形成了代数环。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_13,color_FFFFFF,t_70,g_se,x_16

2. 如何解决代数环

——连续模型

        对于连续模型,可以在反馈通道添加Memory模块延时

5b032f0514374f0581dceda54ce3474d.png                   watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

——离散模型

        对于离散模型,可以在反馈通道添加delay模块延时

d9129949b3164807afedfe68c2ff86e2.png                watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

 3. 多个s函数导致的代数环

        对于控制系统的仿真来说,很少会出现代数环的问题。下图这种系统就会出现代数环,但是这种系统本身就不存在(至少控制系统不会出现这种玩意)。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_11,color_FFFFFF,t_70,g_se,x_16

        当simulink中的模块不足以完成建模时,常用的方法就是使用s函数了。如果只是一个s函数建立的模型,例如下图,也不会出现代数环的问题(如果简单粗暴的用s函数建立上图那种模型当我没说)。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_17,color_FFFFFF,t_70,g_se,x_16

         如果用到多个s函数,如下图,就会提示代数环的警告了。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

systemP的模型:(源代码放最后啦)

gif.latex?%5Cbegin%7Bbmatrix%7D%20%5Cdot%7Bx%7D1%28t%29%5C%5C%20%5Cdot%7Bx%7D2%28t%29%20%5Cend%7Bbmatrix%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200%20%26%201%5C%5C%200%20%26%20-1%20%5Cend%7Bbmatrix%7D%5Cbegin%7Bbmatrix%7D%20x1%28t%29%29%5C%5C%20x2%28t%29%29%20%5Cend%7Bbmatrix%7D+%5Cbegin%7Bbmatrix%7D%200%5C%5C1%20%5Cend%7Bbmatrix%7D%20u%28t%29%20-%20%5Cbegin%7Bbmatrix%7D%200%5C%5C-%5Cfrac%7B1%7D%7B2%7D%20%5Cend%7Bbmatrix%7D%20M%28t%29

gif.latex?y%20%3D%20%5Cbegin%7Bbmatrix%7D%20x1%28t%29%5C%5C%20x2%28t%29%5Cend%7Bbmatrix%7D

systemM的模型:(源代码放最后啦)

gif.latex?M1%20%3D%2019.98%20*%20sign%28n0%20-%20n%29%20*%20%280.005%20*%20sin%28a%29%20+%200.02%20*%20cos%28a%29%29       ①

%20%280.0675%5E2%20-%200.055%5E2%29%29%20*%20%28n0%20-%20n%29   ②

 gif.latex?Mw%3D1.7987%20*%20%28tanh%2832.8317%20*%20w%29-tanh%287.4921%20*%20w%29%29%20+%200.9601%20*%20tanh%286.0375%20*%20w%29%20+%200.0378%20*%20w    ③

gif.latex?Mf%20%3D%200.1%20*%20sin%28w%29%20+%200.32       ④

gif.latex?y%20%3D%20M1+Mmud+Mw+Mf

        对于这种情况如果我们加入Memory模块做延时,虽然能解决代数环的问题,但是如果系统本身不是稳定的,延时环节会让系统产生震荡。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

         将加入Memory和没加Memory的两种输出的波形图对比:(本身搭建的系统就没有意义,所以不分析,将分析另外一个波形图,以此说明差异)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16


        上面的两个模型没有严密的逻辑分析,紧供分析代数环,所以对于系统震荡的问题不好分析,所以在此插入我另外一个仿真中遇到的两个图(也是systemM和systemP构成的仿真,只是系统严谨)

        下图是加入Memory延时,导致机器学习训练收敛性很差

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

        下图是去掉延时,解决代数环后,通过机器学习后的控制波形

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

         很容易发现,第二个的效果很好啦


        延时对不稳定系统的影响还是很大的。对于多个s函数,导致计算时序的影响,出现代数环的问题,我们可以在s函数上做调整。

         在s函数,flag等于0时,也就是初始化时,我们可以看到

sizes.DirFeedthrough

        的设置,输入是否直接影响输出。将其值设为0(修改连续系统的DirFeedthrough,如果修改纯数学公式的会导致仿真错误,本文中systemP为连续系统,systemM为数学公式);仿真时就不会出现代数环的问题,且波形和有代数环时一样。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16


        我在做仿真的时候,systemP和systemM可以用simulink提供的模块搭建,但是会比较麻烦,所以采用了s函数,后来也做了完全用simulink提供的模块搭建的仿真,控制效果也和s函数出现的效果类似。


4. 源代码

systemP:

%systemP
function [sys,x0,str,ts,simStateCompliance] = systemP(t,x,u,flag)

switch flag
  case 0   
    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;
  case 1   
    sys=mdlDerivatives(t,x,u);
  case 2    
    sys=mdlUpdate(t,x,u);
  case 3   
    sys=mdlOutputs(t,x,u);
  case 4   
    sys=mdlGetTimeOfNextVarHit(t,x,u);
  case 9   
    sys=mdlTerminate(t,x,u);
  otherwise 
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
end

function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
sizes = simsizes;          
sizes.NumContStates  = 2;  
sizes.NumDiscStates  = 0;  
sizes.NumOutputs     = 2;   
sizes.NumInputs      = 2; 
sizes.DirFeedthrough = 1;   
sizes.NumSampleTimes = 1;  

sys = simsizes(sizes);

x0  = [0;0];

str = [];

ts  = [0 0]; 

simStateCompliance = 'UnknownSimState';

function sys=mdlDerivatives(t,x,u)
sys = [0 1;0 -1] * x + [0;1]*u(1) - [0;-1/2]*u(2);

function sys=mdlUpdate(t,x,u)
sys = [];

function sys=mdlOutputs(t,x,u)
sys = x;

function sys=mdlGetTimeOfNextVarHit(t,x,u)
sampleTime = 1; 
sys = t + sampleTime;

function sys=mdlTerminate(t,x,u)
sys = [];

systemM:

%systemM
function [sys,x0,str,ts,simStateCompliance] = systemM(t,x,u,flag)

switch flag
  case 0  
    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;
  case 1  
    sys=mdlDerivatives(t,x,u);
  case 2   
    sys=mdlUpdate(t,x,u);
  case 3   
    sys=mdlOutputs(t,x,u);
  case 4   
    sys=mdlGetTimeOfNextVarHit(t,x,u);
  case 9   
    sys=mdlTerminate(t,x,u);
  otherwise 
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
end


function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
sizes = simsizes;        
sizes.NumContStates  = 0;   
sizes.NumDiscStates  = 0;   
sizes.NumOutputs     = 1;   
sizes.NumInputs      = 3;   
sizes.DirFeedthrough = 1;   
sizes.NumSampleTimes = 1;  

sys = simsizes(sizes);

x0  = [];

str = [];

ts  = [0 0]; %[0 0] 

simStateCompliance = 'UnknownSimState'; 

function sys=mdlDerivatives(t,x,u)
sys = [];

function sys=mdlUpdate(t,x,u)
sys = [];

function sys=mdlOutputs(t,x,u)
n0 = u(1);        %r/min
a = u(2)*pi/180;  %degree
w = u(3);         %rad/s
n = w*60/(2*pi);  %r/min

M1 = 19.98 * sign(n0 - n) * (0.005 * sin(a) + 0.02 * cos(a));
Mmud = 2 / 15 * pi^2 * 0.05 * 1 * (0.0675^2 * 0.055^2 / (0.0675^2 - 0.055^2)) * (n0 - n);
Mw = 1.7987 * (tanh(32.8317 * w)-tanh(7.4921 * w)) + 0.9601 * tanh(6.0375 * w) + 0.0378 * w;
Mf = 0.1 * sin(w) + 0.32; 
ML = M1+Mmud+Mw+Mf;
sys = ML;

function sys=mdlGetTimeOfNextVarHit(t,x,u)
sampleTime = 1;    
sys = t + sampleTime;

function sys=mdlTerminate(t,x,u)
sys = [];

matlabsimulink代数环问题的讲解及解决方法1-解决代数环方法.doc 本帖最后由 小小2008鸟 于 2012-11-30 11:26 编辑 什么是代数环?发生在两个或多个模块在输入端口具有信号直接传递而形成反馈的情况时,直接传递的模块在不知输入端口的值的情况下无法计算出输出端的值,也就是现在时刻的输出是依赖现在时刻的输入值来计算的。当这种情况出现时simulink会在每一次迭代言算完成时,去决定它是否会有解。代数回路会减缓方真执行的速度并可能会没有解。     当方程两边都出现同一个变量时,即产生了代数环。如:3y 4=y 当Simulink中存在非模型延迟时,通常会产生代数环。比如,传感器将输出信号反馈到输入端。解决代数环      连续模型,在构成代数环的反馈环节加入memory模块;      离散模型就加入单位延迟1/Z,不过加入memory后仿真会慢些,但用了加速后,这个牺牲还是值得的。另还有拆解法等,具体见下面第9行论文内容。Simulink提供了一些专门手段来拆解代数环,例如代数约束模块,积分模块的状态输出端等。这些手段可以解决一些特定的代数环问题。下面举一个利用积分模块的状态输出端的例子。    从积分模块的输人端口到输出端口是非直通的,但从积分模块的初始值输人端口到输出端口,以及从复位输人端口到输出端口却都是直通的。因此,如果从积分模块的输出端口引出的信号再经过一些直通模块后又反馈到积分模块的初始值输人端口或者复位输人端口,则构成一个代数环。    为了解决这个问题,Simulink专门为积分模块设计了一个状态端口,其输出与输出端口完全相同,仅在内部计算的时序上有细微区别,而无论是从积分模块的初始值输人端口还是从复位输人端口到状态端口都是非直通的。因此,当出现上述的代数环问题时,可 以从积分模块的状态端口引出信号。这样,代数环就被拆解了
### 解决Simulink中的代数环问题 #### 一、理解代数环的本质 代数环是指在一个模型中存在一种特殊的反馈结构,在这种结构里,输入信号直接或间接地依赖于自身的输出信号而未经过任何延迟环节。当整个回路仅由直通模块构成时,则会形成这样的闭合循环[^3]。 #### 二、诊断设置调整 为了更好地理解和处理代数环现象,可以通过修改仿真参数来控制其行为。具体来说,可以在Simulation-Diagnostics菜单下找到Algebraic loop选项,并将其设为`Warning`而非默认的`Error`级别;如果希望完全忽略这些警告信息,则可进一步更改为`None`模式[^2]。 #### 三、引入延迟元素打破闭环 最有效的解决方案之一是在适当位置加入具有记忆特性的组件(如Unit Delay),以此切断即时的数据流连接并破坏原有的纯前馈路径。这样做不仅能够有效规避求解过程中可能出现的迭代不收敛情况,同时也简化了系统的数值计算过程[^1]。 ```matlab % 添加单位延迟单元到模型中以解决代数环 add_block('simulink/Sources/Unit Delay', 'myModel/Delay'); ``` #### 四、利用内置函数辅助分析 MATLAB提供了专门用于检测和调试复杂动态系统的工具箱——Simscape,其中包含了多种实用的功能可以帮助工程师们快速定位潜在的问题所在。对于特定场景下的优化建议也可以通过查阅官方文档获得更加详细的指导。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SudoReboot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值