控制系统仿真工具.docx
《控制系统仿真工具.docx》由会员分享,可在线阅读,更多相关《控制系统仿真工具.docx(89页珍藏版)》请在冰点文库上搜索。
控制系统仿真工具
第8章控制系统仿真工具
8.1仿真工具概述
计算机是系统仿真最重要的工具,用于仿真的计算机基本可分为通用计算机和专用计算机。
常用的仿真语言有C语言、VisualBasic和Matlab。
C语言主要用于仿真研究后直接进行实际工程应用(单片机、工控机等)且对界面要求不高的情况;VisualBasic主要用于仿真研究后直接进行实际工程应用(微机、工控机)且要求界面设计美观的情况;而Matlab主要用于纯仿真研究,以便得出一些具有参考意义的结论。
除计算机以外,仿真工具还包括两类仿真器:
专用的物理仿真器和用于训练操纵人员的所谓操纵训练仿真器。
8.2VB语言仿真
(1)VisualBasic的优点
1976年,现任美国微软公司总裁BillGates(比尔·盖茨)先生和PaulAllen开发出了Basic语言的早期版本。
1998年12月微软公司正式推出VisualBasic6.0中文版本,尤其是近3年,VisualBasic几乎是两年更新一个版本,说明VisualBasic程序开发的投资力度和受重视的程度。
可以说VisualBasic是BillGates先生的招牌,他是靠Basic语言起家的,故其发展的速度和投资力度是有保证的;另一方面,VisualBasic的迅猛发展也是其应用广泛和受用户喜爱的一个标志。
用VB编程具有以下5个优点:
1)用户图形界面编程工作量少。
一个实际的软件编程可分为图形界面编程和非图形界面编程两部分,分别代表用户可见的和不可见的部分。
由于VB编程面向用户图形界面,用户只需按设计风格和实际要求将VB系统环境所提供的基本元素(包括按钮、图片、文本框、标签等)放在窗体中,然后更改其属性表即可,就像用各种事先做好的模具来绘画一样,只需按脑海中构想的图找到相应的模板在图画纸的相应位置上画好,然后涂上颜色就行了。
所以说用VB编程,用户可见部分的图形界面编程的工作量大大降低,从而缩短了软件的开发周期。
2)VB编程以事件驱动为机制。
用户的任何一个动作都产生一个事件,如按鼠标左键、击键等,如果给一个事件编程了,则当该事件发生时就会产生执行效果。
可以给所有可能发生的事件都编程,则任何一个事件发生都会产生效果。
就像玩捅开纸格中奖游戏一样,如果每一个纸格后面都藏有奖品,则每捅开一次纸格都会中奖,只不过奖品不同而已。
也有可能纸格后面没有藏奖品(相当于某一事件没有编程),则捅开该纸格后将得不到奖品(相当于该事件发生后将没有执行效果)。
同时其事件驱动的编程机制使得程序设计起来容易,读起来直观,使用起来方便。
3)VB采用面向对象的程序设计方法,程序代码具有良好的可重用性、可扩充性和可修改性。
4)VB6.0作为Windows编程技术之一,具有Windows环境所具有的5大优点:
即标准的图形用户界面、动态链接(DDL)、多任务、设备独立性及直接操作特性。
5)由于VB的用户越来越多,很多计算机软件公司相继开发出适于VB的工具箱,目前由第三方(即非Microsoft公司和用户以外的第三计算机软件开发方)开发的VB工具箱已达上百种,故VB程序设计随时间的推移会越来越简单。
关于VisualBasic程序设计的学习请参见文献[28]和文献[29]。
(2)用VB进行计算机仿真的工作步骤
1)将要仿真的系统数学模型写成微分方程组形式,并编写成函数或普通过程。
2)选择适当的系统离散化方法,并编写成函数或普通过程。
3)计算或估算出系统的采样步长大小。
4)对控制器选择适当的离散化方法,写出递推公式。
5)给定输入,按反馈系统信号传递方式,由递推公式,求出输出。
6)判断输出的精度是否满足要求,如果满足要求转步骤7,否则转步骤5。
7)画仿真曲线,输出仿真数据,并根据仿真结果进行分析,给出结论。
在进行连续系统数字仿真时,离散方法的选择十分重要。
但是究竟如何选择,至今没有一种具体办法。
所以,只能根据实际系统的性能、所要求的精度和计算机的速度、内存等性能等实际情况的不同具体选择一个较为合适的离散方法。
下面给出4阶龙格库塔法的VB程序清单:
Subrk4()
Dimi,jAsInteger
u(0)=.5*h
u
(1)=u(0)
u
(2)=h
u(3)=h
u(4)=u(0)
Fori=0Ton'赋数组初始值
f(i)=0#
xr(i)=x(i)
yw(i)=x(i)
Nexti
Fori=0To3
fss'计算k1,k2,k3,k4,fss为数学模型微分方程组过程名
Forj=0Ton
xr(j)=yw(j)+u(i)*f(j)'为计算k2,k3,k4作准备
x(j)=x(j)+u(i+1)*f(j)/3#'x(j)为龙格库塔解
Nextj
Nexti
EndSub
说明:
该4阶龙格库塔VB普通过程代码适用于对具有由n个微分方程组成的数学模型进行离散求解,是一个通用的程序,读者一步一步验算可知其公式与前面给出的4阶龙格库塔公式是完全一致的。
虽然读起来不那么直观,但程序中应用了一些编程技巧和经验,所用语句、变量都最少,具有节省内存、运行速度快的优点。
当然要想正确应用该程序,还需:
将h,n,u(4)定义成模块级或全局的常数和数组,将f(微分方程的微分变量数组),xr(微分方程的状态变量数组),yw(中间变量数组),x(初值变量及解变量数组)定义成具有n维的模块级或全局数组,注意n必须为具体的数。
在名为fss的普通过程中按标准状态空间方程的形式即
编写数学模型的微分方程,f数组代表微分变量数组,xr数组代表状态变量数组。
在事件过程中编写用龙格库塔方法解算数学模型的计算机仿真程序,包括赋变量初值、循环解算并判断解是否满足精度要求、解的数据及图形曲线输出等。
【例8.2.1】用VB6.0对船舶航向自动舵控制系统进行计算机仿真,目的是测试所设计的航向自动舵控制算法是否满足所要求的性能指标,假设其控制算法采用PI控制,而船舶运动仿真数学模型采用第6章的三自由度模型。
控制精度要求:
航向误差小于0.1,上升时间小于250s,最大超调量不大于40%。
系统框图如图8.2.1所示。
仿真要求给出航向fai及舵令delt的仿真曲线结果,并分析仿真结果。
图8.2.1船舶航向自动舵控制系统框图
控制算法采用:
PI控制,即
,其中比例系数和积分系数根据控制的仿真效果自己调整,控制器的离散建议用Tustin变换,利用其简单、稳定的优点。
船舶运动仿真数学模型采用三自由度模型,离散算法采用RK4或RK5,利用其适用于非线性模型的优点。
步长自己按经验公式计算。
数学模型的数据来源于大连远洋运输公司的“阳澄湖”号油船的数据,全部采用状态空间数学模型,为了简化模型,暂不考虑风、浪、流等干扰项,即使用名义数学模型,现给出其模型参数如下:
(8-2-1)
其中
分别为船舶的横漂速度和艏摇角速率
用VB6.0编程实现的步骤如下:
1)计算采样时间步长,根据第7章给出的经验公式,首先绘制出船舶运动数学模型的Bode图如图8.2.2所示,求出
rad/s,则采样时间步长h取6s。
2)采用Tustin变换将K离散化得
图8.2.2船舶运动数学模型的Bode图
3)确定仿真结束条件,本例通过判断仿真时间长短作为仿真结束条件,要求仿真2400s即400步,系统仿真达到稳态后为直线,观察价值不太,如果在2400s内系统还未达到稳态,则认为控制器参数不好,应重新调整PI控制器的比例系数和积分系数。
4)启动VB6.0,更改窗体的Caption属性为“船舶航向自动舵控制系统仿真”,Borderstyle属性改为1-FixedSingle,并将窗体拖至足够大用以显示两个曲线图。
5)打开代码窗口,编写代码如下:
'在general中定义模块级变量
Consth!
=6#'采样时间为6.0s
Dimu(4)AsSingle
Constn%=2'3个微分方程
Dimf
(2),xr
(2),yw
(2),x(3)AsDouble
Dimdelt,dfai,fair,faiAsSingle
Dimaa,bbAsInteger
Subfss()'数学模型普通过程
f(0)=-0.027*xr(0)-1.846*xr
(1)+0.042*delt
f
(1)=-0.001*xr(0)-0.089*xr
(1)-0.002*delt
f
(2)=xr
(1)
EndSub
Subrk4()'4阶龙格库塔普通过程
Dimi,jAsInteger
u(0)=0.5*h
u
(1)=u(0)
u
(2)=h
u(3)=h
u(4)=u(0)
Fori=0Ton'赋数组初始值
f(i)=0#
xr(i)=x(i)
yw(i)=x(i)
Nexti
Fori=0To3
fss'计算k1,k2,k3,k4,fss为数学模型微分方程组过程名
Forj=0Ton
xr(j)=yw(j)+u(i)*f(j)'为计算k2,k3,k4作准备
x(j)=x(j)+u(i+1)*f(j)/3#'x(j)为龙格库塔解
Nextj
Nexti
EndSub
'绘图子程序
Subht0(zsxAsInteger,zsyAsInteger,yxxAsInteger,yxyAsInteger,xiAsInteger,yiAsInteger,x0AsSingle,xstepAsSingle,pageAsInteger,y0AsSingle,ystepAsSingle,xtxAsInteger,xtAsString,ytyAsInteger,ytAsString,titlexAsInteger,titleAsString)
'zsx左上角x坐标,zsy左上角y坐标,yxx右下角x坐标,yxy右下角y坐标,xi为x轴标度坐标间隔,yi为y轴标度坐标间隔,x0为x轴标度数据起点,xstep为x轴标度数据步长,page为页号(曲线连续多页显示时用),y0为y轴标度数据起点,ystep为y轴标度数据步长,xtx为x轴说明起始坐标,xt为x轴说明字符串,yty为y轴说明起始坐标,yt为y轴说明字符串,titlex为图的标题起始x坐标,title为图的标题
Dimi,j,hxw,hxt,sxw,sxt,titley,xty,ytx,pagex,pagey,dataxx,dataxy,datayx,datayyAsInteger
hxw=20'横虚线宽
hxt=40'横虚线加上虚线缝隙总宽
sxw=1'竖虚线宽
sxt=2'竖虚线加上缝隙总宽
titley=8'标题y坐标距上边框距离
xty=2'x轴说明坐标距底边框距离
pagex=yxx'页码x坐标
pagey=zsy'页码y坐标
ytx=200'y轴说明坐标距左边框距离
dataxx=100'x轴数据标注间隔
dataxy=2'x轴数据标注距底边框距离
datayx=120'y轴数据标注距左边框距离
datayy=2'y轴数据标注间隔
Form1.Line(zsx,zsy)-(yxx,yxy),RGB(0,255,0),B'画曲线边框
Fori=0To((yxy-zsy)/yi-2)'画横的虚线网格
Forj=zsxToyxx-hxwStephxt
Form1.Line(j,zsy+(i+1)*yi)-(j+hxw,zsy+(i+1)*yi),RGB(0,255,0)
Nextj
Nexti
Forj=0To((yxx-zsx)/xi-2)'画竖的虚线网格
Fori=zsyToyxy-sxwStepsxt
Form1.Line(zsx+xi*(j+1),i)-(zsx+xi*(j+1),i+sxw),RGB(0,255,0)
Nexti
Nextj
Form1.CurrentX=titlex'标题显示
Form1.CurrentY=zsy+titley
Form1.Printtitle
Form1.CurrentX=xtx'x轴说明
Form1.CurrentY=yxy+xty
Form1.Printxt
i=0
DoWhilei<=(yxy-zsy)/yi'标注y轴数据
Form1.CurrentX=zsx-datayx
Form1.CurrentY=yxy-i*yi-datayy
Form1.PrintStr$(y0+i*ystep)
i=i+1
Loop
j=0
DoWhilej<=(yxx-zsx)/xi'标注x轴数据
Form1.CurrentX=zsx+j*xi-dataxx
Form1.CurrentY=yxy+dataxy
Form1.PrintStr$(x0+j*xstep)
j=j+1
Loop
Form1.CurrentX=zsx-ytx'y轴说明
Form1.CurrentY=yty
Form1.Printyt
EndSub
Subht(aAsDouble,bAsDouble,iAsInteger)'动态绘图
Ifi=1Then'准备航向误差初始坐标值
CurrentX=300
CurrentY=30
Else'准备航向误差当前坐标值
CurrentX=(i-1)*h+300
CurrentY=-aa+30
EndIf
Line-(i*h+300,-CInt(a)+30),RGB(255,0,255)
Ifi=1Then'准备舵令初始坐标值
CurrentX=300
CurrentY=90
Else'准备舵令当前坐标值
CurrentX=(i-1)*h+300
CurrentY=-bb+90
EndIf
Line-(i*h+300,-CInt(b)+90),RGB(0,0,255)
aa=CInt(a)'当前坐标更新
bb=CInt(b)
EndSub
PrivateSubForm_Click()
Dimdelt1,dfai1,kp,kiAsSingle
DimiAsInteger
kp=-0.1'PI控制器参数设置,负号是因假设舵令方向与实际方向相反
ki=-0.0001
Form1.BackColor=RGB(255,255,255)'设背景色为白色
Form1.AutoRedraw=True'图形自动重画
Scale(0,0)-(3000,120)'定义窗体坐标系
'绘制航向误差曲线
ht0300,10,2700,50,200,10,0,200,1,-20,10,2800,"(秒)",2,"dfai(度)",1300,"航向误差曲线"
'绘制舵令曲线
ht0300,70,2700,110,200,10,0,200,1,-20,10,2800,"(秒)",62,"delt(度)",1500,"舵令曲线"
fair=10'设定航向假设为10度
fai=0'设初始航向为0度
delt=0'设初始舵令为0度
delt1=0
dfai1=0
'控制器输出递推解算
Fori=1To400'仿真400步即2400s
dfai=fair-fai
delt=delt1+(kp+ki*h/2#)*dfai-(kp-ki*h/2#)*dfai1
delt1=delt'递推变量更新
dfai1=dfai
rk4'解算船舶运动数学模型
fai=x
(2)
x(3)=delt
htx
(2),x(3),i'绘制航向误差及舵令曲线
Nexti
EndSub
6)按F5运行程序,点一下窗体,仿真曲线如图8.2.3所示。
图8.2.3船舶航向自动舵控制系统仿真曲线
7)通过曲线分析,各种性能指标满足要求。
8.3C语言仿真
(1)C语言特点
编程较专业,通用;用户多,随时间推移,编程简化;界面设计复杂;编控制工程软件不如Matlab简单。
(2)C语言发展简史
●1972年,美国贝尔实验室DennisRitchie编写C语言。
●1993年,面向Windows的VC出现。
●目前,TC,BC,VC等根据不同情况选择使用。
(3)C语言程序构成
1)头文件,库函数声明,变量(全局或外部)及数据结构声明、函数声明等。
2)主程序。
3)子程序。
4)工程文件。
(4)应用示例
下面给出例8.2.1用TC2.0实现的重要C语言程序,在该程序中还给出了用第6章介绍的模型实现的风、流干扰子程序。
因该程序是由原系统复杂程序简化得来的,学生用时,要在读懂程序的基础上,改进并调试才能运用。
1)工程文件ship.prj
ship.c主程序
control.c控制程序
noise.c干扰程序
display.c显示程序
2)头文件ship.h
#ifndef__SHIP_H
#define__SHIP_H
#include
#include
#include
#include
#include
#include
#include
#definerho1025.0
#definerhoa1.23
#defineg9.80665
#ifndefDegToRad
#defineDegToRad3.14159265359/180.0
#endif
#ifndefRadToDeg
#defineRadToDeg180.0/3.14159265359
#endif
#ifndefRadToMin
#defineRadToMin3437.746771
#endif
#ifndefPIForth
#definePIForth0.785398163/*PI/4*/
#endif
#ifndefPI
#definePI3.14159265359
#defineDOUBLEPI6.28318530718
#endif
typedefstruct{
floatcl;/*length*/floatbl;/*breadth*/
floatvol;/*displacement*/floatt;/*draft*/
floatsa;/*rudderplanformarea*/floatcbb;/*blockcoefficient*/
floatxc;/*distanceofGtocenter*/floatal;/*projectarea*/
floatu;/*meter/second*/floatIniheading;/*radian*/
}Ship_Struct;
typedefstruct{
floatwind_speed;/*meter/second*/floatwind_angle;/*[0-2*PI]*/
floatcurrent_speed;/*meter/second*/floatcurrent_angle;/*[0-2*PI]*/
}Sea_Struct;
typedefstructdistance_bearing{
doubledistance;/*distanceunit:
nauticalmile*/
doublebearing;/*bearingunit:
radian*/
}DB_Struct;
typedefstructCalculation{
doublexll[6];/*LLmodeldata*/
doublexm[6];/*measuremodeldata*/
floatStime;/*systemtime*/
floatCourse_Err;/*inradian*/
floatTrack_Err;/*innmile*/
floatDisToWp;/*distancetocurrentwaypoint*/
floatCost;/*valueofevaluationfunction*/
floatRspeed;/*realspeed*/
}Cal_Struct;
typedefstructSystem_Set{
intWPNo;/*waypointnumber*/
floatWidth;/*trackwidth*/
floatAA;/*approachdistance*/
}SSet_Struct;
typedefstructSimulation_Condition{
floatWind_D;/*winddirection(inradian)*/
floatWind_S;/*windspeed(m/s)*/
floatCur_D;/*currentdirection(inradian)*/
floatCur_S;/*currentspeed(m/s)*/
floatSpeed;/*shipspeed(m/s)*/
intIndex;/*(nonewdata)Index=0;(newdata)Index=1*/
}Sim_Struct;
typedefstructControl_Data{
intStatus;
floatOrder;/*rudderorder(inradian)*/
floatSet_Course;/*setcoursedirection(inradian)*/
intCwp;/*currentwayp