基于Simulink的RTX实时环境导弹半实物仿真编程技术研究
2018-12-04张培忠宁金贵
张培忠,高 坤,宁金贵
(中国人民解放军63850部队,吉林 白城 137001)
导弹半实物仿真技术是一项涉及多学科、多专业的复杂系统工程,其中稳定、实时、可靠的仿真软件是一个重要组成部分。在导弹半实物仿真过程中,由于在仿真回路中接入了实物部件,要求仿真设备软硬件的时间尺度与实物部件的时间尺度(自然时间尺度)一致,也就要求整个仿真系统是实时运行的。一般半实物仿真系统都以实时操作系统作为运行平台,例如YH-Astar仿真工作站,该工作站是基于Intel处理器和Windows 2000+RTX操作系统,这就要求设计的导弹仿真程序也能够在RTX实时环境中运行。
YH-Astar仿真工作站采用YHSim一体化建模与实时仿真软件,该软件虽然功能强大,但不是通用商业软件,升级维护不便,且不支持图形模块化建模,程序代码兼容性、可移植性不足,导致用户建模、校模、验模效率偏低[1-2]。然而,Matlab/Simulink是目前计算机仿真应用最为广泛的软件,支持图形模块化建模,程序代码兼容性、移植性好,技术资料丰富,便于升级维护,许多专用的仿真系统都支持Simulink模型,方便了用户的使用[3]。从软件功能的通用性、兼容性、完善性等多方面考虑,有必要利用Simulink开发导弹半实物仿真软件[4]。但是,用Simulink开发的仿真程序还不能直接拿到RTX实时环境中运行,需要经过实时性改造和移植,才能获得实时、稳定运行的仿真程序。
1 基于RTX实时环境的程序开发
1.1 RTX实时环境简介
常用Windows系列操作系统不是实时系统,RTX(Real-Time Extension)是美国Ardence公司开发的基于Windows NT/2000/XP操作系统的硬实时扩展子系统。RTX给Windows系统增加一个实时子系统RTSS(Real-Time Subsystem)和实时HAL(Hardware Abstract Level)扩展,以实现硬实时功能。图1为RTX的工作原理图。
RTSS在概念上与其他Windows子系统(如Win32、POSIX等)类似,它拥有自己的执行环境和API(Application Programming Interface),扩展了自己的线程调度机制,RTX-RTSS中执行的程序都具备比Win32程序更高的优先权,包括Windows管理的中断及延时过程调用DPCs等。RTSS还支持 IPC(Inter Process Communication)对象,这些IPC对象可以被RTSS进程和Win32进程操作,从而实现实时进程和非实时进程之间的通信与同步。
RTX HAL扩展起着中断隔离的作用,Windows不能屏蔽RTSS管理的中断,但在RTSS进程运行时,可以屏蔽Windows的中断。RTX HAL还提供高精度的时钟和定时器,时钟分辨率可以达到100 ns,定时器最小周期为1 μs,同时也支持 Windows 的非实时时钟和定时器。RTX HAL的其他特征还有:提供了RTX和Windows之间的软件中断机制、异常处理以及对系统确定性的扩展。
RTX还支持单处理器系统和多处理器系统。在多处理器系统中,RTX可以运行于“共享”方式或“独占”方式。“共享”方式是指RTX与Windows程序共享一个处理器,其他处理器全部由Windows程序占用;“独占”方式是指RTX独占一个处理器,保证了其实时功能。
1.2 RTX应用程序开发
RTX API是基于Win32的应用程序接口,使开发者能够利用Win32开发经验、现有代码、开发工具来编写实时应用程序。Win32和RTSS都支持RTX API。RTX API包含Win32 API的部分函数,称为RTXAPI的函数集。RTX API是为了实时应用而经过仔细挑选的函数集,但不包括Win32的一类函数,如GUI函数,这类函数通常用于实时性要求不高的场合。实际上,那些实时应用不必要的、对确定性执行不适用的Win32函数都没包括在RTX API中。因此,通常采用Win32与RTSS相结合方式开发实时软件,将有实时性要求的事务放在RTSS进程中处理,而将人机界面等对实时性要求不高的事务放在Win32进程中处理,RTSS进程与Win32进程通过共享内存的方式相互沟通,如图2所示。
RTX为用户和开发人员提供了实时系统运行环境(RTX Runtime)和实时系统开发环境(RTX SDK)。用户可以像开发其他Windows应用程序一样,用Visual Studio开发RTX应用程序。安装RTX后,在Visual Studio集成开发环境下,增加开发RTSS软件的应用程序向导RTX AppWizard,类似于MFC AppWizard。用户使用该向导,可定制所需的应用程序框架,包括定时器、中断、事件管理、端口IO及RTSS动态链接库等。用户在该框架基础上添加程序代码,编译链接后即可生成RTX应用程序。
2 基于Matlab/Simulink的仿真建模及代码生成
Matlab/Simulink是国际上仿真领域最常用的商业化计算机工具软件包。它提供了一个图形模块化、动态建模、仿真和综合分析的集成环境,无需用户手工编写大量的程序代码,只要通过简单的图形模块化鼠标操作,就可以构造出复杂的、可靠的、易读的仿真程序,显著提高了仿真程序的开发效率和质量[5]。虽然 Matlab/Simulink没有硬件接口及实时仿真功能,但它的S-函数机制和Real-Time Workshop组件为开发实时仿真软件提供了有效的技术途径。
首先用Matlab/Simulink建立仿真模型,这期间需要编写S-函数,用以实现仿真程序与仿真设备硬件接口之间的联接,并将该S-函数加入到Simulink仿真模型中。Simulink仿真模型设计完成后,通过Real-Time Workshop将仿真模型编译成C语言代码,最后对该C语言代码进行实时性改造[6],再移植到Windows+RTX实时环境中,完成实时仿真程序设计。
2.1 用Simulink仿真建模
Simulink是Matlab产品系列中非常重要的一个组件,是用图形模块化建模、分析和仿真各种动态系统的交互环境,包括连续系统、离散系统和连续离散混合系统。Simulink提供了许多实现不同功能的图形化模块库,每种模块库包含了多种功能模块,用户也可以设计自己的专业模块库并加入其中,以扩充Simulink的功能。由于Simulink采用图形模块化、交互式操作方式,用户建模时只需使用鼠标拖放不同模块库中所需要的功能模块图标,并将它们连接起来,就可以创建仿真模型,从而使复杂、繁琐的仿真模型设计问题简单化。用户还可以把若干个功能块组合成子系统,建立起分层的、多级的复杂仿真模型,使仿真模型的组成结构清晰、明了,逻辑关系易读,提高了仿真建模、校模、验模的效率和质量。
Simulink图形模块化的“编程”方法使得用户从编写繁杂语句代码的劳动中解放出来。但是,创建一个Simulink仿真模型的时候,就等于在编程,必须考虑数值计算的问题。首先,应当选择对指定模型的微分方程求解所使用的最佳算法,Simulink提供了多种微分方程的数值解法,有各自的特点和适用场合,不同的解法通过Simulation/Configuration Parameters页中的求解器(Solver)选项设置。其次,要对模型中的变量进行分析,考虑是否需要进行过零检测,某些变量在过零时会出现不连续状态,如自由下落的物体着地后,会被弹起来,速度会发生跳变,这类变量,如果在动态系统仿真中不对其进行过零检测,很可能会导致不正确的结果。最后,要避免出现代数环,对不能去掉的代数环进行处理。
2.2 编写S-函数
半实物仿真程序需要与仿真设备及实物部件之间进行通迅,Simulink本身不具备这个功能,用户可以通过编写S-函数,来实现仿真程序与硬件接口的联接。
S-函数(System Function)是采用计算机编程语言方式描述的一个功能模块,它是Simulink建模的有力扩充,它提供了增强和扩展Simulink功能的强大机制,同时也是使用Real-Time Workshop实现半实物仿真的关键。在用户使用Simulink建模时,S-函数的使用方法同其他功能模块一样,可以采用Matlab、C、C++、FORTRAN以及Ada等高级语言编写S-函数。
S-函数有两种类型,一种是M文件S-函数,用Matlab语言来编写;另一种是ME X文件S-函数,用C、C++、Ada 或 Fortran 语言编写编译而成。本文采用C语言编写MEX文件的S-函数。C语言编写MEX文件的S-函数是一些符合特定语法结构的回调函数,每个回调函数都对应着一个预先指定的具体任务,各个回调函数在总仿真流程中所处的位置及功能如图3所示。Matlab提供了C语言编写MEX文件的S-函数的模板文件sfuntmpl_doc.c,该文件定义了各回调函数的结构,并有详细注释。用户参考回调函数的注释,依据模板文件中的回调函数结构,用C语言编写MEX文件的S-函数。
2.3 生成C语言代码
Real-Time Workshop(简称RTW)是Matlab的重要组成部分,是一个基于Simulink图形模块化的仿真模型转化成程序代码的工具。用户使用RTW可以直接从Simulink图形模块化的仿真模型生成优化的、可移植的、用户定制的C或Ada程序代码,并根据不同的目标配置生成可以在多种环境下运行的程序。
在用RTW生成程序代码之前,需要对图形模块化的仿真模型进行一些必要的设置。包括:(1)设定仿真模型的内部参数,如各积分项的初始条件等;(2)设定Simulink仿真参数,通过Simulation/Configuration Parameters菜单设置,包括Start time、Stop time、Solver等;(3)设定RTW代码,指定RTW系统目标文件、模板联编文件和联编命令文件。
RTW生成的程序代码不能直接用于Windows+RTX实时环境中,还需要对该程序代码进行实时性改造,再移植到RTX实时环境中。为此,先将RTW生成文件设置为grt.tlc,模板联编文件和联编命令文件保持默认设置。各项参数设置完后,点击“Build”生成C语言代码。生成的C语言代码文件默认保存在 Matlab 安装目录下的 workmodel_grt_rtw 目录下(model为模型名称),包括:model.mk、model.mak、model.bat、model.h、model.c、model_data.c、model_types.h、model_private.h、rt_nonfinite.c、rt_nonfinite.h、rtmodel.h、rtwtypes.h、rtw_proj.tmw。用 VC++ 6.0打开其中model.mak 文件,会创建一个Win32控制台(Win32 Console Application)类型的工程。此工程包括上百个Matlab提供的C源文件和头文件,在安装目录Matlab ROOT twclibsrc下,这些C源文件提供了模型运行中的函数支持,比如仿真运算、积分器等Matlab库函数。工程的主文件为 grt_main.c,它与用户模型无关,也是Matlab提供的,在Matlab ROOT twcgrt目录下。
3 C语言程序代码的实时性改造和移植
利用RTW将Simulink图形模块化的仿真模型转化成了C语言程序代码,这是一种在Win32环境下运行的通用程序代码,还不具备实时性,没有仿真步长度量及推进功能,需要对其进行实时性改造和移植。
3.1 C语言程序代码结构
分析Simulink图形模块化的仿真模型的C语言程序代码(主要是grt_main.c和model.c文件)可以发现,仿真程序的流程依据图4进行的。仿真过程分为三部分:(1)初始化部分,主要由MODEL()、MdlInitializeSizes()、 MdlInitializeSampleTimes()、MdlStart()函数组成;(2)帧循环部分,主要是rt_OneStep()函数,该函数主要包括了MdlOutputs()、MdlUpdate()函数;(3)仿真结束处理部分MdlTerminate()。其中,需要实时处理的部分只有帧循环部分rt_OneStep()函数及其MdlUpdate()函数、MdlOutput()函数,其他的初始化和仿真结束后的数据记录、清理等工作都不需要实时处理。
3.2 构建实时仿真程序
RTX实时程序通常采用Win32进程与RTSS进程相结合的方法(见图2),将需要实时处理的事务放在RTSS进程中,其他部分放在Win32进程中。文献[1]和[2]介绍的半实物仿真程序设计就是采用这种方法,他们首先对RTW生成的模型代码进行实时性分离,将需要实时运行的部分(rt_OneStep()函数及其MdlOutputs()函数、MdlUpdate()函数)放到RTSS进程中,其他部分如初始化、仿真结果记录等放在Win32进程中。但是,这种方法由Win32进程和RTSS进程共同完成仿真,要求Win32进程和RTSS进程共享仿真模型的数据空间,主要是共享SimStruct数据结构。SimStruct是一个非常复杂的数据结构,其封装了仿真模型的所有动态信息,内部有大量的指针变量以及指针嵌套结构。鉴于Win32环境和RTSS环境存储器的编址方式不同,共享的、同一物理存储单元在Win32环境和RTSS环境的逻辑地址不同,因此要实现SimStruct数据结构的共享就非常困难。
新设计的实时性改造方案是:将全部仿真程序(包括初始化、帧循环、仿真停止处理)都放在RTSS进程运行,Win32与RTSS仿真程序及其数据结构无关。Win32进程仅负责共享内存的创建、RTSS进程的载入,负责RTSS仿真过程的控制及仿真结果的显示功能,并通过共享内存向RTSS进程发送控制命令、读取RTSS仿真数据及状态信息;而RTSS进程则独立运行全部仿真程序,并通过共享内存接收Win32进程的控制命令及参数,用定时器控制帧周期,在完成每一帧的计算后,将仿真结果存入共享内存,供Win32进程读取显示。经过实时性改造及代码移植后,仿真程序框架结构如图5所示。
3.3 建立RTSS工程
依据图5的仿真程序结构编制仿真程序。用 VC++ 6.0创建一个RTSS Application类型的工程,在该工程中加入RTW生成的代码文件,将主程序文件替换为Matlab的grt_main.c文件,然后对该文件代码进行修改。修改的内容主要有:(1)在main()函数中加入RtOpenSharedMemory()函数,用于打开由Win32主程序建立的共享内存;(2)调用RtCreateTimer()和 RtSetTimerRelative()函数,创建定时器并设置时间间隔(即帧周期);(3)编写定时器回调函数代码,将单步仿真程序rt_OneStep()移到该函数中;(4)去掉原代码中帧循环部分,改为检查共享内存中控制命令字节程序;(5)删除原程序中有关显示及数据记录的函数,如printf()、rt_StartDataLogging()、rt_UpdateTXYLogVars()、rt_StopDataLogging()等。该工程编译连接后生成可执行文件,扩展名为.rtss。
3.4 建立Win32工程
用VC++ 6.0建立Win32 Console 或MFC类型的Win32工程,加入以下程序代码:(1)调用 RtCreateSharedMemory()函数创建共享内存,并进行共享内存的初始化,如设置仿真帧周期等;(2)通过CreateProcess()函数运行RTSSrun程序,进而载入并运行由RTSS工程生成的.rtss程序;(3)查询共享内存的RTSS状态字节,等待RTSS进程的“就绪”状态,然后写“允许仿真”命令;(4)进入帧循环阶段,读共享内存,存储、显示仿真过程的有关数据;(5)设置“结束仿真”命令;(6)仿真结束,存储数据,调用RtUnmapSharedMemory()函数释放共享内存。
4 编程实例
以某型导弹的飞行弹道实时仿真为例,编制基于RTX实时环境的导弹仿真程序,验证上述方法的可行性。具体步骤是:(1)用Simulink对导弹飞行弹道进行图形模块化仿真建模;(2)用RTW工具生成C语言程序代码;(3)编写S-回调函数;(4)对C语言程序代码进行实时性改造,并移植到RTX实时环境中;(5)在程序中增加帧周期测量代码;(6)在RTX实时环境下运行并分析运行结果。采用的软件版本为Matlab 7.0/Simulink4.0。
4.1 导弹飞行弹道图形模块化仿真建模
基于Matlab/Simulink的导弹质心动力学仿真模型见图6所示,导弹绕质心转动力学仿真模型见图7所示,为了缩短文章篇幅,本文省略了导弹质心运动学仿真模型、导弹绕质心转动的运动学仿真模型、几何关系方程仿真模型、导弹空气动力学仿真模块。将上述各个子模块按输入/输出信号的对应关系连接起来,构成导弹飞行弹道方程总的仿真模型,见图8所示。
4.2 生成C语言代码及实时性改造和移植
打开Matlab的 “Configuration Parameters”属性页,将“Real-Time Workshop”选项卡中的“RTW system target file”设置成“grt.tlc”,点击“Build”按钮,则开始生成导弹飞行仿真模型的C语言程序代码,并编写S-回调函数。
按照本文3.2、3.3、3.4部分介绍的方法,对代码进行实时性改造和移植。本实例Win32程序采用的是MFC类型的应用程序,在其中定义共享内存数据结构。Win32工程和RTSS工程编译连接后,分别生成RTmain.exe和RTX.rtss文件。将RTX.rtss拷贝到RTmain.exe所在的目录,执行RTmain.exe程序,即可载入并运行仿真程序。
4.3 实时仿真程序的运行结果
RTmain.exe程序的运行结果见图9和图10。图9左右侧图形分别是该程序运行后得到的“V-t”和“y-t”曲线,图10左右侧图形分别是单帧运行时间和帧周期图线。从程序运行结果可见:(1)对于导弹飞行弹道的解算,实时仿真程序的单帧运行时间仅30 μs左右,运行速度非常快,说明实时仿真程序的代码质量较高;(2)帧周期时间非常准确,通常情况下偏差在0.2 μs以内;(3)用其他进程进行抗干扰测试,例如在运行仿真程序的同时还播放视频,仿真帧周期也很稳定,统计的最大偏差为0.7 μs。
5 结论
使用Matlab/Simulink/RTW软件工具进行图形模块化设计仿真模型,并将图形模块化仿真模型转换成C语言程序代码,对其进行实时性改造和移植,获得在Windows+RTX实时环境下运行的仿真程序。通过研究得出以下结论:
1) Simulink图形模块化建模功能简化了编程过程,提高了仿真建模、校模、验模的效率和质量,便于开发复杂系统的实时仿真程序;
2) 对图形模块化仿真模型转换成C语言程序代码,并对C语言程序代码进行实时性改造和移植后,仿真程序可以在RTSS中实时、稳定、可靠运行;
3) 由Win32程序监控仿真过程,不参与实时仿真计算,与实时仿真程序RTSS之间分工明确,数据耦合简单,保证了RTSS中仿真模型可靠、实时运行,且抗干扰能力强。