Veins入门教程——教你如何下手研究

目录

注意:写着写着发现要讲的实在太多了,实在没精力了,后面就只会提重点了,可能显得虎头蛇尾,但本文只是提点入门,最重要的还是自己去琢磨,不可能一篇博客就包教会。还有学之前先学会C++。

Veins是一款用于车载移动环境下无线通信仿真的开源框架,其对于车载无线网的底层结构,如物理层、MAC层等基于802.11p协议已基本开发完善,因此在此基础上进行二次开发,如改进MAC层协议或者路由协议等研究都是非常便携的。甚至如果是进行应用层上的研究,如车联网环境下的车辆自动驾驶、编队行驶、路径规划、信号灯区域协调等则更加方便,因为底层的结构可以直接使用,不必再浪费时间精力在这些并不是需要主要研究但却又对仿真结果影响重大的部分。

Veins的好处很多,一旦掌握可以节省大量的开发时间,得到更加准确的仿真实验结果,为自己的理论提供更加权威可靠的支持。但是Veins的相关教程却寥寥无几,除了官网上的一份运行其内置示例的教程外很难再寻找到其他相关教程,因此很多人打开Veins后面对密密麻麻的C++代码难以下手,望而却步。博主因为学业所需对其进行过一段时间的研究,真是万分痛苦!在此将自己的研究经验经过整理得到一份入门级教程奉献给大家,愿大家都能早日脱离苦海。

看教程之前先确定自己已经把官网上的内置示例的教程运行成功了。

废话少说!

首先在OMNeT++的IDE左侧有如下图所示的窗口,打开veins的项目(博主拿二次开发过的程序在讲解,可能会比纯净版多出一些文件,大家不要在意),veins内置的示例就在文件夹examples内:

  • antenna.xml:对车辆天线做出配置,不用管;
  • config.xml:配置物理层无线电传播相关参数,如示例中将信号路径衰落的模型配置为“SmiplePathlossModel”,障碍物引起的信号衰落模型设置为“SimpleObstacleShadowing”,一般使用默认的即可;
 <?xml version="1.0" encoding="UTF-8"?>
<root>
<AnalogueModels>
<AnalogueModel type="SimplePathlossModel">
<parameter name="alpha" type="double" value="2.0"/>
<parameter name="carrierFrequency" type="double" value="5.890e+9"/>
</AnalogueModel>
<AnalogueModel type="SimpleObstacleShadowing">
<parameter name="carrierFrequency" type="double" value="5.890e+9"/>
<obstacles>
<type id="building" db-per-cut="9" db-per-meter="0.4" />
</obstacles>
</AnalogueModel>
</AnalogueModels>
<Decider type="Decider80211p">
<!-- The center frequency on which the phy listens-->
<parameter name="centerFrequency" type="double" value="5.890e9"/>
</Decider>
</root>
  • debug:调试信息,不用管;
  • erlangen.launchd.xml:建立与SUMO的通信,不能更改;
  • erlangen.net.xml: SUMO路网文件,跑自己的仿真时需要替换,至于如何生成请参考SUMO官网文档
  • erlangen.poly.xml:如果SUMO路网文件是由地图转化而来的,如从OpenStreetMap导入的,则路网文件中还将包含所选地区的建筑物的信息,通过SUMO提供的OpenStreetMap Web接口便可生成记录这些建筑物形状、大小和位置信息的配置文件,作为config.xml内信号衰落模型的输入;如果不考虑建筑物对于信号传播的影响则无需此文件,当然config.xml内的信号衰落模型的配置也要删去;
 <?xml version="1.0" encoding="UTF-8"?>
<root>
<AnalogueModels>
<AnalogueModel type="SimplePathlossModel">
<parameter name="alpha" type="double" value="2.0"/>
<parameter name="carrierFrequency" type="double" value="5.890e+9"/>
</AnalogueModel>
</AnalogueModels>
<Decider type="Decider80211p">
<!-- The center frequency on which the phy listens-->
<parameter name="centerFrequency" type="double" value="5.890e9"/>
</Decider>
</root>
  • erlangen.rou.xml:交通流文件,如何生成也请查阅SUMO官网文档,不再赘述;
  • erlangen.sumo.cfg: SUMO运行文件,可对运行时长等运行参数进行配置;
  • omnetpp.ini: OMNeT++运行文件,后文重点讲解;
  • RSUExampleScnario.ned: OMNeT++类似于积木,一个工程项目是由多个ned文件互相嵌套组合而成的。veins作为一个基于OMNeT++的框架,其便是由层次分明的ned文件组合而成的,如果学过面向对象编程的话可能会容易理解一些,这些ned文件就类似一个个。但是OMNeT++中更为特殊,因为ned文件只是定义了组件的结构,比如定义一辆车,ned只是描述了它包含几个对外通信的接口,这些接口的参数之类的,具体的功能还需要与ned文件同名的C++文件进行定义,比如用这些接口选择与谁进行通信,专业点就叫路由。对于OMNet++独特的ned网络语言大家还是踏踏实实看OMNeT++官方手册学习吧。一开始可能找不到头绪,所以建议大家去听听这个OMNeT++基础讲解的视频课程(要学的东西是不是很多?是不是很烦?)。这里的RSUExampleScnario.ned定义了OMNeT++中最大的结构——网络(network),可以看到在omnetpp.ini中的[General]部分对于本次仿真所运行的网络定义为RSUExampleScenario;
 [General]
