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

VeinsInet节点定位停止报错:send()/sendDelayed()无法发送inet::Packet

解决OMNeT++中send()/sendDelayed()数据包持有报错问题

问题根源

你说没在callRefreshDisplay()里发送数据包,但看你贴的代码,这个方法里明确调用了sendPacket(std::move(packet))——这就是触发报错的直接原因。

OMNeT++的callRefreshDisplay()是专门用于界面显示刷新的回调方法,它运行在模拟的"显示更新阶段",这个阶段不允许执行发送数据包、调度事件这类修改模拟状态的操作。此时数据包会被omnetpp::cDefaultList持有,调用send()自然会抛出错误。

解决方案

把发送数据包、停车的业务逻辑从callRefreshDisplay()中移出,放到OMNeT++标准的事件处理流程里,比如用周期性定时器检查位置:

  1. 添加定时器成员:在你的应用类中声明一个自消息定时器

    class VeinsInetSampleApplication : public inet::ApplicationBase {
        // ... 已有成员
        cMessage* positionCheckTimer;
    };
    
  2. 初始化定时器:在initialize()中调度周期性检查任务

    void VeinsInetSampleApplication::initialize(int stage) {
        ApplicationBase::initialize(stage);
        if (stage == INITSTAGE_APPLICATION_LAYER) {
            positionCheckTimer = new cMessage("positionCheckTimer");
            scheduleAt(simTime() + 0.1, positionCheckTimer); // 每0.1秒检查一次位置
        }
    }
    
  3. 处理定时器事件:在消息处理方法中检查位置,执行业务逻辑

    void VeinsInetSampleApplication::handleMessageWhenUp(cMessage* msg) {
        if (msg == positionCheckTimer) {
            checkPositionAndAct();
            scheduleAt(simTime() + 0.1, positionCheckTimer); // 继续调度下一次检查
        }
        // ... 处理其他消息逻辑
    }
    
    void VeinsInetSampleApplication::checkPositionAndAct() {
        double pos1 = 128;
        double pos2 = 130;
        double pos3 = 103;
        double pos4 = 105;
    
        if (getParentModule()->getIndex() == 0) {
            auto currentPos = mobility->getCurrentPosition();
            if (currentPos.x > pos1 && currentPos.x < pos2 && currentPos.y > pos3 && currentPos.y < pos4) {
                // 构造并发送事故数据包
                auto payload = makeShared<VeinsInetSampleMessage>();
                payload->setChunkLength(B(100));
                payload->setRoadId(traciVehicle->getRoadId().c_str());
                timestampPayload(payload);
    
                auto packet = createPacket("accident");
                sendPacket(std::move(packet));
    
                // 让车辆停止
                traciVehicle->setSpeed(0);
    
                // 如果需要刷新界面,再调用callRefreshDisplay
                callRefreshDisplay();
            }
        }
    }
    
  4. 清理定时器:记得在finish()中释放定时器资源

    void VeinsInetSampleApplication::finish() {
        cancelAndDelete(positionCheckTimer);
        ApplicationBase::finish();
    }
    

注意事项

callRefreshDisplay()只应该用来做纯显示相关的操作,比如修改节点图标颜色(就是你注释掉的那行代码),不要在里面执行任何会改变模拟状态的逻辑。

内容的提问来源于stack exchange,提问作者amin rezaei

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:17:28