Veins中其他节点发WSM时handleLower未触发,onWSM接收失效求助
问题:Veins v5.2 + OMNeT++ v6.0.1中CAM消息发送正常但接收异常
基于OMNeT++ v6.0.1与Veins v5.2搭建V2X仿真场景(含1个RSU和3辆车辆),为车辆开发应用,满足条件时广播CAM消息至所有节点。目前消息发送正常,但接收存在异常:调用sendDown(wsm)广播后,仅车辆生成时onWSM()被调用,其余情况无响应,未输出"CAM RECEIVED BY CAR"日志,排查发现DemoBaseApplLayer::handleLowerMsg(cMessage* msg)未被调用。
车辆应用代码
#include "hradeck17/application/CamTestApp.h" #include "hradeck17/messages/CAM_m.h" using namespace veins; using namespace hradeck17; Define_Module(hradeck17::CamTestApp); void CamTestApp::initialize(int stage) { EV << "Initializing CamTestApp " << std::endl; DemoBaseApplLayer::initialize(stage); if (stage == 0) { sentMessage = false; lastDroveAt = simTime(); currentSubscribedServiceId = -1; lastCamGeneratedAt = simTime().dbl() * 1000; T_GenCamMin = 100; T_GenCamMax = 1000; T_CheckCamGen = T_GenCamMin; T_GenCam_Dcc = T_GenCamMin; T_GenCam = 1000; N_GenCam = 3; lastHeading = traciVehicle->getAngle(); lastPosition = mobility->getPositionAt(simTime()); lastSpeed = traciVehicle->getSpeed(); conseqCamGenerations = 0; /* Schedule a self-message for checking the CAM generation condition */ scheduleAt(simTime(), new cMessage("checkCAMCondition")); } } void CamTestApp::onWSA(DemoServiceAdvertisment* wsa) { } void CamTestApp::onWSM(BaseFrame1609_4* frame) { CAM* wsm = check_and_cast<CAM*>(frame); findHost()->getDisplayString().setTagArg("i",1,"green"); EV << "CAM RECEIVED BY CAR" << std::endl; } void CamTestApp::handleSelfMsg(cMessage* msg) { if(strcmp(msg->getName(), "checkCAMCondition") == 0){ double currentTime = simTime().dbl()*1000; /* Check the current state of the vehicle */ currentHeading = traciVehicle->getAngle(); currentPosition = mobility->getPositionAt(simTime()); currentSpeed = traciVehicle->getSpeed(); // EV << traci->getLonLat(currentPosition).first << std::endl; // EV << traci->getLonLat(currentPosition).second << std::endl; /* Elapsed T_GenCam_Dcc ms from last CAM generation (condition 1) */ if(currentTime - lastCamGeneratedAt >= T_GenCam_Dcc){ /* Heading changed by more than 4 degrees */ /* Speed changed by more than 0.5 m/s */ /* Position changed by more than 4 m */ if(fabs((currentHeading - lastHeading)) * 180 / M_PI > 4 || fabs(currentSpeed - lastSpeed) > 0.5 || currentPosition.distance(lastPosition) > 4){ findHost()->getDisplayString().setTagArg("i", 1, "red"); CAM* wsm = new CAM(); populateWSM(wsm); wsm->setSenderAddress(myId); wsm->setPosition(currentPosition); wsm->setHeading(currentHeading); wsm->setSpeed(currentSpeed); T_GenCam = currentTime - lastCamGeneratedAt; sendDown(wsm); lastCamGeneratedAt = currentTime; } } /* Condition 2 */ else if(currentTime - lastCamGeneratedAt >= T_GenCam && currentTime - lastCamGeneratedAt >= T_GenCam_Dcc){ /* Trigger CAM generation */ CAM* wsm = new CAM(); populateWSM(wsm); wsm->setSenderAddress(myId); wsm->setPosition(currentPosition); wsm->setHeading(currentHeading); wsm->setSpeed(currentSpeed); T_GenCam = T_GenCamMax; sendDown(wsm); lastCamGeneratedAt = currentTime; } /* Update state of the vehicle */ lastHeading = currentHeading; lastPosition = currentPosition; lastSpeed = currentSpeed; /* Schedule next CAM check message */ scheduleAt(simTime() + ((double)T_CheckCamGen/1000), new cMessage("checkCAMCondition")); } else { DemoBaseApplLayer::handleSelfMsg(msg); } } void CamTestApp::handlePositionUpdate(cObject* obj) { DemoBaseApplLayer::handlePositionUpdate(obj); }
消息定义代码
import veins.base.utils.Coord; import veins.modules.messages.BaseFrame1609_4; import veins.base.utils.SimpleAddress; namespace hradeck17; //Cooperative awareness message (CAM) //CAM is always broadcasted, max frequency is 10 Hz packet CAM extends veins::BaseFrame1609_4 { string demoData; int ID; veins::LAddress::L2Type senderAddress = -1; int serial = 0; veins::Coord position; double heading; double speed; }
解决方案
1. 配置消息服务ID与订阅
Veins的DemoBaseApplLayer会根据消息的serviceID过滤接收内容,默认仅处理已订阅服务ID的消息:
- 发送CAM时,在
populateWSM(wsm)后添加wsm->setServiceId(1);(可自定义ID,但需保持一致) - 在
initialize的stage 0阶段,调用subscribeService(1);,让接收节点订阅对应服务ID
2. 确保handleLowerMsg正常调用
如果你的CamTestApp重写了handleLowerMsg方法,必须显式调用父类方法:
void CamTestApp::handleLowerMsg(cMessage* msg) { DemoBaseApplLayer::handleLowerMsg(msg); }
若未重写该方法,确认父类的handleLowerMsg未被其他逻辑阻断。
3. 修正CAM生成条件逻辑
原代码中第二个条件永远无法触发(第一个条件已覆盖>= T_GenCam_Dcc的情况),调整逻辑如下:
double timeSinceLastCam = currentTime - lastCamGeneratedAt; if (timeSinceLastCam >= T_GenCam_Dcc) { // 状态变化触发CAM if(fabs((currentHeading - lastHeading)) * 180 / M_PI > 4 || fabs(currentSpeed - lastSpeed) > 0.5 || currentPosition.distance(lastPosition) > 4){ findHost()->getDisplayString().setTagArg("i", 1, "red"); CAM* wsm = new CAM(); populateWSM(wsm); wsm->setSenderAddress(myId); wsm->setPosition(currentPosition); wsm->setHeading(currentHeading); wsm->setSpeed(currentSpeed); wsm->setServiceId(1); wsm->setRecipientAddress(LAddress::L2BROADCAST()); T_GenCam = timeSinceLastCam; sendDown(wsm); lastCamGeneratedAt = currentTime; } // 定时触发CAM(无状态变化时) else if (timeSinceLastCam >= T_GenCam) { findHost()->getDisplayString().setTagArg("i", 1, "red"); CAM* wsm = new CAM(); populateWSM(wsm); wsm->setSenderAddress(myId); wsm->setPosition(currentPosition); wsm->setHeading(currentHeading); wsm->setSpeed(currentSpeed); wsm->setServiceId(1); wsm->setRecipientAddress(LAddress::L2BROADCAST()); T_GenCam = T_GenCamMax; sendDown(wsm); lastCamGeneratedAt = currentTime; } }
4. 确认消息广播属性
确保CAM消息设置为广播地址,在发送前添加:
wsm->setRecipientAddress(LAddress::L2BROADCAST());
5. 检查通信范围与物理层参数
确认车辆处于DSRC通信范围内(默认Veins通信范围为几百米),若车辆距离过远,消息会被物理层丢弃。可在仿真中查看车辆位置,或调整PhyLayer80211p的通信参数。
内容的提问来源于stack exchange,提问作者Stepulin
相关产品推荐
相关产品推荐