cmdenv-express-mode = true
cmdenv-autoflush = true
cmdenv-status-frequency = 1s
**.cmdenv-log-level = info ned-path = .
image-path = ../../images network = RSUExampleScenario

讲解omnetpp.ini!(挑关键的)

  • network:非常关键的参数,需要替换成自己的network级ned文件;
  • sim-time-limit: 网络仿真时间限制,注意与SUMO生成的交通流运行时长对应;
  • RSU SETTINGS:RSUExampleScnario.ned中的路侧单元ned中的参数做出设置。其中最重要的就是applType,它指定了RSU的应用层,也就是RSU会做什么。其实RSU也是一个ned文件,比network级低,它是由另外几个更低级的ned组成的,包括作为应用层的ned(appl),作为MAC层的ned(nic),作为移动驱动的ned(mobility)。applType指定的就是应用层的ned,而应用层ned的功能又由其同名且在同一个文件夹的C++文件定义,这样RSU的功能也就确定了,做应用层研究的要改变的就是这个应用层的ned与对应的C++文件。至于后面那些参数都是对于应用层ned中的一些参数做出设置,比如.rsu[*].appl.beaconUserPriority = 7就是令所有RSU应用层的信标优先级为7,这个就不要再问了,做车联网的这个还不懂就别玩了。
 ##########################################################
# RSU SETTINGS #
# #
# #
##########################################################
*.rsu[0].mobility.x = 2000
*.rsu[0].mobility.y = 2000
*.rsu[0].mobility.z = 3 *.rsu[*].applType = "TraCIDemoRSU11p"
*.rsu[*].appl.headerLength = 80 bit
*.rsu[*].appl.sendBeacons = true
*.rsu[*].appl.dataOnSch = false
*.rsu[*].appl.beaconInterval = 1s
*.rsu[*].appl.beaconUserPriority = 7
*.rsu[*].appl.dataUserPriority = 5

  • 11p specific parameters NIC-Settings:对MAC层ned(nic)相关参数做出设置,nic包含两个子ned(mac1609_4和phy80211p)。至于connectionManager基本保持不变,如果要研究信号传播范围的影响的话,需要改变maxInterfDist
 ##########################################################
# 11p specific parameters #
# #
# NIC-Settings #
##########################################################
*.connectionManager.sendDirect = true
*.connectionManager.maxInterfDist = 2600m
*.connectionManager.drawMaxIntfDist = false *.**.nic.mac1609_4.useServiceChannel = false *.**.nic.mac1609_4.txPower = 20mW
*.**.nic.mac1609_4.bitrate = 6Mbps
*.**.nic.phy80211p.sensitivity = -89dBm *.**.nic.phy80211p.useThermalNoise = true
*.**.nic.phy80211p.thermalNoise = -110dBm *.**.nic.phy80211p.decider = xmldoc("config.xml")
*.**.nic.phy80211p.analogueModels = xmldoc("config.xml")
*.**.nic.phy80211p.usePropagationDelay = true *.**.nic.phy80211p.antenna = xmldoc("antenna.xml", "/root/Antenna[@id='monopole']")

  • WaveAppLayer: 对移动节点(车辆)的应用层做出设置,和RSU一个道理;
 ##########################################################
# WaveAppLayer #
##########################################################
*.node[*].applType = "TraCIDemo11p"
*.node[*].appl.headerLength = 80 bit
*.node[*].appl.sendBeacons = true
*.node[*].appl.dataOnSch = false
*.node[*].appl.beaconInterval = 1s
  • Mobility: 对移动节点的移动模块做出设置。其中accidentCount、accidentStart、accidentDuration这三个参数是对移动节点发生事故的事件做出设置,这是veins的examples演示的功能(事故预警消息的传播),我们用不到直接令accidentCount=0即可。
 ##########################################################
# Mobility #
##########################################################
*.node[*].veinsmobilityType.debug = true
*.node[*].veinsmobility.x = 0
*.node[*].veinsmobility.y = 0
*.node[*].veinsmobility.z = 1.895
*.node[*0].veinsmobility.accidentCount = 1
*.node[*0].veinsmobility.accidentStart = 75s
*.node[*0].veinsmobility.accidentDuration = 50s

