从1993年起,Flexsim软件产品就进入了仿真软件市场并且建立了自己的咨询业务。经过十多年在仿真行业的经验积累以及高新软件技术的应用,我们已经开发出了一个全新的面向对象的仿真建模工具Flexsim。它是迄今为止世界上惟一一个在图形建模环境中集成了C++IDE和编译器的仿真软件。在这个软件环境,C++不但能够直接用来定义模型,而且不会在编译中出现任何问题。这样,就不再需要传统的动态链接库和用户定义变量的复杂链接。Flexsim有很广阔的应用范围,还能应用在更高层次的仿真工程上。欢迎大家使用Flexsim,它一定会令你耳目一新!
Flexsim能应用于建模、仿真以及实现业务流程可视化。下面我们简单地介绍一下Flexsim仿真软件。 一、建模
Flexsim应用深层开发对象,这些对象代表着一定的活动和排序过程。要想利用模板里的某个对象,只需要用鼠标把该对象从库里拖出来放在模型视窗即可。每一个对象都有一个坐标(x,y,z)、速度(x,y,z),旋转以及一个动态行为(时间)。对象可以创建、删除,而且可以彼此嵌套移动,它们都有自己的功能或继承来自其他对象的功能。这些对象的参数可以把任何制造业、物料处理和业务流程的快速、轻易、高效建模的主要特征描述出来。 下图是一个仓库的模型:
Flexsim中的对象参数可以表示几乎所有存在的实物对象。像机器、操作员、传送带、叉车、仓库、交通灯、储罐、箱子、货盘、集装箱等等都可以用Flexsim中的模型表示,同时数据信息也可以轻松地用Flexsim丰富的模型库表示出来。 层次结构
Flexsim可以让建模者使模型构造更具有层次结构。在组建客户对象的时候,每一组件都使用了继承的方法,在建模中使用继承结构可以节省开发时间。Flexsim可以使用户充分利用Microsoft Visual C++的层次体系特性。 用户化
目前在市场上,还没有其他任何仿真软件能像Flexsim这样有更多的用户化设定。对使用者来说,软件的每一个方面都是开放式的。对象、视窗、图形用户界面、菜单、选择列表和对象参数等都是非常直观的。你可以在对象中根据自己的想法改变已经存在的代码,删除不需要的代码,甚至还可以创建全新的对象。值得一提的是,不论是你设定的还是新创建的对象都可以放入库中,而且可以应用
在别的模型中。最重要的是,在Flexsim中可以用C++语言创建和修改对象,同时,利用C++可以控制对象的行为活动。Flexsim的界面、按钮条、菜单、图形用户界面等都是由预编译的C++库来控制的。 可移植性
由于Flexsim中的对象都是开放的,因此这些对象可以在不同的用户、库和模型之间进行交换,同时结合对象的高度可自定义性,可以大大提高建模的速度。当用户自定义的对象加入库中时,就可以非常方便的在别的模型中使用该对象。由此可见,用户化和可移植性扩展了对象和模型的生命周期。 二、仿真
Flexsim中有一个效率非常高的仿真引擎,该引擎可同时运行仿真和模型视窗(可视化),但可以通过关闭模型视窗来加速仿真的运行速度。同时当仿真运行时,利用该引擎和flexscript语言可以改变模型的部分属性。 下图是仿真原材料的传输过程:
Flexsim还可以用试验的形式来仿真假定的情节,而且它可以自动运行并把结果存在报告、图表中。这样我们可以非常方便地利用丰富的预定义和自定义的行为指示器,像用处、生产量、研制周期、费用等来分析每一个情节。而且也很容易将结果导入到别的应用程序像Microsoft Word和Excel等,利用ODBC(开放式数据库连接)和DDEC(动态数据交换连接)可以直接输入仿真数据。 三、可视化
如果一幅图能够表达上千的文字,那么Flexsim的虚拟现实动画以及模型浏览窗口就表达了无限的容量。Flexsim把所有最新的虚拟现实博奕图形整合在个人计算机上。Flexsim中有可以直接导入3DS (3D Studio), VRML,3D DXF and STL等类型文件的选项,而其他仿真软件中没有这项功能。Flexsim内置了虚拟现实浏览窗口,可以让用户添加光源、雾以及虚拟现实立体技术。用户定义的“Fly-Throughs”可以被定义为艺术模型状态显示出来。AVI文件可以通过Flexsim的AVI录制器快速生成。任何模型都能被录制、拷贝到CD,以及发送到任何人的实时查看器中。 七、输入和输出
1)输出:Flexsim具有强力的商务图表功能,海图(Charts)、饼图、直线图表和3D文书能尽情地表现模型的情报,需要的结果可以随时提出。Flexsim的open architecture允许用户连接OBDC数据源、进行读和写,可以实时的连
接Word和Excel。对于Flexsim模型,为便于在Flexsim系统之外观看和演示,系统提供了AVI转换功能:可以将模型的3D效果转换成AVI格式。
2)输入:Flexsim的模型中的3D图形可以是所有符合OpenGL规范的3D图形,比如:*.wrl; *.3ds; *.dxf; *.stl等。 八、应用领域
Flexsim是一款建模应用软件,可以用于对任何商业流程,包括制造、物流、管理等等的仿真和可视化。尤其适合于流水线(研发、生产制造、销售展示、工程规划、生产管理分析)、物流设备(研发、生产制造、销售展示、工程规划、性能分析)、物流与配送(工程布局规划、性能分析)等。
Flexsim的理念就是柔性。无论是建模对象、视图、图形用户界面,还是你能想到的许许多多其他构件,在Flexsim中都可以完全用户化。
1 Flexsim系统仿真软件概况
Flexsim 是PC Base的数字虚拟企业的仿真系统,来建立各种经营、管理、制造等模型,并且可在微软公司的Windows 2000、Windows XP、及Vista 等不同作业平台上执行的全窗口化3D专业仿真软件。Flexsim是新一代的面向对象的仿真建模工具,它是迄今为止世界上唯一一个在图形建模环境中集成了C++IDE和编译器的仿真软件。在这个软件环境,C++不但能够直接用来定义模型,而且不会在编译中出现任何问题。这样就不再需要传统的动态链接库和用户定义变量的复杂链接。它能使决策者轻易地在个人电脑中建构及监控任何工业及企业的分散式流程。透过Flexsim我们可以率先找出未来工业及企业流程的模式。Flexsim基础架构设计不只是要满足使用者现今的需求,其架构的概念更是为了企业的未来而准备。
Flexsim就是帮助工程师,经理和决策者形象化地在动态三维
虚拟现实环境中检测新提议的操作,流程或是系统。这对于创建那些可能出现崩溃,发生中断或是产生瓶颈的复杂系统是必不可少的。通过预先创建系统模型,可以考察各种假设的场景,同时不会产生改变实际系统时所面临的中断,成本和风险。
Flexsim不仅已应用于工业自动化仿真、物流中心配送仿真、交通运输仿真、交通流量管制仿真、医疗管理研究、医院动线规划仿真等民用工程,也已经应用于先进国防战略仿真、航天制程仿真等大型研究方向。
主要的应用领域: 制造业:
半导体芯片制造、肉食包装工厂中的牛肉处理、钢铁制造、果酱成品的罐装,标签,包装,发货、电子器件制造、 仓储和配送:
港口集装箱船只的装卸、配送中心操作、订单取货、传输带系统和布局、物流货架、传送带和堆垛机。 运输:
高速路交界处的交通流、火车站中人群和列车的移动、河流中驳船的往来穿梭、国际边防路口的交通堵塞 其他:
矿石开采和加工、快餐店中食物准备和客户服务、参观者在娱乐场所内的活动、喷气式飞机引擎的拆卸,翻新和更换、医院中病人和食物的处理、共享的网络存储器中数据的流动、银行处理中
心中支票的处理。
2 Flexsim仿真功能
2.1 Flexsim建模的功能
1) Flexsim具有离散型和连续型的混合建模功能。软件本身更多的是离散型仿真方面应用,但它支持连续型生产建模,它有专门的流体部件库,有很多应用于炼钢厂、塗料生产厂及石油输送的成功案例。
图-1 Flexsim连续型生产模型之一
2) Flexsim提供平面与三维建模窗口,可以直接将AutoCAD的平面布置图导入建模窗口,可完全遵循平面布置图的距离关系建立平面模型,平面模型只要换一个窗口,或换一个角度就是三维模型,建立二维模型的同时,同步自动生成三维模型,不需要将二维模型转为三维模型的操作。同样,也可以直接在三维建模窗口建立模型,二维模型同步自动生成。二/三维建模完全同步关联。
图-2 AutoCAD的平面布置图上建模
3) Flexsim提供的部件具有相当的柔韧性,部件的参数设定可适应于不同层次的使用者,对于刚入门的使用者,Flexsim提供了制造业和物流业常见策略,用户只需要选择和修改数据,就可以实现先进先出、先进后出、随机出入、百分比出入、统计概率出入、最长队列出入、最短队列出入、按品种出入、按标签出入等出入库策略,无需编程。对于使用熟练者,可以直接用C++编程,实现更复杂的有特殊需求的出入库策略,每个部件都有C++编程接口。
4) Flexsim用拖放图形方法建立模型,Flexsim提供有固定类部件库,执行类部件库,流体类部件库,以及用户部件库。建模时将相应的部件拖放到模型窗口的指定位置。Flexsim允许用户开发自己的部件并建立自己的部件库,对于使用熟练者用户可以手工编制代码来建模。
5) Flexsim具有完全的C++面向对象(object-oriented)性。 6) Flexsim所有模型均建立和运行于耀眼的彩色3D中 ,采用了与先进的视频游戏相同的虚拟现实技术。
--通过简单的点击和拖动,可从任何角度观看模型。 --通过“飞行漫游模块”,用户可随镜头漫游整个模型运行状况。可以任意使用全景、局部放大、侧面、反面等漫游技巧。
--多个窗口可以设置不同的视角,仿真运行时,以便同时观察系统的各部分。实现模型的规模化展现。
图-3 大规模模型全景
模型的第二层情景 模型的第一层情景
7) Flexsim能利用包括最新的虚拟现实图形在内的所有PC上可用的图形。如果是扩展名为3DS、VRML、DXF和STL的3D立体图形文件的话,可以直接导入Flexsim模型中,模型
中的任何部件或背景都可以通过导入图片或立体图形文件的方法替换部件或背景的图片或立体图形。
图-4 Flexsim模型
8) Flexsim是世界唯一的在图形的模型环境中应用C++ IDE和编译程序的仿真软件。定义模型逻辑时,可直接使用C++,而且可立刻编译到 Flexsim 中。因为Flexsim 具有高度的开放性和柔韧性,所以能为几乎所有产业定制特定的模型。 9) 有Flexsim版本3.0的中文版。最新版本没有中文版,是英文版,但软件本身在建模环境中能输入中文字符,在仿真运行环境中能以标签或表格形式显示中文信息等。
图-5 Flexsim最新版报表中显示的中文信息 10)
Flexsim尽管能同时打开多个窗口,但模型是在集成统
一的开发环境中,这种开发环境具有两种表现形式,一种
是3D或2D的视景环境,一种是树结构的纯文本环境。它是同一个东西,不同表现形式,方便建模和调试。Flexsim建模环境同时支持仿真模型的运行、调试等功能。 11)
Flexsim全部模块是在Windows系列版本的操作系统上
运行,包括Windows 2000各版本、Windows XP各版本、Windows 2003各版本以及Windows Vista各版本。软件操作风格上具备典型的Windows操作风格,具备菜单、工具条以及复制、粘贴等操作。 12)
Flexsim提供较为详细的通用格式的技术帮助文件(文
件格式为*.HTML)。在软件中也有帮助菜单,有查询功能。 13)
开放性和互联性是Flexsim体系架构的一个特点。
Flexsim完全与C++ 相结合,用户可以随时修改Flexsim满足其特定需求,而不必学习专有代码。Flexsim能够链接到任何ODBC数据库(像Oracle.or Access.)和大众数据结构文件(如text, Excel, 或 Word)。创时能公司能够提供仿真与用户异构平台的接口。 2.2 Flexsim的分析优化的功能
1) Flexsim建立模型的所有资源是对象(Objects),对象可以是产品,模型,图表,记录,库,GUI,甚至是应用程序本身。而Flexsim的对象都可以向定制的用户公开,建模人员可以自由地操作部件、图形用户界面、菜单、选择列表和部件参数,可以在部件里增加自定义的逻辑、改变或删
掉既存的编码。所以当然允许用户根据实际需求来自定义统计分析报表。Flexsim在仿真过程中,能根据仿真进度动态显示2D和3D报表数据。
图-7 3D报表实时显示报表数据
2) Flexsim仿真的统计分析数据除在仿真运行环境内显示外,可以直接导出EXCEL和文本文件形式的报表,提供数据库以自定义表形式储存报表。
3) Flexsim在模型运行过程中记录了所有设备的所有状态(工作、等待、阻塞、故障等)的时间数值,以及设备加工产品的个数,用户可以自由组合和输出由这些数据组成的报表。当然提供包括设备利用率、单条模型生产线的加工总能力、单个设备的加工能力、设备状态的时长及时间比例、模型瓶颈分析等统计分析功能。
图-8 Flexsim提供的设备状态饼图
4) Flexsim提供平面和立体饼图、柱状图、折线图、海图、以及甘特图等多种图形图表,支持数据与图表混合的统计报表(如上图)。
5) 优化模块Optquest完全集成于Flexsim中,Optquest用于仿真优化,即找寻一组最佳的参数值(或决策变量值),以使得目标函数最优,在仿真模型中执行优化功能。由于在Flexsim中除了模型本身外、模型中的每个部件都提供了编写VC++程序的接口,所以当然支持嵌入自定义的优化算法。 2.3 Flexsim的其它功能
1)层次结构 Flexsim可以让建模者使模型构造更具有层次结构。建立模型的时候,每一部件都使用继承的方法(即采用继承结构),可以节省开发时间。Flexsim可以让用户充分利用Microsoft Visual C++的层次体系特性。 2)量身定制 软件的所有可视窗体都可以向定制的用户公开。建模人员可以自由地操作部件、视窗、图形用户界面、菜单、选择列表和部件参数,可以在部件里增加自定义的逻
辑、改变或删掉既存的编码,也可以从零开始完全建立一个新的部件。不论是设定的还是新创建的部件都可以保存到部件库中,而且可以应用在其它模型中。最重要的是,在Flexsim中可以用C++语言创建和修改部件,同时,利用C++可以控制部件的行为活动。Flexsim的界面、按钮条、菜单、图形用户界面等都是由预编译的C++库来控制的。
3)可移植性 因为Flexsim的部件是向建模者公开的,所以部件可以在不同的用户、库和模型之间进行交换。可移植性与量身定制相结合能带来惊异的建模速度。定制的部件保存在部件库中,建模时,只要从部件库中拖放相应部件,就能在新模型中再现这些部件。可移植性与量身定制延长了部件和模型双方的生命周期。
4)仿真实验 Flexsim 能一次进行多套方案的仿真实验。这些方案能自动进行,其结果存放在报告、图表里,这样我们可以非常方便地利用丰富的预定义和自定义的行为指示器,像用处、生产量、研制周期、费用等来分析每一个情节。同时很容易的把结果输出到象微软的Word、Excel等大众应用软件里,利用ODBC(开放式数据库连接)和DDEC(动态数据交换连接)可以直接对数据库进行读写数据。
5)统计分析 自带随机变量发生器,能容易地建立近似于现
实系统的数学模型。提供了25种以上的统计分布函数,集成了ExpertFit,具有拟合统计分布函数的功能。
技术支持:Flexsim中国唯一代理商 北京创时能科技发展有限公司
第五章 Flexsim相关的概念及关键技术研究
5.1 Flexsim软件介绍
Flexsim是由美国的Flexsim Software Production公司出品的,是一款商业化离散事件系统仿真软件。Flexsim采用面向对象技术,并具有三维显示功能。建模快捷方便和显示能力强大是该软件的重要特点。该软件体供了原始数据拟合、输入建模、图形化的模型构建、虚拟现实显示、运行模型进行仿真试验、对结果进行优化、生成3D动画影像文件等功能,也提供了与其他工具软件的接口。图5-1是Flexsim软件及其构成模块的结构图[7]。
ExpertFit等拟和分布工具 输入建模
Flexsim仿真软件 模型建立与调试 模型有效性确认 运行仿真试验 3D的可视化 结果动态显示 生成影像文件 系统仿真 运行仿真试验
Microsoft Visual C++.NET Excel等可以用作统计分析的工具 结果统计分析
图5-1 Flexsim功能结构图
Flexsim提供了仿真模型与ExpertFit和Excel的接口,用户可以同过ExperFit对输入数据进行分布拟合,同时可以在Excel中方面地实现和仿真模型之间的数据交换,包括输出和运行模型过程中动态修改运行参数等。另外该软件还提供了优化模块Optquest,增加了帮助迅速建模的Microsoft Visio的接口。
5.1.1 Flexsim软件的主要特点
Flexsim仿真软件的特点主要体现在采用面向对象技术,突出3D显示效果,建模和调试简单开放方便,模型的扩展性强,易于和其他软件配合使用等方面。
(1) 基于面向对象技术建模
Flexsim中所有用来建立模型的资源都是对象,包括模型、表格、记录、GUI等。同时,用户可以根据自己行业和领域特点,扩展对象,构建自己的对象库。面向对象的建模技术使得Flexsim的建模过程生产线化,对象可以重复利用,从而减少了建模人员的重复劳动。
(2) 突出的3D图形显示功能
Flexsim支持OpenGL技术,也支持3ds、wrl、dxf和stl等文件格式。因此用户可以建立逼真的模型,从而可以帮助用户对模型有一个直观的认识,并帮助模型的验证。用户可以在仿真环境下很容易地操控3D模型,从不同角度、放大或缩小来观测。
(3) 建模和调试的方便
建模过程中用户只需要从模型库中拖入已有的模型,根据模型的逻辑关系进行连接,然后设定不同对象的属性。建模的工作简单快捷,不需要编写程序。
(4) 建模的扩展性强
Flexsim支持建立用户定制对象,融合了C++编程。用户完全可以将其当作一个C++的开发平台来开发一定的仿真应用程序。
(5) 开放性好
提供了与外部软件的接口,可以通过ODBC与外部数据库相连,通过socket接口与外部硬件设备相连,与Excel、Visio等软件配合使用。
5.2 Flexsim的一些重要概念
Flexsim是目前国内最新的仿真软件,关于该软件的资料和使用经验还很少。作者是在不断的摸索中学习的,所以希望本文能对其他人有一定的借鉴。要完全掌握好Flexsim,并将其用到我们的工作、学习和研究当中,理解该软件的一些重要概念和思想是很重要的,本节针对集装箱码头建模仿真中用到的技术做一个梳理。
5.2.1 面向对象的思想
相对于目前的一些仿真软件(如Witness, eM-Plant等),Flexsim是采用面向对象思想和技术开发的,其本身更是用C++语言实现。严格地说该仿真软件包括了两部分,仿真软件和后台支持环境VC++.NET。由于C++是一种面向对象的语言,所以使用Flexsim软件,从用户用于系统建模,或是做一些二次开发,这些工作都有面向对象思想的体现。可以这样说,没有领会面向对象的思想,就不能完全发挥Flexsim软件本身的特点,也就不能用其实现用户的目的。使用Flexsim软件的用户需要对C++语言有一定程度的熟悉。本节主要是解释Flexsim中所特有的一些面向对象思想,而不涉及面向对象语言的解释(关于C++语言的知识请查看相关书籍)。
对象(Object)的概念在Flexsim软件中无处不在,我们先直观的感受一下。软件的运行界面左边是一个常用的对象库(如图5-1)。库中的各种部件就是有特定功能的对象,这些对象是软件本身自带的,使用这些基本的部件对象用户可以完成大多数的仿真工作。我们使用Processor来解释一下对象的概念:我们日常所见的任何具体事物都可看作是对象,这里Processor就是一种设备,它的作用就是对经过他的物件进行一些加工,即改变物件的状态。这里我们可以将其当作现实中的设备,如机床等。
图5-1
这里我们借用C++程序设计语言中的对象的概念。对象是类的实例,类是对现实对象的抽象。类中包含了对象的数据(相当于现实对象的状态),以及对象的方法(相当于现实对象用来处理外界所给信息的方法)。对象封装了属性和方法,进一步到Flexsim中,对于软件中可用的库对象,他们本身有自己的属性(如颜色,尺寸,位置等),还有处理物件的方法。在使用软件的过程中,我们完全可以以人们平时的思维方式来思考,而无须过多的抽象化,这也就是面向对象方法的优点。
5.2.2 Flexsim的对象层次结构
面向对象方法的一个优点是类与类之间可以有继承关系,对象的继承性给我们提供了更大的柔性来扩展我们自己的对象,即衍生出新的对象。在Flexsim中我们可以充分利用继承性来开发我们自己的对象,而软件本身也给用户提供了这样的机制。Flexsim本身的库对象是高度抽象化的,具有很强的通用性,几乎涵盖了仿真中可能遇到的所有对象。这些对象之间有一定的继承关系,他们之间存在着逻辑关系。下图(图5-2)是Flexsim中对象的层次结构。
FlexsimObject FixedResource Dispatcher Navigator NetworkNode Source Queue Sink Conveyor Rack Reservoir FixedSourceTemplate Processor TaskExecuter NetworkNavigator CraneNavigator Operator Transpoter Crane ASRSvehicle UserDefine UserDefine Combiner Separator 图5-2
从类的派生关系图中我们可以对Flexsim中各种对象的逻辑关系一目了然。对象库中的对象分为两种,一种是从FixedResource中派生下来的,另一种是TaskExecuter中派生下来的。通过分析我们不难发现,从FixedResource中派生来的对象有一个共同的特点,其本身是不会运动的,他们的作用只是产生或消除物件、存储物件、加工物件等等;从TaskExecuter中派生的对象,其本身是可以运动的,其作用是将物件从一个地点运送到另一个地点。
当现有的库对象不能满足用户的需要时,用户就需要创建自己的对象。Flexsim为用户提供了这样一种机制——用户可以定制自己的库对象。在对象层次图中,我们看到有两个虚线框,这表示用户可以从FixedResource和TaskExecuter中派生出自己的对象。Flexsim的早期版本中从这两个类中派生新的对象比较复杂,最新的3.06版中增加了BasicFR和BasicTE类,使用户的开发工作更容易。后面的章节中将具体介绍怎样来实现一个新对象的定制。 5.2.3 节点和树
在介绍树结构之前,我们先来了解Flexsim中节点(node)的概念。 节点是树结构的最基本的组成单元,他们组成了链接的层次。所有的节点都有一个文本缓冲区,用来保存节点的名字。节点可以是其他节点的容器,可以是用来定义一个对象属性的关键字,或是拥有一个数据项。属于一个节点的数据项类型可能是:数值(number),字符串(string),对象(object),或指针(pointer)。
下面列出FLexsim中不同类型的节点标志: 标准(Standard):
对象(Object):
属性/变量(Attribute/Varibale):
函数(Function(C++)):
函数(Function(FlexScript)):
用户可以在对象的树结构中任意地操作节点,例如增加节点,删除节点,改变节点所包含的值等。含有对象数据(Object)的节点可能包含有节点的子列表。含有对象数据的节点称之为对象节点。当你单击一个对象节点
时,你会看到在节点的左边有一个大于号(>)。
单击>将打开对象数据的树分支。如果一个节点包含子节点,可以按下+按钮来展开。如果
一个节点包含对象数据,可以按下>来展开。
下图(图5-3)展示了一个队列(Queue)展开的对象数据树。
图5-3
树结构(tree)是一种很常用的数据结构。Flexsim仿真模型中的对象,或对象中的属性和方法节点等都是树结构;用户甚至可以直接在树结构中操作对象。在Flexsim中有两个主要的对象类型:模型(Model)或仿真对象(Simulation Object)和视图对象(View Object)。两种类型都有对象数据树,包含了属性和行为控件。一个对象节点的对象数据树中的节点可以作为属性、变量或成员函数。也有只是作为简单的容器来包含节点以达到组织的目的。 5.2.4 任务序列
任务序列(Task Sequences)是Flexsim仿真软件中的核心机制。各种复杂仿真的实现很大程度取决于怎样实现任务序列。前面介绍了Flexsim中有两种对象,一种是派生至FixedResource的静态对象(即对象本身不运动);另一种是派生至TaskExecuter的动态对象(即对象本身可运动)。如果用户建立的系统模型全部使用了静态对象,那么就不需要任务序列的机制,但是这种情况几乎没有。使用动态对象搬运物件,对象怎样运动,实现什么样的功能等,这就需要任务序列来控制。
任务序列是由TaskExecuter执行的一组命令序列。这里TaskExecuter涵盖了所有派生自他的动态对象,如Operators,Transpoters,Crane,ASRSvehicle,Robots,Elevators以及其他可运动的对象。图1-4表示一个任务序列,该任务序列有多个任务组成。
Simulation Time
P1 P2 Task1 Task2 Task3 Task4 … P1: Priority Value P2: Preempt Value
图1-4
Flexsim中为用户提供了功能齐备的任务类型。常用的任务序列有:TASKTYPE_TRAVEL、TASKTYPE_LOAD、TASKTYPE_UNLOAD、TASKTYPE_TRAVELTOLOC等。不同的任务序列有不同的设置参数,用户可以根据需要在使用的时候查询帮助文档。 5.2.4.1 默认任务序列
FixedResource为了将物件(item)移至下一个站点(station),有一个创建任务序列的默认机制。FixedResource对象的参数对话框中一个通用的“Flow”选项页,选择其中的“Use Transport”复选框,这样就可创建默认的任务序列。对于Processor对象,还可以自动创建对Setup time/Process time/Repair operation的任务序列。
当仿真运行时,这些自动创建的任务序列就会传递给与其中心端口相连的动态对象来执行。这里给个简单的例子说明。假设用户选择了Queue对象参数对话框的“Flow”选项页中的“Use Transport”复选框,当系统运行时,产生了如下任务序列:
P1 P2 Travel Load Break Travel Unload 当Operator收到该任务序列时,顺序地执行任务序列中的每个任务,执行过程如下:Operator先移动到Queue处(Travel);接着拿起物件(Load);然后移动到下一个站点处(Travel);最后放下物件(Unload)。
在仿真运行的任意时刻,一个TaskExecuter只能执行一个任务序列,而此时FixedResource可能创建了许多任务序列,这些未执行的任务序列被放置在缓存队列中等待执行。
5.2.4.2 定制任务序列
一般情况下,默认的任务序列就可以满足仿真要求。有时候用户需要为某些特定的工艺、多个设备的组合操控灯定制任务序列。这里分三种介绍定制任务序列,第一种是创建最简单的、只分配给一个对象执行的任务序列;第二种是由多个对象协同作业的任务序列。 定制简单任务序列
使用3条命令来创立任务序列,命令执行的顺序如下: createemptytasksequence(…); inserttask(…);
dispatchtasksequence(…);
从函数名就可以看出创建任务序列的过程。首先创立一个空的任务序列,然后在此任务序列中插入具体的任务,最后发布该任务序列。我们举个简单的例子,叉车运动到集装箱旁边,然后装载集装箱。在这个过程中,涉及了两个任务:运动(TASKTYPE_TRAVEL)和装载(TASKTYPE_LOAD)。具体实现如下:
fsnode* new_ts = createemptytasksequence(forklift, 0, 0);
inserttask(new_ts, TASKTYPE_TRAVEL, station);
inserttask(new_ts, TASKTYPE_LOAD, item, station, 2); dispatchtasksequence(new_ts);
这里叉车(forklift)是任务序列的执行者,我们为其创建了一个新任务序列(new_ts),在此任务序列中插入具体的任务(TRAVEL/LOAD),最后发布任务序列。
我们在创建新任务序列时,createemptytaskseqence函数的第一个参数forklift可以是该任务序列的执行者,或者是Dispatcher对象。关于Dispatcher对象的作用下一小节有具体的介绍。后两者参数决定了该任务序列的优先级别,我们可以根据任务的紧急程度来定义任务序列的执行顺序。
Inserttask函数插入具体的任务类型。第一个参数表示该任务所属的任务序列。前面提过不同的任务类型有着不同的代码,以及不同的参数选择。这些参数分别是:Task Type/involved1/involved2/var1/var2/var3,有些参数是选择性的,这要根据任务类型来决定。这里以TASKTYPE_LOAD为例,图1-5表示了不同参数的意义。用户可以根据所示规则查询具体的任务的参数选项。
P1 P2 TRAVEL LOAD Task Type: LOAD Involoved1: bject to load item Involoved2 : object to load from station Var1 : output port 2 Var2 : 0 (默认值) Var3 : 0 (默认值)
图1-5 任务Load的参数含义
协同作业的任务序列
协同作业的情况有很多,比如叉车作业需要一个司机来操控,或者一件物品需要两个人来同时搬运等。在Flexsim中叉车、人都是可运动对象,要实现协同作业的任务序列相对于只对一个对象创建任务序列要复杂许多。我们以叉车和司机的协同工作为例来说明怎样实现协同作业的任务序列。
我们先来分解任务的执行过程:1)人运动到叉车上(Travel);2)人进入驾驶室(这里是叉车的动作)(Load);3)叉车运动到指定地点(Travel);4)叉车装载货物(Load);5)叉车运动到卸载点(Travel);6)卸载货物(Unload)。图1-6是叉车和人的任务序列。 Forklift
P P Wait Load Travel Load Travel Unload OperatorP P Travel to forklift Wait
图1-6 协同任务序列
从图中可以看出,叉车在人到达之后才执行任务,人进入叉车之后就随着叉车一起完成叉车的任务。人的任务序列中只有一个任务,其他时间不做任何事情。
在Flexsim中实现的代码要复杂一些,调用的函数与前面所讲的函数不同。涉及的函数主要有:
createcoordinatedtasksequence(…); insertallocatetask(…); insertproxytask(…); insertsynctask(…);
insertdeallocatetask(…);
dispatchcoordinatedtasksequence(…);
一个协同作业的任务序列的定制是很复杂,也是很容易出错的。在开始实现之前必须分析清楚作业的过程。对于前面人操控叉车的例子我们已经将作业流程分析清楚了,下面是具体的实现,我将每个函数的功能写在程序的注释当中。
//创建协同任务序列
fsnode * myts = createcoordinatedtasksequence(operatorteam); //为每个执行对象分配任务
int opkey = insertallocatetask(myts, operatorteam, 0, 0); int forkliftkey = insertallocatetask(myts, forkliftteam, 0,0); //人的分派任务序列
int traveltask = insertproxytask(myts, opkey, TASKTYPE_TRAVEL, forkliftkey, NULL); insertsynctask(myts, traveltask); //叉车的分派任务序列
insertproxytask(myts, forkliftkey, TASKTYPE_MOVEOBJECT, opkey, forkliftkey); insertproxytask(myts, forkliftkey, TASKTYPE_TRAVEL, loadstation, NULL); insertproxytask(myts, forkliftkey, TASKTYPE_LOAD, item, loadstation);
insertproxytask(myts, forkliftkey, TASKTYPE_TRAVEL, unloadstation, NULL); insertproxytask(myts, forkliftkey, TASKTYPE_UNLOAD, item, unloadstation); //释放分派的任务序列
insertdeallocatetask(myts, forkliftkey); insertdeallocatetask(myts, opkey); //发布协同任务序列
dispatchcoordinatedtasksequence(myts);
5.2.4.3 对象Dispatcher及任务序列的分配规则
现在考虑一种较为复杂的情况:有两个Queue对象用于存放物件,三个Operator对象用于搬运物件;三个Operator是自由的,没有被分配给固定的Queue,那么怎样来有效地调用这三个Operator呢?此时就要用到Dispatcher对象。
Dispatcher用来控制一组Transporter或Operator。任务序列从一个静态对象发送到Dispatcher,然后Dispatcher来调配这些任务序列分配给与其输出端口相连的动态对象。动态对象接收到任务序列后执行相应的命令序列。
Dispatcher对象的功能就是将任务序列进行队列存储和发送任务序列。根据用户建模的逻辑,任务序列可以被排队等待或是立即传送个相应的对象。Dispatcher的参数设置对话框只有两项,当接收到一个任务序列时,调用“Pass To”函数。顾名思义,该函数将任务序列发送给接收对象;如果该函数返回值是0,即该任务序列不能被立即分配,则根据“QueueStrategy”定义的规则将任务序列放入队列中等候。QueueStrategy函数返回任务序列的相关值,然后根据优先级来确定任务序列在队列中的位置。高优先级的任务序列放在队列的前面,低优先级的放在队列的后面。如果优先级相同,则根据队列的先进先出(FIFO)原则来处理。用户可以根据需要,动态的改变任务序列的优先级。
当将队列中的任务序列进行排序时,Dispatcher执行队列策略函数,遍历取得已有任务序列的优先级值,与最新的任务序列优先级值比较,根据比较的结果重新进行队列排序。
在Flexsim对象层次图中,我们发现Dispatcher是所有TaskExecuter的父类,也就是说所有的TaskExecuter也是Dispatcher。这就意味着Operator或Transporter也可以担当Dispatcher的角色来分配任务序列,或者是自己执行任务序列。
5.2.4.4 Dispatcher与TaskExecuter的区别
在仿真执行的任意时刻,即使任务序列的等候队列中多个任务序列,TaskExecuter一次只能执行一个任务序列。而Dispatcher对象的作用只是在缓存队列中存放已排序好任务序列,并将队列最前面的任务序列发送给动态对象,但并不执行任务序列。
5.2.4.5 利用任务序列实现集装箱的装卸过程
在集装箱码头的作业的过程中,集卡行驶到岸桥设备处等待装箱,岸桥将集装箱从船上卸下装到已等待的集卡上;装箱后的集卡行驶到堆场中,场桥将集装箱从集卡上卸下,堆放到堆场中。集装箱从船到堆场的过程中,经过了集卡、岸桥、场桥等设备的搬运,在Flexsim中就需要使用任务序列来完成这个过程。
这里涉及了三个可运动对象:集卡、岸桥和场桥。这里设计的思路是这样的,集装箱的运输由集卡来实现,这样集卡就有这样一个任务序列:Travel Load Travel Unload。集装箱装入集卡的作业由岸桥设备完成,卸载放入堆场的作业由场桥设备完成,所以集卡的任务序列中Load/Unload的任务就应该由岸桥和场桥来完成。
岸桥完成一次作业的过程也就是完成一个任务序列的过程,可以知道岸桥完成的任务序列应该是:Travel Load Travel Unload。岸桥在作业的过程中,集卡处于等待的状态,也就是说岸桥和集卡之间是协同作业的。场桥的情况与岸桥一致。Flexsim中可以使用调用子任务的方法将岸桥和场桥的任务序列插入到集卡的任务序列中。图1-7表示了主任务序列和子任务序列之间的关系。
集卡主任务序列 Travel Load Travel Unload 岸桥子任务序列 Travel Load Travel Unload 场桥子任务序列 Travel Load Travel Unload
图1-7 集装箱搬运过程的任务序列
在Flexsim中的实现的主要代码如下,其关键的代码在文中有注释: //获取任务序列中的任务数量
int nroftasks = gettotalnroftasks(tasksequence);
//查找Load/Unload任务,找到之后调用子任务来替换这两个任务
for(int i=1; i<=nroftasks; i++) { int tasktype = gettasktype(tasksequence, i); switch(tasktype) {
case TASKTYPE_LOAD: case TASKTYPE_FRLOAD: { int msgtype = (tasktype == TASKTYPE_LOAD ? 1 : 2); //changetask(…)函数会发出一个消息(message),我们在消息的接受者的OnMessage(…)函 //数中创建岸桥和叉车的子任务序列
changetask(tasksequence, i, TASKTYPE_CALLSUBTASKS, current, NULL, msgtype, tonum(gettaskinvolved(tasksequence, i, 1)), tonum(gettaskinvolved(tasksequence, i, 2)), gettaskvariable(tasksequence, i, 1));
} break; case TASKTYPE_UNLOAD: case TASKTYPE_FRUNLOAD: { int msgtype = (tasktype == TASKTYPE_UNLOAD ? 3: 4); changetask(tasksequence, i, TASKTYPE_CALLSUBTASKS, current, NULL, msgtype, tonum(gettaskinvolved(tasksequence, i, 1)), tonum(gettaskinvolved(tasksequence, i, 2)), gettaskvariable(tasksequence, i, 1));
} break; default: break; } }
子任务序列的实现过程,关键代码有注释 //由changetask()传过来的参数msgtype
int msgtype = msgparam(1); switch(msgtype)
{//这里只实现了岸桥子任务序列 case 1: case 2: { fsnode* op = msgsendingobject; fsnode* item = tonode(msgparam(2)); fsnode* queue = up(item);//queue1 fsnode* active_ts = gettasksequence(op, 0); //0表示当前活动的任务序列 int port = gettaskvariable(active_ts, getcurtask(active_ts), 4); fsnode* sts = centerobject(queue, 2); //注意连接时候的端口号 fsnode* ts = createcoordinatedtasksequence(op);//创建协同工作序列 int op_key = insertallocatetask(ts, op, 0, 0); int sync_key1 = insertproxytask(ts, op_key, TASKTYPE_PICKOFFSET, item, queue, 0, 1, 0);
int sts_key = insertallocatetask(ts, sts, tonum(queue), 0); insertproxytask(ts, sts_key, TASKTYPE_TRAVEL, queue, NULL, 0); int sync_key2 = insertproxytask(ts, sts_key, msgtype == 1 ? TASKTYPE_FRLOAD : TASKTYPE_LOAD, item, queue, port);
insertsynctask(ts, sync_key1); insertsynctask(ts, sync_key2); int sync_key3 = insertproxytask(ts, sts_key, TASKTYPE_UNLOAD, item, op, port);
insertsynctask(ts, sync_key3); insertdeallocatetask(ts, op_key); insertdeallocatetask(ts, sts_key); return tonum(ts); } break; …
}
具体的代码实现部分有些复杂,但是我们通过前面的分析,将思路整理清楚了,实现也就相对容易了。
5.3 运动学(Kinematics)
运动学部分是Flexsim3.06版中新引入的功能。Flexsim软件的一大特点就是三维显示功能非常强大,除了能够处理数据统计外,还能使模型的场景中的可运动设备动起来,从而使模拟过程更接近真实。例如,对于港口设备岸边集装箱岸桥,在系统建模中如果我们只关心数据、处理时间等的话,可以用Processor来简单代替岸桥的功能。在Flexsim中可以将岸桥完全实现,不仅在外观上,更重要的是设备处理物件的动作。要实现设备的动作,平移(水平运动,或垂直运动),或是旋转运动,这些都需要用到运动学的知识。
本节主要介绍运动学相关知识,例如坐标空间转换,运动实现,模型的导入,尺寸大小的设定等,还将详细讲述如何在Flexsim中创建用户自己的专门对象库。
5.3.1 FLexsim中的坐标空间
运动功能允许一个对象同时实现多个移动操作,在每个运动方向都有加速度、减速度、起始速度、结束速度以及最大速度等属性。例如集装箱岸桥的运动就是由多个部件的运动组成,即大车沿着轨道运行,小车在大车上运行,吊具在垂直方向上运行。大车、小车和吊具都有其自己的速度属性。如果有了岸桥这样一个设备对象,在仿真过程中我们就可以实现岸桥的作业过程。运动学函数的引入就是帮助用户来实现自己定制的设备的动作。运动学这部分是从3.06版才开始引入的,新版本还会对这部分进一步改进。
实现运动学并不难,主要是对三个函数的使用。要执行运动操作,首先要调用initkinematics命令。该命令为运动初始化数据,保存对象的起始位置、起始角度。初始化完毕之后,调用addkinematic命令为对象添加平移或旋转动作。例如,用户告诉对象在5秒钟时开始运动,给定加速度、减速度和最大速度,在x方向上平移10个单位;然后告诉对象在7秒钟时,用不同的加速度、减速度和最大速度,在y方向上移动10个单位。这两个运动的结果是:对象先在x方向上运动,然后同时在y方向上加速,最后到达目的点的运动轨迹是抛物线。每一个单独的运动通过addkinematic命令添加;然后调用updatekinematics命令在运动过程中不断地刷新视图,该命令的作用就是计算对象当前的位置和旋转角度。
上面的例子很简单,为了更好的解释运动学,我们先介绍坐标空间的概念。Flexsim中最常用的坐标空间就是模型空间(model)。用户建立系统模型时,将许多对象放入视图中,根据不同的逻辑关系组成不同的模型。这些对象都处于模型空间中。模型空间是Flexsim中最大的坐标空间,系统模型中的所有对象都被包含在这个空间当中。
还有一种容器坐标空间(container)。容器对象就是可以存储物件,举例来说,对象Queue的作用是暂存物件,此时Queue就相当于一个容器。当物件置于Queue中时,物件(item)就处于Queue的容器空间中。当一个物体处于不同的容器空间中时,他的位置坐标就是他所在容器坐标空间坐标系的值。图1-5描述了容器空间的概念。
Y Z Y’ Model空间 Z’ Queue空间 3 物件item O’ -2 1 X’ O 2 X 图1-5
在上图中,Queue置于Model坐标空间中,其位置坐标是(2,3);物件item置于Queue的容器空间中,其位置坐标是(1,-2)。用户查看对象的属性页面可以得到对象的坐标值。这里需要提示一点的是,在Flexsim中每个被选中的对象都有一个黄色的外界矩形框,对象的坐标是以如图所示的位置点来确定的。
当用户定制的对象需要做的动作比较复杂的动作时,相对运动的坐标关系常常需要在不同的容器坐标系之间作相应的转换工作。Flexsim也提供了相应的坐标转换函数,在我们后面的内容中会有详细的讲述。
模型的导入及模型尺寸的调整
Flexsim可以导入多种3D媒体文件。这些文件格式包含了3ds、wrl、dxf和stl,这些都是很常用的工业标准。用户可以使用第三方的软件,如3DMax,MAYA来构造模型,然后将模型文件转化为标准格式,最后导入Flexsim中。这里有一些注意点,Flexsim只支持VRML1.0版的图形,不支持2.0版本;Flexsim只能导入stl的ascii文件,不支持stl的二进制(binary)文件。
在对象的属性对话框中,在“3D shape”一项中可以更改3D模型。我们这里用一个实例来介绍一个制作的过程,以及一些技巧。
制作一个集装箱吊具。我们在3DMax中按比例做出吊具的三维模型,具体的制作过程不是我们讨论的内容。在完成之后我们还需要做一些后期的处理工作,使导出的文件在导入Flexsim中有最佳的效果。实现过程很简单,过程如下:量取模型长宽高的比例值(0.5:2.5:0.6);设置3DMax软件的最小单元的尺寸为1;将已完成的模型缩小到尺寸大小为1的正方体中(图1-6);最后将模型导出,保存为3ds文件格式。
图1-6
我们选取BasicTE作为吊具的模板。在Flexsim中,BasicTE对象的默认外形是一个球体。打开该对象的属性对话框,将“3D shape”选项中的媒体文件改为吊具模型的文件。导入之后的外观如图1-7所示。在“Position, Rotation, and Size”选项中,将SX/SY/SZ三项的值改为我们之前记录的外界矩形框的长宽高比例,效果如图1-8。
图1-7 图1-8
从图中我们看到,不管模型的尺寸怎么改变,模型始终被包含在黄色的外界框中。这么做的目的不仅是为了外观上的好看,更重要的是为了后面的运动学计算时的方便。
有时候模型导入Flexsim后,模型和外界框之间有一些偏差。此时可以使用“Edit 3D Shape Factors”来修正,使模型完全处于黄色的外界框之中。
除了改变模型的外观和尺寸,Flexsim中还可以改变对象外观的贴图和颜色。还有一点就是用户还可以自己编写OpenGL代码来画出对象的外观,具体实现在“Custom Draw Code”中实现。这部分的要求比较高,用的不是很多。
制作岸边集装箱起重机对象
岸桥设备是集装箱码头装卸船作业的最主要设备,在港口中有着广泛的应用。我们用一个例子来总结一下本节所讲的内容,该例子对于其他对象的开发有很多的借鉴意义。岸桥设备对象在后面的系统建模及仿真中也得到了应用。
BasicTE对象
我们前面提到,Flexsim为用户提供了BasicTE/BasicFR对象来开发自己的对象。岸桥设备的实现要涉及到运动学,所以我们选择BasicTE对象。BasicTE对象的引入就是为了实现对象的运动,我们主要的工作就要实现参数对话框中OnBeginOffset/OnUpdateOffset/OnFinishOffset函数。
图1-9 BasicTE参数对话框
这些函数的功能是:
(1) OnBeginOffset —— 计算出该对象在X/Y/Z方向上要运行的距离或要旋转的角
度;
(2) OnUpdateOffset —— 在对象运动的过程不断地计算位置或旋转的角度; (3) OnFinishOffset —— 运动结束后调用该函数。
部件的层级关系
这里我们将岸桥分解为三个主要运动部件:大车运行结构、小车运行机构和吊具。三者之间的关系是:小车和吊具跟随大车运动;吊具跟随小车运动。也就是说大车和小车都相当于容器,小车置于大车容器中,吊具置于小车容器中。在Flexsim中的实现如图1-10
BasicTE BasicTE BasicTE 大车运行机构 小车运行机构 吊具
图1-10 岸桥部件层次关系
导入三维模型
我们在3DMax中制作三维模型,调整三个部件的比例关系,记录模型外接矩形框的窗宽高比例,然后将三个部件分别导出,保存为:STS.3ds/Trolley.3ds/Grabber.3ds。
将三个模型导入到各自对应的BasicTE对象。调整尺寸之后得到的如图1-11所示的效果。
图1-11 三维模型导入Flexism后的效果
运动的实现
我们先来看看BasicTE是怎样来完成一次搬运的作业过程的。图1-12表示的是BasicTE与物件容器(容器1是提取物件的位置,容器2是物件放下的位置)的相对位置。BasicTE先运动到容器1;提取物件;在运动到容器2;放下物件。这就是一个完整的作业过程。我们关心的是BasicTE两次运动的行走路线,从图中我们可以清楚地看到有两种路线:1)在X/Y方向上同时有运动速度,此时从起始点到目的点的运动路线是抛物线;2)将X/Y方向上的运动分解,可以先完成X方向上的运行距离,再完成Y方向上的运行距离,或反过来。
Y Y’ x’ 容器1 y’ BasicTE X’ 容器2 X
图1-12 两种运行路线
确定了运行路线后,接下来需要知道的是BasicTE对象需要运动的距离。不管是抛物线的运行路线还是直线的运动路线,都可以将分解为起始点与目的点之间在X方向上的距离和Y方向的距离。BasicTE的参数对话框的“OnBeginOffset”选项中为我们提供了多个有用的参数值,这是系统自动计算的,用户只要明白这些参数的含义直接拿来使用即可。下面是对这些参数含义的解释:
1) current:BasicTE对象本身;
2) x:BasicTE在x方向上的偏移量;其值为BasicTE与物件中心坐标在x方向的差; 3) y:BasicTE在y方向上的偏移量;其值为BasicTE与物件中心坐标在y方向的差; 4) z:BasicTE在z方向上的偏移量;其值为BasicTE与物件中心坐标在z方向的差; 5) item:BasicTE所搬运的物件;
6) endspeed:BasicTE到达目的点的速度;
7) maxspeed:BasicTE运动过程中所能达到的最大速度; 8) acceleration:BasicTE运动过程中的加速度; 9) deceleration:BasicTE运动过程中的减速度;
我们接着来看看我们做要完成的岸桥设备该怎样运动?可以肯定岸桥不会有抛物线的运动轨迹,假设岸桥的大车(STS)在model坐标空间中沿着y方向运动,那么小车(Trolley)在大车的坐标空间中沿着x方向运动,吊具(Grabber)在z方向上运动。小车和吊具都处于大车的坐标空间中,当我们在大车中实现运动函数时,上面所提到的距离参数需要做一些转换。
这里x/y/z距离参数都是大车的BasicTE对象相对物件的距离,这个距离值只有在model坐标空间中才有意义;大车处在model的坐标空间中,大车在y方向上运动,所以y参数值可以直接使用。小车处于大车的坐标空间中,需要将x参数转化到同一坐标系下,这样小车才能准确地运动到物件的正上方。吊具运行的距离也同要需要将z值转换到同一坐标系下。图1-13是对上述文字的一些解释。
Y Y’ Model newx item delta y STS trolley xDis_Trolley X’ X x
图1-13 岸桥各部件运动距离
从图中我们可以清楚地看到大车的运行距离是y。
小车的运行距离xDis_Trolley需要经过一些计算才能得到。因为小车处于大车的坐标空间中,而x参数值是大车中心与物件中心的差,是model坐标空间中的值,所以我们先将x转换到大车的坐标空间中,Flexsim为我们提供了转换函数vectorprojerx(…)。物件在大车坐标空间的坐标值newx:newx = vectorprojectx(model, xcenter(current)+x, 0, 0, current);从图中可以知道delta是在大车的坐标空间中:delta = xloc(trolley) + 0.5*xsize(trolley);小车最终的运行距离是:xDis_Trolley = newx – delta。同样的我们可以得到吊具的运行距离z。
运行距离得到之后,接下来的工作是分析岸桥在完成一次装卸作业的运动周期。我们将完成一次装卸作业的运动定义如下:1)吊具运动;2)大车运行;3)小车运行;4)吊具运行。仿真过程中岸桥设备按照这样的作业周期不停地作业,直到仿真结束或者装卸完毕。
在OnBeginOffset中具体实现如下: …
//初始化运动
initkinematics(sts_kin, current);//全局坐标 initkinematics(trolley_kin, trolley); initkinematics(grabber_kin, grabber); …
//添加运动
double time1 = addkinematic(grabber_kin, 0, 0, z, …time(), KINEMATIC_TRAVEL); double time2 = addkinematic(sts_kin, 0, y, 0, …time1, KINEMATIC_TRAVEL); double time3 = addkinematic(trolley_kin, x, 0, 0, …time2, KINEMATIC_TRAVEL); double time4 = addkinematic(grabber_kin, 0, 0, z, …time3, KINEMATIC_TRAVEL); return time4 – time(); 在OnUpdateOffset中的实现比较简单,只要不断地更新运动过程即可,主要实现如下: …
if(offsettingnow) { updatekinematics(label(current, \"sts_kin\"), current); updatekinematics(label(current, \"trolley_kin\"), trolley); updatekinematics(label(current, \"grabber_kin\"), grabber); } …
在OnFinishOffset中的实现代码与OnUpdateOffset的主要代码一样。
对于调用运动学函数,用户必须给这些函数传递一个空节点作为第一个参数。该参数的作用是存储运动信息,或从该节点中提取信息。对于用户来说只要添加一个标签即可,例如在代码中有这样一些标签,如label(current, \"sts_kin\")等。函数调用的过程中,该标签会显示“do not touch ”文本。用户不必关心其中的内容,只要添加了即可。
Addkinematic(…)函数的最后一个参数KINEMATIC_TRAVEL定义了平移的运动方式。还有其它一些参数来定义不同的功能,如KINEMATIC_ROTATE定义了旋转的运动方式,关于其它参数的含义请查阅Flexsim的帮助文档。
定制参数输入对话框
以上的工作已经完成了一个岸桥设备对象,用户可以在仿真中使用。如果用户要改变设备的一些参数值,如各部件的运行速度,加速度等,就需要打开属性对话框界面,然后寻找与这些参数相对性的标签值。这样的操作是相当繁琐的,给对象开发者之外的人使用常常会导致错误。Flexsim3.06版中引入了定制图形用户界面(GUI)的功能。
我们将用户关心的参数放在新的参数对话框中,将运动学实现部分,后台参数处理等屏蔽掉,这样对于使用者是非常有用的。我们设计了图1-14这样的参数对话框,当用户双击对象之后不会看到BasicTE的参数对话框,而是其关心的参数输入对话框。
图1-14岸桥速度设置对话框
点击Flexsim中“ToolBox”按钮,弹出“Global Modeling Tools”对话框。在对话框的最下面一项是“Graphical User Interfaces”,点击“Add”按钮,添加一个新的图形用户界面,
然后点击“Edit”弹出GUI的设计界面,用户就可以定制自己的界面。
Flexsim中为GUI设计提供了许多控件,这些控件在Flexism的不同对象中都有出现,用户对Flexsim的使用熟悉的话,对这些控件的使用会很快掌握,并用来创建自己的界面。图1-15是GUI设计界面。
图1-15 GUI设计界面
上图左边是已有的控件,以及编辑控件的对话框;右边是设计窗口,用户可以将左边窗口中的控件拖入设计窗口中进行排列编辑等。
对象中涉及的参数在对象的属性对话框中都有相应的标签(label)值与之对应。如果没有用户定制的界面,则在参数需要改动时必须修改标签值。在我们定制的界面中,将参数与标签值对应,我们只需修改定制界面中的值即可,这样使人机交互更友好。图1-14所示的用户定制界面,使用者对关心的参数一目了然。
控件参数怎么与标签值产生联系呢?这里有两种方式:1)冷链接。用户在定制界面的控件中输入参数之后,需要按下“Apply”或“OK”,修改值才会传递给标签值;2)热链接。用户输入参数后,修改值马上就传递给标签。每个控件有许多属性和事件函数,用户根据不同的需要来选择实现。
界面定制完成之后,就应该把该界面与用户所选择对象产生联系。这里我们已经完成了图1-14的界面,选择岸桥对象(被选择对象有一个红色的外接框),然后选择“GUI options”下的“Copy this GUI into selected Objects”。完成之后,当用户再次双击岸桥对象,打开的将是图1-14的界面。
创建用户自己的对象库
Flexsim本身提供了基本的对象库,这些对象分为两类Fixed Resources和Mobile Resources,这些基本对象可以完成许多仿真工作。用户也可以创建自己的对象库以针对其所在行业所遇到的问题。例如针对港口的物流仿真,现有的基本对象库就不能满足仿真的要求,这时用户就有必要来创建港口设备对象库。对象库的建立就是为了对象的重复利用,以
节约建模时间。
我们这里介绍怎样来创建一个对象库。前面我们已经建立了一个岸桥对象,用鼠标右键点选该对象,在弹出的快捷菜单中选择“Add to User Library”,这样岸桥对象就被添加到库中。修改一下库名称、图标,使其更加直观(图1-16)。用户还可以开发其它的设备对象,然后加入到对象库中,使其成为一个系列。这样就可以针对不同的行业做出不同的方案。
图1-16 港口设备对象库
因篇幅问题不能全部显示,请点此查看更多更全内容