利用蚁群算法进行优化PID参数
在MATLAB中利用蚁群算法进行优化PID参数,自己觉得用S 函数来写不是特别的好,因此采用M 文件来写算法程序,然后通过和Simulink进行交互(MATLAB和Simulink史可以相互交换数据的),从而得到相应的结果。
下面主要说下在写程序的过程中,自己遇到的一些问题。因为是自己第一次在MATLAB中利用M文件来写算法,也是第一次学习使用多个M文件互相调用和嵌套,在写的这个过程中是充满了艰辛的。不过有点遗憾的是,应该是自己的参数没有设置好的缘故吧,最终的结果不是很理想。
在编写算法的过程中主要遇到的问题有语法错误、数字逻辑之间错误、函数调用的过程中参数变量的传递出错、不知道在M文件如何和Simulink中进行传递参数。
1)语法逻辑错误:在判断一个数在一定的范围的时候,我们总是受到我们之前的书写习惯(10<x<20),但是在MATLAB和VS中这么写是一种逻辑错误(正确的写法是((x<10)&&(x<20))),编译器并不会报错,但是编译器会认为这个条件是一直成立的,这是一个很坑爹的错误,只能怪自己编写的程序少。
2)在函数M文件的调用过程中,很容易导致自己传递的参数变量的个数或者位置出错,这种错误也只有运行的时候,才能发现错误。因为蚁群算法涉及到很多的参数传递,因此自己在编写的时候,在嵌套的时候有两三次都是忘记传递参数以及参数的位置出错了。
3)变量作用域问题:在MATLAB中,每次调用一个M文件,那么每次调用的过程中,M文件里定义的变量都会重新赋值。因为这些变量的作用域是在这个函数空间中的,每次调用完这个函数,这些变量也就没有了。所以如果想把一个函数中这一次迭代计算的结果留到下一次迭代中使用的话,那么就应该在主函数中定义一个变量来保存这个计算结果,而不是在要进行迭代的函数中定义一个变量来保存。否则的话,你每一次使用的结果都是定义变量的初始值。在全局变量的使用中的,你可以把输入参变量,也作为输出参变量,用来保存上一次迭代中的结果,用以下一次的使用。
4)之前看到一个前辈说过,在for循环中尽量不要使用变量i和j,因为这两个在MATLAB中也是充当复数变量的。
5)写这种程序还是要掌握一些基本的MATLAB的调试方法,设置断点,输出相应的变量值,不过在断点调试的过程中,运行的语句中的变量都会进行相应的输出。
6)对MATLAB中的数组使用的形式有两种,一种是采用[]小标,一种是采用{}下标,采用后一种的小标是cell 数组,cell数组不能采用第一种写法来使用数组元素。
7)在MATLAB中对阶跃响应进行采样的时候,即使你是采样时间间隔是0.002,依然有可能在这个间隔内变化0.5以上或者更多。为什么说这个呢?因为自己在对阶跃相应的结果进行分析求上升时间的时候,设置的条件是在0.89到0.90之间,变化的范围是0.01,但是还是出现了有的时候没有一个点在这个范围内的情况。
8)是和MATLAB的路径有关的问题。有的时候当你运行M 文件的时候,可能会报错:①在使用自定义函数时候,无论多么简单的函数,都会出现”未定义与 ‘double’ 类型的输入参数相对应的函数” ② Undefined function or variable ‘Function_name’.出现这些情况很大的可能的是MATLAB的路径不是你所要打开的文件的所在路径,当然还有可能当你在使用第三方库函数的时候,放置的路径中含有中文字符。那个含有中文字符的问题是我自己在MATLAB中用一个公司提供的第三方库的时候曾经遇到过,当时弄了好久没弄好,后来还是找售后才弄好的,只能说当时年少不懂事的。那个路径错误是自己帮同学调试程序的时候遇到了的,一开始以为是函数的问题,后来才发现是文件路径的问题。
9)有一次在帮同学调试模型的时候发现,无论怎么修改PID系数,最终的结果都不会发生变化。模型中的PID模块是同学自己创建子系统。因为他在用系统提供的PID模块的时候,发现其中的PID表达式和我们日常写的表达式不太一样,在微分中加入了一个滤波系数N,后来上网查一个这个系数的功能是为了抑制噪声的。于是就想自己用Simulink中提供的积分和微分模块来创建一个子系统,搭建自己想要的PID模块。经过一段时间的折腾发现是子系统中的各个环节的增益模块的系数没有改成相应的变量Kp、Ki、Kd。从而导致属性页中设置的Kp、Ki、Kd没有传递进去。
MATLAB和Simulink进行交互传递数据
1)、获取Simulink的模型中某一个模块的参数,注意该参数必须是模块属性页中的参数。目前发现对于S函数模块可以利用get_param来获取参数,但是好像并没有什么用。相应的命令是get_param(‘model_name/S-Function4′,’Parameters’),但是得到的是你设置的变量名称,并不是变量的值。而且当你使用Set_param时也可以对S函数的参数变量这一栏进行修改,但是修改之后你原来设置的参数名称也都没了。另外你自己创建的子系统也是可以使用这两个函数来进行函数参变量的设置的。S函数的属性页中有参数变量这一选型,但是这个可以在MATLAB的工作区间进行传递。
get_param(‘model_name/black_name’,’ parameter_name’);
set_param(‘model_name/black_name’,’ parameter_name’,’value’);
但是在M文件中使用Set_param函数的时候,我们经常需要传递的值是变量的值,此时我们需要对变量的值进行一定的转化,比如这样的set_param(‘OptimizerPID/PID Controller’,‘P’,num2str(Pid_kp));
2)、开始仿真:set_param(‘OptimizerPID’,’SimulationCommand’, ‘start’);机智的你一定知道结束仿真的命令就是把start 换成stop的。
3)、把Simulink中仿真的结果传递到M文件:simOut = sim(‘OptimizerPID’,…
‘StopTime’, ‘5’, …
‘ZeroCross’,‘on’,…
‘SaveTime’,‘on’,‘TimeSaveName’,‘tout’,…
‘SaveState’,‘on’,‘StateSaveName’,‘xoutNew’,…
‘SaveOutput’,‘on’,‘OutputSaveName’,‘youtNew’,…
‘SignalLogging’,‘on’,‘SignalLoggingName’,‘logsout’);
ppp1= simOut.get(‘fin’);
ppp2=simOut.get(‘fin1’);
对于simout这条语句中的诸多参数变量,有一些我也不是特别的清楚,但是在删除之后,发现程序还是可以运行的哈,对了每条语句后面的…是为了分行的,没有其他的作用。下面的两条语句就是把Simulink中你要想传递到M文件的变量名,前提是你在Simulink中已经设置好了变量的存储形式了。我采用的是利用To workspace模块并且保存的形式是数组的形式,没有试验其他的形式是否可以。我的猜想是可以的,但是应该在使用的时候应该是不方便的,结构体的形式还是没有数组使用的更直接方便一点。
PS:有了simout 这条语句就不需要把 set_param(‘OptimizerPID’,’SimulationCommand’, ‘start’)语句加入到程序中了。