OPNET Modeler 常用编辑器主要有项目编辑器、节点模型编辑器和进程模型编辑器。下面举一个例子来介绍这几种常用编辑器的使用。
在仿真开始时,进程模型被首次调用,进入Initialization状态。在初始化后(将包计数器设置为0),将转移到Idle状态等待第一个包到达,当一个包到达时,进程模型被再次激活并且转移到Arrival状态。Arrival状态将包计数器变量加1,并将包销毁,然后又立即回到Idle状态等待下一个包的到达,可以画出如下图所示的草图。
接下来就从小到大依次创建各个模型,即进程模型——>节点模型——>网络模型,这也是自定义模型网络建模的次序。
打开OPNET软件,在File——>New,弹出的框中选择 Process Model,点击OK按钮创建。
创建完成后的进程模型如下图所示。
在创建进程模型时,有几个需要注意的点:
①创建的第一个状态自动被OPNET标识为初始状态,也就是带黑色大箭头的这一个状态;
②选中放置的状态,右键Set Name就可以更改状态的名称;
③绿色的状态为强制状态(也称非停留态),转移到绿色状态将依次执行入口执行代码和出口执行代码,然后立即转移到其他状态。红色的状态为非强制状态,一个新创建的状态默认为红色状态,转移到该状态时,执行完入口执行代码后,模块将程序的控制权转回仿真核心,模块在此停滞,等待下一个事件到达激活模块。右键红色的状态,在弹出的菜单中选择 Make State Forced 可将非强制状态转化为强制状态(即红转绿),右键绿色的状态,在弹出的菜单中选择 Make State Unforced 可将强制状态转化为非强制状态(即绿转红)。
④选中创建转移按钮在各个状态间进行连线,需要圆滑的就需要在两点之间再点击一次放置一点。无条件转移的是实线,有条件转移的是虚线,虚线旁边的条件即属性,单击选中需要条件转移的线,在线上右键选择 Edit Attributes 设置其转移条件,如下图所示。
⑤给idle连接一个自身转移线,将其condition属性设置为default。当仿真运行时,仿真核心将处在事件列表队首的事件变成中断,并将它发送至合适的模块,假设进程模型接收中断,并且处在idle状态,如果 ARRIVAL条件满足,则顺利转移到arrival状态,但是进程模型也可能收到异常中断,ARRIVAL条件不能满足,这时如果没有其他满足条件的转移,模块将找不到目的状态而出错,default 这个默认转移就是起着最后一道防线的作用。
⑥定义一些条件和变量。
点击HB按钮定义宏。
输入代码如下并保存文件。
#define ARRIVAL (op_intrpt_type () == OPC_INTRPT_STRM)
在OPNET中,经常使用宏来替换复杂的转移条件和状态转移执行代码,这样可以使有限状态图看起来简洁明了。
当中断到达模块时,仿真核心调用 op_intrpt_type() 函数,将其返回值与 OPNET 常量 OPC_INTRPT_STRM 相比较,如果值相等说明这个中断是由于包到达引起的,这时 ARRIVAL 条件满足。
接下来需要申明两个状态变量,一个用来存储包计数器的值,另一个是用来将计数器的值写入统计量的句柄。
点击SV按钮进行状态变量的设置,如下图所示。
在Interfaces——>Local Statistics下新建一个本地统计量,并添加说明,如下图所示。
接下来创建各状态的执行代码。
对于强制状态,入口执行代码和出口执行代码的执行是连贯的,因此一般将强制状态的程序都放在其入口执行代码中。
双击init状态的上半部分,在其入口执行代码文件中写入下面代码。
pk_count = 0;
pk_cnt_stathandle = op_stat_reg ("packet count", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
第一句代码是将包计数器的值置为 0,第二句代码注册申明的统计量,得到与它关联的统计量句柄 pk_cnt_stathandle,这里会用到核心函数 op_stat_reg()。
双击arrival状态的上半部分,在其入口执行代码文件中写入下面代码。
pk_count = pk_count + 1;
op_pk_destroy (op_pk_get (op_intrpt_strm()));
op_stat_write(pk_cnt_stathandle, pk_count);
第一句代码是将包计数器的值加1。第二句代码中,首先决定中断来自哪个包流 op_intrpt_strm(),它返回该包流的索引号,接着根据这个索引号得到包op_pk_get(),它返回一个指向包数据结构的指针,最后将这个包指针指向的内存块释放,即将包销毁op_pk_destroy()。第三句代码将当前的计数器值通过核心函数 op_stat_write() 写入状态统计句柄 pk_cnt_stathandle。
在Interfaces——>Process Interfaces下按下图所示的进行设置。
begsim intrpt 是仿真开始中断;endsim intrpt 是仿真结束中断。
在各个过程模型的过程接口有一些属性:如 begsim intrpt、endsim intrpt、failure intrpt、regular intrpt 等,在设计模块时,这些属性的设置很关键,其是 begsim intrpt 的设置,其影响 init 的状态的 Enter 代码何时执行,如果是 enabled,那么仿真一开始,即仿真0时刻,可以对 process 进行初始化,process 被触发后,即执行 init 的 Enter 代码。如果是 disabled 的话,就不会被 kernel 触发。如果仿真结束时需要进行一些工作(如变量的收集,内存的释放等),则需要 enable endsim intrpt。regular intrpt 可用来做定时器,在process interface 设定了 intrpt interval 之后,仿真核心每隔该时间量触发一次 regular 中断。
进程模型的设置到此结束,点击编译进程模型按钮(工具栏最后一个按钮),弹出如下框,说明编译没有问题。
在编译时,会先让你保存该进程模型,将其命名为 packet_count。
接下来创建节点模型。
在File——>New,弹出的框中选择 Node Model,点击OK按钮创建。
创建完成后的节点模型如下图所示。
节点模型的创建只用到了创建进程工具按钮和创建包流的按钮。
对三个模块的属性进行设置,src1的属性设置如下图所示。
count的属性设置如下图所示,注意这里的进程模型选择前面创建的进程模型packet_count。
src2的属性设置如下图所示,包延迟时间这里右击将其设置为 promoted。
两个包生成器同时向count模块发送包。第一个包生成器以每秒一个包的速度发送,而第二个包生成器以可变的速率发送,需要为第二个包生成器的 Packet Interarrival Time属性指定一个分布函数来达到这个效果。前面之所以提升这个属性,是因为我们希望在节点级能够对该属性进行调节, 这样给用户带来方便,但是这个属性却是属于进程级的,通过提升可以使该属性在节点级也能够设置。提升后,在节点模型中还可以对它重命名。
以上工作完成后保存节点模型,命名依然是packet_count,如下图所示。
进程模型和节点模型可以同名,它们之间不会混淆,因为文件的后缀不同,进程模型后缀是*.pr.m,节点模型后缀是 *.nd.m,如下图。
在Interfaces——>Node Statistics下把 packet count 统计量添加进来,操作步骤如下图所示。
添加成功后如下图,点击OK即可。
在File——>New,弹出的框中选择 Project,设置项目名称为packet_count,场景名称为constant,如下图所示,点击OK。
在弹出的启动向导对话框中点击 Quit 跳过后续步骤。
接下来打开对象面板,搜索packet_count节点,将其放置到工作空间中,关闭对象面板。
右击放置的节点,选择Choose Individual DES Statistics,然后勾选下面几个选项,点击OK。
接下来需要指定节点模型中第二包生成器的Packet Interarrival Time属性,在节点模型上单击鼠标右键,从弹出的菜单中选择Edit Attributes,选择 src2.Packet Interarrival Time 的分布函数对话框,设置如下图。
勾选DES下的动画功能,这样仿真后就可以查看动画效果了。
仿真前先配置repositories,在Edit——>Preferences下搜索repositories,确保其为空,若不空,则删除掉,否则后续仿真可能会出错。
设置仿真参数如下图所示。
这里的仿真内核选择了Optimized 是为了加快仿真速度不产生 ODB(OPNET Debugger) 调试信息,如果需要 ODB 调试信息,这里的仿真内核要选择为 Development,并在左侧的 Execution下选择 OPNET Debugger ,右侧的勾选框选择,如果是Optimized 仿真内核,则会提示 ODB 不可用,如下图所示。
点击Run,如果没有错误即可完成仿真,如下图所示。
右击节点,选择View Results,勾选 packet count 即可看到最终绘制的曲线,如下图所示。
在DES下选择Play 2D Animation就可以查看发送包流的动画了!
随时间变化的曲线动画如下。
包流动画如下所示。
接下来在Scenarios——>Duplicate Scenario…复制一个场景,将其命名为exponential,如下图所示。
编辑节点的属性,选择 src2.Packet Interarrival Time 的分布函数对话框,设置如下图。
可以一次运行两个仿真,在Scenarios菜单下选择Manage Scenarios,按下图所示的设置。
点击OK进行仿真,仿真完成后如下图所示。
接下来查看将 src2.Packet Interarrival Time 设为指数分布函数的曲线图。
图中的曲线表明包计数器的值随着仿真时间变化的规律。可以看出包的总数随着仿真时间的推移单调递增,曲线中的毛刺是由于包突发到达(服从指数分布函数规律)引起的。而曲线的斜率,即包的吞吐量和包生成速率相符,可以通过计算来验证。两个包生成模块,平均每秒生成1个包,仿真100秒,实际产生包的时间间隔为90秒,则包计数进程模块收到的包个数大概为180。
点击Show按钮后,又弹出单独的一个窗口,用鼠标选中某一块范围就可以将其放大观看,如下图所示。
在这个单独的窗口中,右击曲线可以设置曲线的颜色,加网格,让线性的呈离散显示等操作,如下图所示。
右击曲线外部可以设置面板的显示特性,比如刻度以秒计,图标样式等属性,如下图所示。
可以将不同函数的放在一起显示,如下图所示。
或者在一幅图中画出两条曲线,如下图所示。
仿真过程中遇到下图所示的错误可以参考文章:OPNET出现LINK:fatal error LNK1181:无法打开输入文件的解决办法。
错误一:
错误二:
以上就是 OPNET Modeler 常用编辑器的综合运用举例的所有内容了,希望本文对你学习 OPNET Modeler 软件有一定的帮助!
本文参考书目:OPNET 网络仿真/陈敏编著. - 北京:清华大学出版社,2004