前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >omnet++,veins车辆间消息的传输、车辆运动信息获取

omnet++,veins车辆间消息的传输、车辆运动信息获取

原创
作者头像
PERSEUS
修改2023-11-01 20:32:50
4050
修改2023-11-01 20:32:50
举报
文章被收录于专栏:车联网仿真

本文介绍V2X消息的传输和事件的安排及调度。

1、定义自己的消息内容:

1.1、定义.msg文件:

加入自己需要传递的信息,以我之前的实验内容中的beacon为例:

代码语言:javascript
复制
cplusplus{{
#import "veins/base/utils/Coord.h"
#import "veins/modules/utility/Consts80211p.h"
}};

// namespace Veins;

class noncobject Coord;

packet Beacon {
	//id of the originator
	int vehicleId = 0;
	//id of the sender. relayerId == vehicleId on first hope
	double v = 0;
	double a= 0;
	double x = 0;
	double y = 0;
	double l = 0;
	//double speedX = 0;
	//double speedY = 0;
	double ang = 0;
	double speed[100];
	double acceleration[100];
	Coord position[100];
	double angle[100];
    double beaconrate[100];
    double cp[100];  //collision probability
    Coord slotpos;
    simtime_t timestamp = 0;
}

1.2、Bulid Project生成Beacon_m.h和Beacon_m.cc文件:

生成的类提供了获取消息内容的接口,即get和set函数,和.msg中的内容是对应的。

1.3引用:

在头文件中引用消息的类Beacon_m.h:

代码语言:javascript
复制
#include "veins/modules/messages/Beacon_m.h"

2、消息的发送:

2.1、定义自消息:

在你需要实现发送和接收的层的实现类中定义自消息并完成Beacon消息发送的安排。如我需要在应用层发送和接收beacon消息,使用的实现类是veins提供的MyVeinsApp。

首先在头文件中声明自消息,如:

代码语言:javascript
复制
cMessage* sendBeacon; ​

然后在.cc中initialize的stage == 0(也可以在该自消息被调度之前)中初始化自消息:

代码语言:javascript
复制
sendBeacon = new cMessage("send Beacon");

接着,在initialize的stage == 1中调度自消息,在给定的时间执行给定的自消息:

代码语言:javascript
复制
if(strcmp(this->getParentModule()->getName(),"human") == 0){
    scheduleAt(SimTime(5),sendBeacon);
}

上面表示名为human的车辆在模拟时间第5s执行sendBeacon这个自消息。

2.2、消息内容的设置及消息的发送:

在开始之前说一下,MyVeinsApp.cc这个类重写了父类的handleSelfMsg,(所有重写的函数都需要实现,否则报错)。所有schedule的自消息都在给定的时间在handleSelfMsg这个函数里实现如:

  • 首先,我相信最常用的信息是车辆的动力学信息,如何获取它:
代码语言:javascript
复制
cModule* vehicle = getParentModule();
Veins::TraCIMobility* traci = dynamic_cast<Veins::TraCIMobility*>(vehicle->getSubmodule("veinsmobility", 0));
Veins::TraCICommandInterface::Vehicle* traciVehicle = traci->getVehicleCommandInterface();​

第一行获取了车辆的模型,因为app层所属是车辆,如果是mac层或者phy层,所属nic,nic所属车辆,需要:

代码语言:javascript
复制
cModule* vehicle = getParentModule()->getParentModule();

NOTE1,如果你想通过场景模块获取其他车辆的信息(不推荐这样做,因为这样通信就没有意义了,现实中也不可能,确实遇到困难才这么做,或者为了方便),直接车辆模块getParentModule()就是场景模块,场景的子模块当然有所有车辆和RSU:

