前言
距离上一篇的教程已经过去了好久了,为了写毕业论文,似乎没有思路和激情来写这部分教程了。
闲话少说了,上一批的引用环境是VISSIM7.0+VS2013,由于VISSIM7.0的COM接口无法提取出检测器(DataCollection)中占有率的数据,因此我在后续的研究中重新采用VISSIM5.4+VS2013的环境,主要采用C#。
本篇的主要内容为如何从VISSIM中提取所需要的数据。
VISSIM的数据提取
任何VISSIM元素都有其ID(NAME为非必须参数),所以我们在通过程序提取VISSIM中数据时,首先要知道的就是你需要完成下列任务:
- 确认自己的研究需要提取那些数据,如路段几何参数,车辆行驶数据,流量,速度,占有率,行程时间,延误等等等;
- 明确这些数据可以通过VISSIM中的哪些元素获取到,如流量、速度、占有率这几个可以从DataCollection(数据采集器)中得到,行程时间和延误从行程时间检测器得到等等;
- 在VISSIM中定义好对应的元素ID(主要是为了方便在程序中找到对应的对象);
- 利用程序接口,找到对应ID的所需数据。
在此过程中你需要仔细的查看VISSIM手册,了解各参数的属性,是否可读,如何获取。上一篇的最后手册已经上传。
后面我将用几个例子展示如何获取各类型的数据。
本篇采用的路网如下图:
路网上存在的VISSIM元素包括;detector,datacollection,routes,traveltime,signalcontrol等,后面对这些元素的提取数据进行示例。
离线的数据返回测试
所谓离线的数据是指无需仿真运行及存在的数据,主要是路网的元素ID和NAME的返回。
1.两种检测器元素返回
VISSIM 中存在两种不同的检测器,与实际的线圈数据类似的是datacollection,而detector主要用于做感应控制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| //测试两种检测器对象 //dataconllection string res = "Allcollections:" + vissim.Net.DataCollections.Count.ToString(); listView1.Items.Add(res); foreach (DataCollection dc in vissim.Net.DataCollections) { string res1 = "DataCollection name:" + dc.Name + "," + "id:" + dc.ID; listView1.Items .Add(res1); } //detector //detector检测器主要的作用是做感应控制,会返回脉冲式的检测数据 foreach (SignalController sc in vissim.Net.SignalControllers ) { string res2 = "SignalControllerID:"+sc.ID; listView1.Items.Add(res2); foreach (Detector de in sc.Detectors) { string res3 = "detectorid:" + de.ID; listView1.Items.Add(res3); } }
|
测试的结果如图,datacollection返回的是设置的断面检测器
2.路径测试
Routesdecisions包含了所有的路径选择对象,然后每个Routesdecision下,有Route的对象来操作具体的参数。
通过这样来获取相对比例,后面的1代表第一个时间间隔
1
| route.get_AttValue1("RELATIVEFLOW",1)
|
1 2 3 4 5 6 7 8 9 10 11
| string res1 = "RoutingDecisions.Count" + vissim.Net.RoutingDecisions.Count.ToString(); listView1.Items.Add(res1); for(int i=1;i<=9;i++) { listView1.Items.Add("第"+ i +"次"); foreach (Route route in vissim.Net.RoutingDecisions.GetRoutingDecisionByNumber(i).Routes) { string res2 = "route ID:" + route.ID + ",route flow" + route.get_AttValue1("RELATIVEFLOW:",1); listView1.Items.Add(res2); } }
|
测试结果:
在线数据返回测试
所谓在线数据,是指只有在仿真的过程当中才存在的数据,如检测器检测的参数,行程时间,延误,车辆位置信息等等。
在做研究的过程当中,在线的数据往往是我们更需要的。
1.datacollection数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| //实例化一个检测器对象,将检测器ID为1112的数据取出 DataCollection dc = vissim.Net.DataCollections.GetDataCollectionByNumber(1112); for (int i= 1;i<=30000;i++) { Application.DoEvents();//使仿真运行时界面可动 vissim.Simulation.RunSingleStep(); if (i>=600 && i%200==0) { ListViewItem temp = new ListViewItem(); temp.Text = dc.ID.ToString(); temp.SubItems.Add((i / 10).ToString() + "s"); temp.SubItems.Add(dc.GetResult("SPEED", "MEAN", 0).ToString());//获取速度 temp.SubItems.Add(dc.GetResult("NVEHICLES", "sum", 0).ToString());//获取流量 temp.SubItems.Add(dc.GetResult("OCCUPANCYRATE", "sum", 0).ToString());//获取占有率 listView1.Items.Add(temp); } }
|
需要注意的是,datacollection在采集数据的时候是有时间间隔的,这里设置了20S采集一次数据,那么在用COM接口取出数据的时候,20S内的数据都不会更新。
测试结果:
2.route参数修改
在VISSIM中,由于路径是在车辆生成时候就已经确定,且在仿真过程中是无法更改的,所以需要实现VMS的功能,需要通过修改路径的相对转向比来实现。
通过如下命令可修改:
1
| route.get_AttValue1("RELATIVEFLOW",1)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| listView1.Columns.Add("routedecide", 80); listView1.Columns.Add("routesid", 80); listView1.Columns.Add("相对流量",80); listView1.Columns.Add("是否修改", 80); for (int i=1;i<=30000;i++) { Application.DoEvents(); vissim.Simulation.RunSingleStep(); if (i == 1) { for (int j = 1; j <= 9; j++) { foreach (Route route in vissim.Net.RoutingDecisions.GetRoutingDecisionByNumber(j).Routes) { ListViewItem temp = new ListViewItem(); temp.Text = i.ToString(); temp.SubItems.Add(route.ID.ToString()); temp.SubItems.Add(route.get_AttValue1("RELATIVEFLOW", 1).ToString()); temp.SubItems.Add("F"); listView1.Items.Add(temp); } } } if (i%1000==0) { for (int j = 1; j <= 9; j++) { foreach (Route route in vissim.Net.RoutingDecisions.GetRoutingDecisionByNumber(j).Routes) { route.set_AttValue1("RELATIVEFLOW", 1, j); ListViewItem temp = new ListViewItem(); temp.Text = i.ToString(); temp.SubItems.Add(route.ID.ToString()); temp.SubItems.Add(route.get_AttValue1("RELATIVEFLOW", 1).ToString()); temp.SubItems.Add("T"); listView1.Items.Add(temp); } } } }
|
测试结果:
traveltime测试
traveltime与datacollection一样,都是有采集间隔的,在没有到下一个采集间隔时,数据不会更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| listView1.Columns.Add("TTid"); listView1.Columns.Add("TT"); listView1.Columns.Add("NV"); for(int i=1;i<=42000;i++) { Application.DoEvents(); vissim.Simulation.RunSingleStep(); if(i>6000 && i%600==0) { foreach(TravelTime TT in vissim.Net.TravelTimes) { //TravelTime TT = vissim.Net.TravelTimes.GetTravelTimeByNumber(1); ListViewItem temp = new ListViewItem(); temp.Text = TT.ID.ToString(); temp.SubItems.Add(TT.GetResult((double)i / 10, "TRAVELTIME", "", 0).ToString()); temp.SubItems.Add(TT.GetResult((double)i / 10, "NVEHICLES", "", 0).ToString()); listView1.Items.Add(temp); listView1.Items[listView1.Items.Count - 1].EnsureVisible(); } } }
|
测试结果:
小结:
VISSIM对象中的数据读取都大同小异,首先需要对VISSIM熟悉,才能更好的使用COM接口,在需要使用特点的函数时,对应手册进行查询。