我是靠谱客的博主 苹果河马,最近开发中收集的这篇文章主要介绍omnet++,veins车辆间消息的传输、车辆运动信息获取1、定义自己的消息内容:2、消息的发送:3、消息的接收:4、总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

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接收消息和处理:

4、总结


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

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

1.1、定义.msg文件:

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

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:

#include "veins/modules/messages/Beacon_m.h"

2、消息的发送:

2.1、定义自消息:

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

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

cMessage* sendBeacon; 

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

sendBeacon = new cMessage("send Beacon");

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

if(strcmp(this->getParentModule()->getName(),"human") == 0){
scheduleAt(SimTime(5),sendBeacon);
}

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

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

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

  • 首先,我相信最常用的信息是车辆的动力学信息,如何获取它:
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所属车辆,需要:

cModule* vehicle = getParentModule()->getParentModule();

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

/*检测车辆数量*/
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可以设置车辆的速度等。

  • 定义消息、设置内容并发送:
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:如果要设置一个数组的所有信息,需要通过循环使用这样的方法:

beacon->setBeaconrate(i,THSbeaconrate[i]);

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

scheduleAt(simTime() + frameLength,sendBeacon);

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

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

 NOTE5:值得注意的是即使设置了目标地址,Veins在过程上还是将消息广播出去,其他车辆接收时在MAC层判断目标地址是否和自己一致,如果一致,将这个消息传递到上层,不一致则丢弃这个消息:

 

 类似这个方法,我们也可以在自己定义的消息(如上面的Beacon)中加入源目成员,发送时设置源目信息,在接收时,可以直接在应用层判断目标地址。

3、消息的接收:

3.1消息从哪里接收

首先我们应该大体知道消息的传递方式如下图(灵魂画手),A给B发消息,最后会从B的Mac层upperLayerOut传到App层的LowerLayerIn接口:

3.2接收消息和处理:

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

virtual void handleLowerMsg(cMessage* msg);

并在MyVeinsApp.cc中实现:

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也可以加上这样的代码:

BaseWaveApplLayer::handlLowerfMsg(msg);

4、总结

到此一次完整的消息传输过程就结束了,容易出错的地方总结如下:

1、消息的封装和解封

//封装:
//新建WSM,这是应用层和MAC层通信的消息
WaveShortMessage* WSM = new WaveShortMessage();
//把beacon封装在WSM中
WSM->encapsulate(beacon);
//设置WSM的基本信息
populateWSM(WSM);
//将WSM从应用层的向下接口发送出去
send(WSM,lowerLayerOut);
//解封:
//消息传换成WSM
WaveShortMessage* WSM = check_and_cast<WaveShortMessage*>(msg);
//从WSM中解封数据包
cPacket* enc = WSM->getEncapsulatedPacket();
//数据包转换成Beacon
Beacon* bc = dynamic_cast<Beacon*>(enc);

2、消息中数组的使用:

//setter:
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]);
}
//getter:
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) ;
}

3、消息调度错误常见有两种情况

(1)调度的时间是过去时间,如在8s时scheduleAt(SimTime(5),sendBeacon);出错;

(2)被调度的自消息已经被调度并且还没执行,如在5s时scheduleAt(SimTime(8),sendBeacon),在6s时又scheduleAt(SimTime(8),sendBeacon),这种情况下可以先取消再调度:

if (sendBeacon->isScheduled()) {
cancelEvent(sendBeacon);
}
scheduleAt(SimTime(8),sendBeacon);

以上!希望对大家有帮助,也感谢大家支持。关于veins应用方面如果大家还有想了解的内容可以私信我,我会尽力去学习。再次感谢。

最后

以上就是苹果河马为你收集整理的omnet++,veins车辆间消息的传输、车辆运动信息获取1、定义自己的消息内容:2、消息的发送:3、消息的接收:4、总结的全部内容,希望文章能够帮你解决omnet++,veins车辆间消息的传输、车辆运动信息获取1、定义自己的消息内容:2、消息的发送:3、消息的接收:4、总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(94)

评论列表共有 0 条评论

立即
投稿
返回
顶部