代码语言:javascript
复制
/*检测车辆数量*/
int Mac1609_4::getCarNumber(){
    int num = 0;
    int i=0;
    cModule* nic = getParentModule();
    cModule* car = nic->getParentModule();
    const char* name = car->getName();
    cModule* scenario = car->getParentModule();

    while(scenario->findSubmodule("node",i)!=-1){
        num++;
        cModule* vehicle = scenario->getSubmodule("node",i);
        Veins::TraCIMobility* traci = dynamic_cast<Veins::TraCIMobility*>(vehicle->getSubmodule("veinsmobility", 0));
        Veins::TraCICommandInterface::Vehicle* traciVehicle = traci->getVehicleCommandInterface();
        //DBG_MAC <<"car index is :" << vehicle->getIndex() << " and lane is :" << traciVehicle->getLaneIndex() << std::endl;

        lanesHasVehicle[traciVehicle->getLaneIndex()] = true;

        /*存储车辆车道信息和行驶方向信息*/
        vehicleLanes[i] = traciVehicle->getLaneIndex();
        vehicleAngles[i] = traci->getAngleRad();
        i++;
    }
}

第二行找到mobility子模块;

第三行使用mobility提供的traci接口;

NOTE2:上面的traci只能获取速度等信息,而traciVehicle可以设置车辆的速度等。

  • 定义消息、设置内容并发送:
代码语言:javascript
复制
if (msg == sendBeacon) {
    Beacon* beacon = new Beacon();
    beacon->setVehicleId(this->getParentModule()->getIndex());
    beacon->setV(traci->getSpeed());
    beacon->setX(traci->getPositionAt(simTime()).x);
    beacon->setY(traci->getPositionAt(simTime()).y);
    THSposition[this->getParentModule()->getIndex()] = traci->getPositionAt(simTime());
    THSangle[this->getParentModule()->getIndex()] = traci->getAngleRad();
    THSspeed[this->getParentModule()->getIndex()] = traci->getSpeed();
    THSacceleration[this->getParentModule()->getIndex()] = acceleration;
    //加速度可以通过保存前一时刻速度来计算:
    acceleration = ( traci->getSpeed() - speedBefore ) * 1;//renew acc every 1s
    speedBefore = traci->getSpeed();

    beacon->setA(acceleration);
    for (int i = 0;i < 100;i++){
        beacon->setBeaconrate(i,THSbeaconrate[i]);
        beacon->setCp(i, THScp[i]);
        beacon->setSpeed(i,THSspeed[i]);
        beacon->setAcceleration(i, THSacceleration[i]);
        beacon->setPosition(i, THSposition[i]);
        beacon->setAngle(i, THSangle[i]);
    }

    //新建WSM,这是应用层和MAC层通信的消息
    WaveShortMessage* WSM = new WaveShortMessage();
    //把beacon封装在WSM中
    WSM->encapsulate(beacon);
    //设置WSM的基本信息
    populateWSM(WSM);
    //将WSM从应用层的向下接口发送出去
    send(WSM,lowerLayerOut);
    return;
}

NOTE3:如果要设置一个数组的所有信息,需要通过循环使用这样的方法:

代码语言:javascript
复制
beacon->setBeaconrate(i,THSbeaconrate[i]);

NOTE4:如果需要循环发送,如实现TDMA可以在return之前,循环调度这个自消息:

代码语言:javascript
复制
scheduleAt(simTime() + frameLength,sendBeacon);

其他的一些信息如源目地址可以这样设置:

代码语言:javascript
复制
//自身应用层的ID:
beacon->setMyL3Addr(myApplAddr());
//设置目标地址,不设置就是-1广播地址:
//如果你使用plexe,可以使用UnicastMessage类的方法:
unicastMsg->setDestination(1);
//如果你是用Veins,可以使用WSM类的方法:
wsmMsg->setRecipientAddress(1);

NOTE5:值得注意的是即使设置了目标地址,Veins在过程上还是将消息广播出去,其他车辆接收时在MAC层判断目标地址是否和自己一致,如果一致,将这个消息传递到上层,不一致则丢弃这个消息。我们也可以在自己定义的消息(如上面的Beacon)中加入源目成员,发送时设置源目信息,在接收时,可以直接在应用层判断目标地址。

3、消息的接收:

3.1消息从哪里接收

