1、一、前 言 相信各位在使用 VISSIM微观仿真软件的过程中,会想 到 通过仿真手段验 证 自己研究的模型算法效果,而 Vissim 自带的功能往往无法满足,因此需要进行二次开发,而这一过程就需要用到 VISSIM 提供的COM接口。从本期开始,我们将介绍基于 C#平台的 VISSIM二次开发,每一期都将附上图文步骤和 C#源代码。同时,我们非常欢迎在此过程中能够和大家一起讨论,分享相关的经验和感悟。 二、 VISSIM二次开发思路 以高速公路 管理控制为例,其思路即在仿真平台基础上,通过 COM接口和 C#构建控制平台,平台可集成路况判别,事故检测、管理控制等一系列功能,并通过 VISSIM
2、自带的评价模块(可输出总车辆行驶时间、行驶距离、排放等参数)对路网运行状态进行评价,概要思路如图1所示。 图 1 高速公路 VISSIM仿真平台原理示意图 三、 C#平台对接 本期主要介绍 VISSIM 4.3和 C#平台的对接,实现的最初级功能包括:( 1)通过 C#windows 控件打开 VISSIM 路网;( 2)设置 VISSIM 仿真参数(仿真时长、仿真速度、精度、随机种子数等)。 第一步 , 加载 COM接口 在 C#中新建 window窗体应用项目,命名为 “VissimComTest_1”,并在解决方案资源管理器中右键点击 “引用 ”,将 VISSIM 的 COM 接口载入项
3、目,如图 2所示。 图 2 加载 VISSIM接口 第二步,新建路网 在编写代码之前要了解的是 VISSIM的整个开发构架,如图 3所示。根对象是 Vissim,路网对象 Net下分出各子对象,如路段( link)、路径( paths)、车辆( vehicle)等。具体的对象关系及相关的函数在 VISSIM官方的二次开发手册中会有详细介绍。 图 3 VISSIM对象关系 首先双击 Form1对话框,打开后台代码,添加 VISSIM的 COM接口命名空间,并新建一个初始化函数 “InitialVissim ()”,代码如下: using System; using System.Collecti
4、ons.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using VISSIM_COMSERVERLib; /注意添加命名空间 namespace VissimComTest_1 public partial class Form1 : Form public Form1() InitializeComponent(); InitialVissim()
5、; /初始化函数 public void InitialVissim() Vissim vis = new Vissim(); if ( vis != null ) vis.LoadNet(“.inp文件路径 “, 0); 完成后,点击编译,运行,就可以打开指令路径的 vissim 路网了( 注意, 4.3版本需要将系统时间调至 2008年,否则无法运行 )。 第三步,添加控件 下面我们通过添加按钮控制和文本框控制来实现 VISSIM路网的开启和仿真参数的设置。首先,在 VS开发平台中点开控件工具箱,拖入一个按钮控制,并在属性中将 Text改为 “开启路网 ”, Name改为 “Start”,
6、如图 4所示。 图 4 拖入按钮控件 双击 “开启路网 ”按钮控件,进行代码编写,将之前放 在 public Form1()中 的 InitialVissim()函数移动 到 private void Start_Click(object sender, EventArgs e)中,运行编译之后,可以通过按钮控件打开 Vissim路网。接着我们添加一组 TextBox控件来设置仿真参数,如:仿真周期和仿真速度等,将对应的 TextBox 控件分别命名为 “SimulationPeriod”和“SimulationSpeed”。同时添加一个 “开始仿真 ”的按钮控件(命名为“StartSimul
7、ation”),用于启动仿真,如图 5所示。 图 5 加入 TextBox控件设置仿真参数 同样,添加相应的代码,如下: private void StartSimulation_Click(object sender, EventArgs e) Vissim vis = new Vissim(); Simulation sim = vis.Simulation; try sim.Period = Convert.ToDouble(this.SimulationPeriod.Text); sim.Speed = Convert.ToDouble(this.SimulationSpeed.Tex
8、t); sim.RunContinuous(); catch MessageBox.Show(“仿真未正常结束! “); sim.Stop(); 编译运行后,如图 6所示。 图 6 仿真运行效果图 需要指出的是, 一旦开启了连续仿真模 式 sim.RunContinuous(),则仿真运行期间不能进行其他操作,除非事先设定了中断 点 。但是经过尝试发现,以 for 循环搭配单步仿真的方式更加灵活,能够在仿真运行过程中进行各种操作,且不影响仿真进度和最终结果,这方面内容将在后续几 期中介绍 。 另外,每次开启 vissim4.3 之前都需要调整时间,很是繁琐,直接在软件中进行修改,在启动时将时间
9、自动修改为 2008, 注意!需要在编译后以管理员模式打开可执行文件 .exe(保存在项目目录下的binDebugVissimComTest_1.exe ),读者可自行尝试实现退出程序后系统时间复位的功能。同时可以下载开发手册,举一反三,自行摸索。 下期预告:下期中我们将介绍如何在仿真运行过程中获取检测器参数,以及如何设置路网的事故场景。 【附】第一期完整代码: using System; using System.Drawing; using System.Collections; using System.Windows.Forms; using System.Collections.Ge
10、neric; using System.ComponentModel; using System.Data; using System.Text; using System.Threading; using System.Linq; using System.Runtime.InteropServices; using VISSIM_COMSERVERLib; namespace VissimComTest_1 public partial class Form1 : Form public Form1() InitializeComponent(); SystemTime MySystemT
11、ime = new SystemTime(); /此部分修改系统时间 DateTime DateTime = new DateTime(); MySystemTime.vYear = (ushort)2008; /改为 2008年 MySystemTime.vMonth = (ushort)Convert.ToInt32(DateTime.Now.Month.ToString(); /获取当前月 MySystemTime.vDay = (ushort)Convert.ToInt32(DateTime.Now.Day.ToString(); MySystemTime.vHour = (ushor
12、t)Convert.ToInt32(DateTime.Now.Hour.ToString(); MySystemTime.vMinute = (ushort)Convert.ToInt32(DateTime.Now.Minute.ToString(); MySystemTime.vSecond = (ushort)Convert.ToInt32(DateTime.Now.Second.ToString(); SetSystemDateTime.SetLocalTime(MySystemTime); /修改系统时间结束 private void Form1_Load(object sender,
13、 EventArgs e) public void InitialVissim() Vissim vis = new Vissim(); /新建路网 vis.LoadNet(“C:UserslenovoDesktopVISSIM二次开发 路网模型 crossing_model.inp“, 0); /加载路网 private void Start_Click(object sender, EventArgs e) InitialVissim(); /初始化 /开始仿真 private void StartSimulation_Click(object sender, EventArgs e) V
14、issim vis = new Vissim(); /此时定义的路网即对应已打开的路网 Simulation sim = vis.Simulation; /仿真对象 try sim.Period = Convert.ToDouble(this.SimulationPeriod.Text); /设置仿真周期 sim.Speed = Convert.ToDouble(this.SimulationSpeed.Text); /设置仿真速度 sim.RunContinuous(); /进行连续仿真 catch /如果捕获到异常 MessageBox.Show(“仿真未正常结束! “); sim.Sto
15、p(); /仿真结束 /自定义类 SetSystemDateTime用于设置系统时间 public class SetSystemDateTime DllImportAttribute(“Kernel32.dll“) public static extern void GetLocalTime(SystemTime st); DllImportAttribute(“Kernel32.dll“) public static extern void SetLocalTime(SystemTime st); /自定义类 SystemTime用于定义日期时间类 StructLayoutAttribute(LayoutKind.Sequential) public class SystemTime public ushort vYear; public ushort vMonth; public ushort vDayOfWeek; public ushort vDay; public ushort vHour; public ushort vMinute; public ushort vSecond;