讲解RSUExampleScnario.ned!

这里只挑最重要的讲,其余的自己看ned文件的import、extends往上慢慢捋就行。

看代码可以发现RSUExampleScnario内加入了一个RSU单元。

 import org.car2x.veins.nodes.RSU;
import org.car2x.veins.nodes.Scenario; network RSUExampleScenario extends Scenario
{
submodules:
rsu[1]: RSU {
@display("p=150,140;i=veins/sign/yellowdiamond;is=vs");
}
}

那么下面官网上的示例动图里的移动节点是怎么加入的呢?

其实是通过TraCIScenarioManagerLaunchd.ned这个模块加入的

 package org.car2x.veins.modules.mobility.traci;

 //
// Extends the TraCIScenarioManager for use with sumo-launchd.py and SUMO.
//
// Connects to a running instance of the sumo-launchd.py script
// to automatically launch/kill SUMO when the simulation starts/ends.
//
// All other functionality is provided by the TraCIScenarioManager. simple TraCIScenarioManagerLaunchd
{
parameters:
@display("i=block/network2");
@class(Veins::TraCIScenarioManagerLaunchd);
bool debug = default(false); // emit debug messages?
double connectAt @unit("s") = default(0s); // when to connect to TraCI server (must be the initial timestep of the server)
double firstStepAt @unit("s") = default(-1s); // when to start synchronizing with the TraCI server (-1: immediately after connecting)
double updateInterval @unit("s") = default(1s); // time interval of hosts' position updates
string moduleType = default("org.car2x.veins.nodes.Car"); // module type to be used in the simulation for each managed vehicle
string moduleName = default("node"); // module name to be used in the simulation for each managed vehicle
// module displayString to be used in the simulation for each managed vehicle
// display strings key-value pairs needs to be protected with single quotes, as they use an = sign as the type mappings. For example
// <pre>
// *.manager.moduleDisplayString = "'i=block/process'"
// *.manager.moduleDisplayString = "a='i=block/process' b='i=misc/sun'"
// </pre>
//
// moduleDisplayString can also be left empty:
// <pre>
// *.manager.moduleDisplayString = ""
// </pre>
string moduleDisplayString = default("*='i=veins/node/car;is=vs'");
string host = default("localhost"); // sumo-launchd.py server hostname
int port = default(9999); // sumo-launchd.py server port
xml launchConfig; // launch configuration to send to sumo-launchd.py
int seed = default(-1); // seed value to set in launch configuration, if missing (-1: current run number)
bool autoShutdown = default(true); // Shutdown module as soon as no more vehicles are in the simulation
int margin = default(25); // margin to add to all received vehicle positions
string roiRoads = default(""); // which roads (e.g. "hwy1 hwy2") are considered to consitute the region of interest, if not empty
string roiRects = default(""); // which rectangles (e.g. "0,0-10,10 20,20-30,30) are considered to consitute the region of interest, if not empty. Note that these rectangles have to use TraCI (SUMO) coordinates and not OMNeT++. They can be easily read from sumo-gui.
double penetrationRate = default(1); //the probability of a vehicle being equipped with Car2X technology
int numVehicles = default(0);
bool useRouteDistributions = default(false);
int vehicleRngIndex = default(0); // index of the RNG stream to be used, all random numbers concerning the managed vehicles
}

其中下面一行代码定义了RSUExampleScnario.ned这个network中加入的移动节点。往上一层层捋就很容易发现,RSUExampleScnario继承自Scnario,Scnario又import了TraCIScenarioManagerLaunchd。

 string moduleType = default("org.car2x.veins.nodes.Car");

到此为止,入门结束,剩下的具体功能实现请进入src/veins/nodes文件夹,仔细琢磨其中的ned文件并一层层往上捋即可。最后再啰嗦一句,ned定义结构,同名C++文件定义功能,明白这一点其实就没问题了。

