• 车联网仿真工具Veins学习1


    准备条件

    假如你是一个小白,先找到相关的参考资料(已根据上一篇博客安装好Veins),主要是官方文档和相关的博客,官方提供了一个example,我找到的资料如下:

    Questions tagged [veins]

    AI助手:
    Chatgpt
    给他一个角色扮演,Veins网络仿真专家,不懂的代码随时扔给它。

    代码架构

    在这里插入图片描述
    antenna.xml #车辆天线配置文件
    config.xml #物理层无线电传播相关参数。默认的配置是信号穿过建筑有衰减,如示例中将信号路径衰落的模型配置为“SmiplePathlossModel”,障碍物引起的信号衰落模型设置为“SimpleObstacleShadowing”,一般使用默认的即可;前期如果不需要这个配置,可以将db-per-cut和db-per-meter都改成0。
    在这里插入图片描述
    erlangen.launched.xml #启动sumo的配置文件,不更改
    erlangen.net.xml # SUMO路网文件,跑自己的仿真时需要替换
    在这里插入图片描述
    erlangen.png #一张地图图片
    在这里插入图片描述
    erlangen.poly.xml:如果SUMO路网文件是由地图转化而来的,如从OpenStreetMap导入的,则路网文件中还将包含所选地区的建筑物的信息,通过SUMO提供的OpenStreetMap Web接口便可生成记录这些建筑物形状、大小和位置信息的配置文件,作为config.xml内信号衰落模型的输入;如果不考虑建筑物对于信号传播的影响则无需此文件,当然config.xml内的信号衰落模型的配置也要删去;简而言之:记录地图中建筑信息的文件
    在这里插入图片描述
    erlangen.rou.xml:交通流文件(大概是生成的小车往哪里走,规划行驶路线)
    erlangen.sumo.cfg: SUMO运行文件,可对运行时长等运行参数进行配置;
    在这里插入图片描述
    omnetpp.ini: OMNeT++运行文件,后文重点讲解;点击左下角的Source就看到源码,默认是Form。
    在这里插入图片描述

    RSUExampleScnario.ned: OMNeT++类似于积木,一个工程项目是由多个ned文件互相嵌套组合而成的。veins作为一个基于OMNeT++的框架,其便是由层次分明的ned文件组合而成的,如果学过面向对象编程的话可能会容易理解一些,这些ned文件就类似一个个类。但是OMNeT++中更为特殊,因为ned文件只是定义了组件的结构,比如定义一辆车,ned只是描述了它包含几个对外通信的接口,这些接口的参数之类的,具体的功能还需要与ned文件同名的C++文件进行定义,比如用这些接口选择与谁进行通信,专业点就叫路由。这里的RSUExampleScnario.ned定义了OMNeT++中最大的结构——网络(network),可以看到在omnetpp.ini中的[General]部分对于本次仿真所运行的网络定义为RSUExampleScenario;
    在这里插入图片描述
    OMNet++独特的ned网络语言需要结合官方文档和相关视频博客开始学习,我将找到的相关资料整理在这:
    OMNeT++ Technical Articles- TicToc Tutorial
    Simulation Manual (pdf)
    视频:
    协议森林主页
    在这里插入图片描述
    OMNet++初学-进阶-精进历程分享
    当然github上也有一个教程及Youtube视频,英文的:VANETTutorials,视频搬到b站了VANET和OMNET++、INET、Veins和SUMO仿真模拟教程。b站也有一些其他的视频,自行搜索。

    omnetpp.ini
    好了,到这网上讲的就不多了,有的是挑关键的讲一讲,这个时候就可以上GPT了,代码一顿喂饱,让它来详细解释一下这段代码:

    General Section:
    cmdenv-express-mode, cmdenv-autoflush, cmdenv-status-frequency, **.cmdenv-log-level:
    这些配置项是有关OMNeT++运行环境的设置,如日志级别、自动刷新等。
    image-path:
    设置了图像文件的路径,通常用于地图等图形可视化。
    network:
    定义了仿真中使用的网络场景。在这里,网络场景是"RSUExampleScenario",这可能是一个您自定义的场景名称。
    Simulation Parameters:
    4. debug-on-errors, print-undisposed, sim-time-limit:
    这些参数控制了仿真的调试行为、是否打印未释放的对象以及仿真的时间限制。
    **.scalar-recording, **.vector-recording:
    启用了标量和矢量数据的记录,以便在仿真运行后进行分析。
    *.playgroundSizeX, *.playgroundSizeY, *.playgroundSizeZ:
    定义了仿真场景的大小,包括X、Y和Z方向。
    Annotation Parameters:
    7. *.annotations.draw:
    控制是否绘制注释信息。通常在可视化仿真结果时使用。
    Obstacle Parameters:
    8. *.obstacles.obstacles:
    使用xmldoc函数引用了一个XML配置文件,该文件定义了障碍物的位置和特性。这些障碍物可以影响通信和车辆移动。
    TraCIScenarioManager Parameters:
    9. 该部分包括了有关TraCI(交通控制接口)的参数,用于与仿真管理器进行通信。
    RSU Settings:
    10. 这一部分设置了RSU的参数,包括位置坐标、应用程序类型、通信参数等。这定义了RSU的行为和通信方式。
    11p Specific Parameters:
    11. 这部分包括了与IEEE 802.11p通信标准相关的参数,如发送距离、发射功率、信噪比等。
    App Layer:
    12. 这一部分设置了应用层的参数,包括应用程序类型、数据传输设置等。
    Mobility:
    13. 这一部分定义了车辆的移动行为,包括位置坐标、速度等。还包括了车辆事故的设置。
    Config Default and Other Configurations:
    14. 最后,提供了一些配置块,用于定义不同的仿真配置。例如,"Config WithBeaconing"启用了RSU和车辆发送信标。
    这段配置文件定义了Veins仿真的各种设置,从基本的仿真参数到车辆和RSU的通信参数,以及特定的应用层和移动行为设置。
    
    • 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

    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的ned文件
    在这里插入图片描述
    在这里插入图片描述

    这段代码定义了一个Veins仿真中的RSU(Roadside Unit)模块,模块名为"RSU"。让我为您逐行解释这段代码的含义:
    package org.car2x.veins.nodes;:
    这行代码指定了模块所在的Java包(package)。该模块位于org.car2x.veins.nodes包中。
    import org.car2x.veins.base.modules.*;import org.car2x.veins.modules.nic.Nic80211p;:
    这些是Java的import语句,用于引入所需的Java类和模块。
    module RSU:
    这行代码定义了一个RSU模块。
    parameters::
    这个部分用于定义模块的参数,包括applType和nicType。
    string applType;:
    这个参数定义了应用层的类型(applType)。在Veins中,应用层类型通常用于定义RSU的应用程序行为。
    string nicType = default("Nic80211p");:
    这个参数定义了网络接口卡的类型(nicType)。默认情况下,它被设置为"Nic80211p",这是IEEE 802.11p标准的网络接口卡类型。
    gates::
    这个部分用于定义模块的输入和输出门(gates)。在这里,定义了一个输入门veinsradioIn,用于sendDirect。
    submodules::
    这个部分用于定义模块的子模块。在这里,定义了三个子模块:appl、nic和mobility。
    appl: <applType> like org.car2x.veins.base.modules.IBaseApplLayer:
    这行代码定义了appl子模块,其类型是根据applType参数动态选择的应用层类型。这种方式允许根据仿真配置选择不同的应用层实现。
    nic: <nicType> like org.car2x.veins.modules.nic.INic80211p:
    这行代码定义了nic子模块,其类型是根据nicType参数动态选择的网络接口卡类型。同样,这种方式允许根据仿真配置选择不同的网络接口卡实现。
    mobility: BaseMobility:
    这行代码定义了mobility子模块,它是基本移动性模块。
    connections::
    这个部分用于定义模块之间的连接。在这里,定义了一系列连接,将nic和appl模块之间的输入输出连接起来,以及将veinsradioIn连接到nic模块的radioIn门。
    这段代码定义了一个RSU模块,其中包括应用层、网络接口卡和移动性模块。模块的类型和连接方式可以根据参数(如applType和nicType)进行动态配置,使得Veins仿真更加灵活和可定制。这是Veins中定义模块的一种典型方式。
    
    • 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

    11p specific parameters NIC-Settings:对MAC层ned(nic)相关参数做出设置,nic包含两个子ned(mac1609_4和phy80211p)。至于connectionManager基本保持不变,如果要研究信号传播范围的影响的话,需要改变maxInterfDist;
    在这里插入图片描述
    在这里插入图片描述

    package org.car2x.veins.modules.nic;
    
    import org.car2x.veins.modules.phy.PhyLayer80211p;
    import org.car2x.veins.modules.mac.ieee80211p.Mac1609_4;
    
    //
    // This NIC implements an 802.11p network interface card.
    //
    // @author David Eckhoff
    //
    // @see DemoBaseApplLayer
    // @see Mac1609_4
    // @see PhyLayer80211p
    //
    module Nic80211p like INic80211p
    {
        parameters:
            string connectionManagerName = default("connectionManager");
        gates:
            input upperLayerIn; // to upper layers
            output upperLayerOut; // from upper layers
            output upperControlOut; // control information
            input upperControlIn; // control information
            input radioIn; // radioIn gate for sendDirect
    
        submodules:
            phy80211p: PhyLayer80211p {
                @display("p=69,218;i=block/process_s");
            }
    
            mac1609_4: Mac1609_4 {
                @display("p=69,82");
            }
    
        connections:
            radioIn --> phy80211p.radioIn;
    
            mac1609_4.lowerControlOut --> phy80211p.upperControlIn;
            mac1609_4.lowerLayerOut --> phy80211p.upperLayerIn;
            phy80211p.upperLayerOut --> mac1609_4.lowerLayerIn;
            phy80211p.upperControlOut --> mac1609_4.lowerControlIn;
            
            mac1609_4.upperControlIn <-- upperControlIn;
            mac1609_4.upperLayerIn <-- upperLayerIn;
    
            mac1609_4.upperLayerOut --> upperLayerOut;
            mac1609_4.upperControlOut --> upperControlOut;
    }
    
    • 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
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    这段代码定义了一个名为Nic80211p的Veins仿真模块,它是一个实现了IEEE 802.11p网络接口卡(NIC)的模块。让我为您逐行解释这段代码的含义:
    
    package org.car2x.veins.modules.nic;:
    
    这行代码指定了模块所在的Java包(package),这个模块位于org.car2x.veins.modules.nic包中。
    import org.car2x.veins.modules.phy.PhyLayer80211p;import org.car2x.veins.modules.mac.ieee80211p.Mac1609_4;:
    
    这些是Java的import语句,用于引入所需的Java类和模块。
    module Nic80211p like INic80211p:
    
    这行代码定义了一个Veins仿真模块,名称为Nic80211p,并指定它实现了INic80211p接口。这意味着Nic80211p模块应该包括了符合802.11p标准的NIC功能。
    parameters::
    
    这个部分用于定义模块的参数,包括connectionManagerName。
    string connectionManagerName = default("connectionManager");:
    
    这个参数定义了连接管理器的名称,默认为"connectionManager"。
    gates::
    
    这个部分用于定义模块的输入和输出门(gates)。在这里,定义了输入门upperLayerIn、输出门upperLayerOut、输出门upperControlOut、输入门upperControlIn和输入门radioIn。
    submodules::
    
    这个部分用于定义模块的子模块。在这里,定义了两个子模块:phy80211p和mac1609_4。
    phy80211p: PhyLayer80211p:
    
    这行代码定义了phy80211p子模块,它表示802.11p物理层。
    mac1609_4: Mac1609_4:
    
    这行代码定义了mac1609_4子模块,它表示802.11p MAC层(Mac1609_4)。
    connections::
    
    这个部分用于定义模块之间的连接关系。连接包括将radioIn连接到phy80211p模块的radioIn门,以及将mac1609_4和phy80211p模块之间的输入和输出连接起来,以实现数据和控制信息的传输。
    总的来说,这段代码定义了一个802.11p网络接口卡(NIC)模块,它包括了物理层(PhyLayer80211p)和MAC层(Mac1609_4)子模块。这种模块结构反映了802.11p标准中NIC的组成部分。这个NIC模块可以在Veins仿真中用于模拟车辆之间的通信和数据传输。 Veins允许用户根据具体仿真需求自定义NIC模块,以适应不同的研究场景。
    
    • 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

    App Layer: 对移动节点(车辆)的应用层做出设置,和RSU一个道理;
    在这里插入图片描述
    Mobility: 对移动节点的移动模块做出设置。其中accidentCount、accidentStart、accidentDuration这三个参数是对移动节点发生事故的事件做出设置,这是veins的examples演示的功能(事故预警消息的传播),我们用不到直接令accidentCount=0即可。
    在这里插入图片描述
    最后一个RSUExampleScnario.ned
    在这里插入图片描述
    在这里插入图片描述
    看ned文件的import、extends往上慢慢捋就行。
    看代码可以发现RSUExampleScnario内加入了一个RSU单元。
    ned定义结构,同名C++文件定义功能。
    从新啰嗦一遍,梳理一下:

    从RSUExampleScenario.ned开始逐级往上,读懂代码并了解其用法。
    点开RSUExampleScenario.ned可知网络主要继承于Scenario
    除了继承的Scenario,RSUExampleScenario还定义了一个RSU,分别从这两个方向往上逐级深入:
    Annotations
    标注注解,暂不深入

    World
    提供一些整个项目可用的函数,暂不深入
    在这里插入图片描述
    Scenario
    Scenario提供预制的Annotations,World,Manager,Obstacles,ConnectionManager和Node模块。其中Node就是车辆模块。
    在这里插入图片描述

    这段代码定义了一个名为"Scenario"的Veins仿真网络。这个网络表示一个仿真场景,其中包括了道路、车辆、通信和可视化等元素。我将逐行解释这段代码的含义:
    
    package org.car2x.veins.nodes;:
    
    这行代码指定了模块所在的Java包(package),这个模块位于org.car2x.veins.nodes包中。
    import org.car2x.veins.base.connectionManager.ConnectionManager; 和其他import语句:
    
    这些是Java的import语句,用于引入所需的Java类和模块。
    network Scenario:
    
    这行代码定义了一个名为"Scenario"的Veins仿真网络。
    parameters::
    
    这个部分用于定义网络的参数,包括仿真区域的大小(playgroundSizeX、playgroundSizeY、playgroundSizeZ)以及显示设置。
    double playgroundSizeX @unit(m);:
    
    定义了仿真区域的X轴尺寸,单位是米。
    double playgroundSizeY @unit(m);:
    
    定义了仿真区域的Y轴尺寸,单位是米。
    double playgroundSizeZ @unit(m);:
    
    定义了仿真区域的Z轴尺寸,单位是米。通常,这代表仿真场景的高度。
    @display("bgb=$playgroundSizeX,$playgroundSizeY");:
    
    这行代码通过@display注解定义了仿真区域的显示设置,使用了playgroundSizeX和playgroundSizeY参数来确定显示的边界框。
    submodules::
    
    这个部分用于定义网络中的子模块。
    obstacles: ObstacleControl:
    
    定义了一个名为obstacles的子模块,它是用于控制障碍物的模块。这些障碍物可以影响车辆的移动和通信。
    annotations: AnnotationManager:
    
    定义了一个名为annotations的子模块,用于管理注释信息,通常在仿真可视化中使用。
    connectionManager: ConnectionManager:
    
    定义了一个名为connectionManager的子模块,用于管理仿真中的连接和通信。
    world: BaseWorldUtility:
    
    定义了一个名为world的子模块,它表示仿真中的世界,包括地图和其他环境元素。
    manager: TraCIScenarioManagerLaunchd:
    
    定义了一个名为manager的子模块,它是TraCI(交通控制接口)场景管理器的启动模块,用于与外部TraCI客户端通信。
    roadsCanvasVisualizer: RoadsCanvasVisualizer:
    
    定义了一个名为roadsCanvasVisualizer的子模块,用于可视化仿真中的道路和车辆。
    node[0]: Car:
    
    定义了一个名为node[0]的节点,类型为Car。这是仿真中的一个车辆节点。
    connections allowunconnected::
    
    这个部分用于定义模块之间的连接关系,允许未连接的连接。
    总的来说,这段代码定义了一个包含了多个子模块的Veins仿真网络,用于模拟车辆通信、移动和可视化等行为。这个仿真场景可以根据参数进行配置,包括仿真区域的大小和显示设置。 Veins允许用户创建复杂的仿真场景,以研究车辆通信和智能交通系统的各种方面。
    
    • 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
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    Manager
    这个是与sumo-launchd.py脚本交互的类,实现与SUMO通信。主要是对小车的仿真。主要的的函数实现在src/veins/modules/mobility/traci/TraCICommandInterface.cc文件内;与SUMO交互的接口函数在同目录下的TraCIConnection.cc内。
    Obstacles
    ObstacleControl即障碍的控制类。障碍会阻碍信号传播,均为多边形(polygon)。相关类文件在src/veins/modules/obstacle/内,障碍的位置通过前文提到的erlangen.poly.xml定义。

    config.xml中的obstacles标签下定义了信号传输的衰减,默认的设置会导致信号穿过建筑后衰减为0,这解释了为什么前文运行例子的时候有些小车没有及时收到信息。

    Node (Car)
    Node是一个元素类型为Car的数组,也就是仿真需要的所有车辆。
    Car有三个模块分别是

    appl 应用层
    nic MAC层
    veinsmobility 移动驱动层
    其中nic定义了上下层的接口,可以不作修改

    而veinsmobility定义了底层,包括位置速度参数等,定义函数比如获取速度,前往下一个坐标等,可以修改/替换,至少需要实现IMobility这个接口

    例子中的apply应用层是TraCIDemo11p.cc只是定义了几个简单的消息处理函数,开发中需要自己添加其他功能
    在这里插入图片描述
    在这里插入图片描述

    这段代码定义了一个Veins仿真中的车辆模块,模块名为"Car"。让我为您逐行解释这段代码的含义:
    
    package org.car2x.veins.nodes;:
    
    这行代码指定了模块所在的Java包(package),这个模块位于org.car2x.veins.nodes包中。
    import org.car2x.veins.base.modules.*;import org.car2x.veins.modules.nic.Nic80211p;:
    
    这些是Java的import语句,用于引入所需的Java类和模块。
    module Car:
    
    这行代码定义了一个车辆模块,模块名为"Car"。
    parameters::
    
    这个部分用于定义模块的参数,包括applType、nicType和veinsmobilityType。
    string applType;:
    
    这个参数定义了应用层的类型(applType)。在Veins中,应用层类型通常用于定义车辆的应用程序行为。
    string nicType = default("Nic80211p");:
    
    这个参数定义了网络接口卡的类型(nicType)。默认情况下,它被设置为"Nic80211p",这是IEEE 802.11p标准的网络接口卡类型。
    string veinsmobilityType = default("org.car2x.veins.modules.mobility.traci.TraCIMobility");:
    
    这个参数定义了车辆移动性模块的类型(veinsmobilityType)。默认情况下,它被设置为TraCIMobility,这是基于TraCI的移动性模块。
    gates::
    
    这个部分用于定义模块的输入和输出门(gates)。在这里,定义了一个输入门veinsradioIn,用于sendDirect。
    submodules::
    
    这个部分用于定义模块的子模块。在这里,定义了三个子模块:appl、nic和veinsmobility。
    appl: <applType> like org.car2x.veins.base.modules.IBaseApplLayer:
    
    这行代码定义了appl子模块,其类型是根据applType参数动态选择的应用层类型。这种方式允许根据仿真配置选择不同的应用层实现。
    nic: <nicType> like org.car2x.veins.modules.nic.INic80211p:
    
    这行代码定义了nic子模块,其类型是根据nicType参数动态选择的网络接口卡类型。同样,这种方式允许根据仿真配置选择不同的网络接口卡实现。
    veinsmobility: <veinsmobilityType> like org.car2x.veins.base.modules.IMobility:
    
    这行代码定义了veinsmobility子模块,其类型是根据veinsmobilityType参数动态选择的移动性模块类型。
    connections::
    
    这个部分用于定义模块之间的连接。连接包括将veinsradioIn连接到nic模块的radioIn门,以及将nic和appl模块之间的输入输出连接起来,以实现数据和控制信息的传输。
    总的来说,这段代码定义了一个车辆模块,包括了应用层、网络接口卡和移动性模块。模块的类型和连接方式可以根据参数(如applType、nicType和veinsmobilityType)进行动态配置,使得Veins仿真更加灵活和可定制。这是Veins中定义模块的一种典型方式。
    
    • 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
    • 41
    • 42
  • 相关阅读:
    面试系列-Springboot 自定义starter使用详解
    有关测试的思考:决定软件测试的那只无形的手
    计算机专业应该学哪些课程?或许我们还有更大的进步空间
    Windows安装Linux子系统
    机器学习——决策树
    从文件里一次读取一行
    【Koltin Flow(三)】Flow操作符之中间操作符(一)
    JVM(十七)—— 垃圾回收(三)
    油猴脚本(JavaScript)-练手-简单的随机音乐播放器
    Python 算法交易实验41 GMM简单估计
  • 原文地址:https://blog.csdn.net/weixin_43835470/article/details/132678540