You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 21:25:04