首先我们应该大体知道消息的传递方式,A给B发消息,首先A的应用层从lowerLayerOut接口向下传递数据包,数据包最终通过信道传输到B,随后会从B的Mac层upperLayerOut传到App层的LowerLayerIn接口。

3.2接收消息和处理:

MyVeinsApp.cc没有重写handleLowerMsg函数,需要在头文件中添加:

代码语言:javascript
复制
virtual void handleLowerMsg(cMessage* msg);​

并在MyVeinsApp.cc中实现:

代码语言:javascript
复制
void MyVeinsApp::handleLowerMsg(cMessage* msg) {
    //消息传换成WSM
    WaveShortMessage* WSM = check_and_cast<WaveShortMessage*>(msg);
    //从WSM中解封数据包
    cPacket* enc = WSM->getEncapsulatedPacket();
    //数据包转换成Beacon
    Beacon* bc = dynamic_cast<Beacon*>(enc);
    cModule* vehicle = getParentModule();
    Veins::TraCIMobility* traci = dynamic_cast<Veins::TraCIMobility*>(vehicle->getSubmodule("veinsmobility", 0));
    EV << "current position = " <<traci->getPositionAt(simTime())<<endl;
    for (int i = 0;i < 100;i++){
        THSbeaconrate[i] = bc->getBeaconrate(i) ;
        THSspeed[i] = bc->getSpeed(i) ;
        THSacceleration[i] = bc->getAcceleration(i) ;
        THSposition[i] = bc->getPosition(i) ;
        THSangle[i] = bc->getAngle(i) ;
        THScp[i] = bc->getCp(i) ;

    //    EV << "received beaconrate = " <<bc->getBeaconrate(i)<<endl;    //get THSbeaconrate ???
    //    EV << "received speed = " <<bc->getSpeed(i)<<endl;
    //    EV << "received acceleration = " <<bc->getAcceleration(i)<<endl;
    //    EV << "received position = " <<bc->getPosition(i)<<endl;
    //    EV << "received angle = " <<bc->getAngle(i)<<endl;
    }
    for (int i = 0;i < (int)bc->getBeaconrate(bc->getVehicleId());i++ ){
        int k = i*(int)(10/bc->getBeaconrate(bc->getVehicleId())) ;
        if(bc->getSlotpos().x+k < 10){
        THSslotnum[(int)bc->getSlotpos().x+k][(int)bc->getSlotpos().y] = 1 ;
        }
    }
    THSbeaconrate[bc->getVehicleId()] = bc->getBeaconrate(bc->getVehicleId());
    THSspeed[bc->getVehicleId()] = bc->getSpeed(bc->getVehicleId()) ;
    THSacceleration[bc->getVehicleId()] = bc->getAcceleration(bc->getVehicleId()) ;
    THSposition[bc->getVehicleId()] = bc->getPosition(bc->getVehicleId()) ;
    THSangle[bc->getVehicleId()] = bc->getAngle(bc->getVehicleId()) ;

    EV << "Receive successfully !!!!!!!!!!!" << endl;

}

设置消息和接收消息的两处内容可能有偏差,不是大问题。

NOTE6:handleLowerMsg重写了父类BaseWaveApplLayer的handleLowerMsg,为了避免覆盖父类的实现,可以在该方法最后加上下面一行代码,对于handleSelfMsg或Mac、phy层的handleUpperMsg也可以加上这样的代码:

代码语言:javascript
复制
BaseWaveApplLayer::handlLowerfMsg(msg);​

到此一次完整的消息传输过程就结束了!

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

邀请人:千万别过来

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、定义自己的消息内容:
    • 1.1、定义.msg文件:
      • 1.2、Bulid Project生成Beacon_m.h和Beacon_m.cc文件:
        • 1.3引用:
        • 2、消息的发送:
          • 2.1、定义自消息:
            • 2.2、消息内容的设置及消息的发送:
            • 3、消息的接收:
              • 3.1消息从哪里接收
                • 3.2接收消息和处理:
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档