Veins(车载通信仿真框架)入门教程的更多相关文章

  1. Veins(车载通信仿真框架)入门教程(四)——调试及记录结果

    Veins(车载通信仿真框架)入门教程(四)——调试及记录结果 在Veins入门教程(三)最后的动图中(如下图)可以看到大大小小的光圈,这个怎么实现的呢? 很简单,以收到RTS消息为例,通过finHo ...

  2. Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导

    Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导 Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导 必要的message类实现 从下面开始是在veins/src/vei ...

  3. Veins(车载通信仿真框架)入门教程(二)——调用第三方库

    Veins(车载通信仿真框架)入门教程(二)——调用第三方库 在借助Veins进行自己的研究时我们经常需要实现一些比较复杂的功能,有时就需要借助第三方库的帮助. 博主的研究需要使用神经网络,但是自己编 ...

  4. Go-Micro框架入门教程(一)---框架结构

    Go语言微服务系列文章,使用golang实现微服务,这里选用的是go-micro框架,本文主要是对该框架的一个架构简单介绍. 1. 概述 go-micro是go语言下的一个很好的微服务框架. 1.服务 ...

  5. CodeIgniter框架入门教程——第一课 Hello World!

    本文转载自:http://www.softeng.cn/?p=45 今天开始,我将在这里连载由我自己编写的<CodeIgniter框架入门教程>,首先,这篇教程的读着应该是有PHP基础的编 ...

  6. Java - Struts框架教程 Hibernate框架教程 Spring框架入门教程(新版) sping mvc spring boot spring cloud Mybatis

    https://www.zhihu.com/question/21142149 http://how2j.cn/k/hibernate/hibernate-tutorial/31.html?tid=6 ...

  7. scrapy爬虫框架入门教程

    scrapy安装请参考:安装指南. 我们将使用开放目录项目(dmoz)作为抓取的例子. 这篇入门教程将引导你完成如下任务: 创建一个新的Scrapy项目 定义提取的Item 写一个Spider用来爬行 ...

  8. Scrapy 框架 入门教程

    Scrapy入门教程 在本篇教程中,我已经安装好Scrapy 本篇教程中将带您完成下列任务: 创建一个Scrapy项目 定义提取的Item 编写爬取网站的 spider 并提取 Item 编写 Ite ...

  9. Netty学习_Netty框架入门教程:Netty入门之HelloWorld实现

    我们可能都学过Socket通信/io/nio/aio等的编程.如果想把Socket真正的用于实际工作中去,那么还需要不断的完善.扩展和优化.比如很经典的Tcp读包写包问题,或者是数据接收的大小,实际的 ...

随机推荐

  1. 前端基础-BOM和DOM学习

    JavaScript分为 ECMAScript,BOM,DOM. BOM:是指浏览器对象模型,使JavaScript有能力与浏览器进行对象. DOM:是指文档对象模型,通过它,可以访问HTML文档的所 ...

  2. 『嗨威说』算法设计与分析 - STL中Sort函数的实现原理初探

    本文索引目录: 一.对Sort算法实现的个人阅读体会 二.Sort算法使用的三个排序算法的优点介绍 2.1 插入排序的优缺点 2.2 堆排序的优缺点 2.3 快速排序的优缺点 2.4 新的结合排序—— ...

  3. Wordpress设置Pretty Permalink的方法

    设置Wordpress的Pretty Permalink的关键点莫过于下面几点(本文是基于Apache httpd服务器). 1.Apache httpd要有rewrite module 在httpd ...

  4. SpringBootSecurity学习(06)网页版登录方法级别的权限

    用户授权 前面讨论过,Web应用的安全管理,主要包括两个方面的内容,一个是用户身份的认证,即用户登录的设计,二是用户授权,即一个用户在一个应用系统中能够执行哪些操作的权限管理.前面介绍了登录,下面简单 ...

  5. myql忽略大小写问题解决

    linux系统下启动mysql默认是区分大小写的,如果刚好项目中使用的表名与数据库中表名大小写有冲突,此时就需要忽略mysql表名大小写了. 解决方式一: 1.关闭数据库 mysqladmin -ur ...

  6. 《Java语言程序设计》编程练习8.9(游戏:#字游戏)

    8.9 (游戏:#字游戏)在并字游戏中,两个玩家使用各自的标志(一方用X则另一方就用O),轮流填写3x3的网格中的某个空格.当一个玩家在网格的水平方向.垂直方向或者对角线方向上出 现了三个相同的X或三 ...

  7. WebSocket协议与抓包

    WebSocket协议 WebSocket并不是全新的协议,而是利用了HTTP协议来建立连接,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器 ...

  8. java中的Overload和Override

    Overload为重载,它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法 然后再调用时,就会根据不同的参数样式,来选择合适的方法执行 在使用重载时只能通过不同的参数样式. 例 ...

  9. 教你如何判断URL的好坏

    1.最核心-网站整体内容质量2.关键词整理拓展及关键词布局3.网站外部链接建设4.网站内链建设合理5.面包屑导航6.友情链接7.404页面网站的SEO站外优化+SEO外链建设 层级:三层为好,301重 ...

  10. SEER流量众筹模块开发测试网络及使用文档发布

    SEER利用区块链奖励机制,可解决传统体育赛事痛点,提高行业运转效率.比如提高赛事方收入,让观众自由选择想看的比赛,给予赛事众筹的参与者贡献影响力,使其获得由智能合约量化的激励等.此功能可广泛应用于包 ...