首页 > 解决方案 > 为什么 Castalia 中的物理过程会输出错误的数据?

问题描述

我正在尝试在 Castalia 中模拟一个传感器阵列,每个节点能够使用多个传感器,但是当我运行模拟时,它将传感器的名称作为一个项目,并最终显示传感器索引和首先提到的传感器的值。请帮忙!!如何让它在每个节点 omnetpp.ini 中检测多个传感器(valueReporting)

[General]

# ==========================================================
# Always include the main Castalia.ini file
# ==========================================================

include ../Parameters/Castalia.ini

sim-time-limit = 600s

SN.field_x = 100                    # meters
SN.field_y = 100                    # meters

SN.numNodes = 36
SN.deployment = "6x6"

SN.node[*].Communication.Radio.RadioParametersFile = "../Parameters/Radio/CC2420.txt"

SN.node[*].Communication.MACProtocolName = "TMAC"

SN.node[*].Communication.RoutingProtocolName = "MultipathRingsRouting"
#SN.node[*].Communication.Routing.collectTraceInfo = true

SN.node[*].ApplicationName = "ValueReporting"
SN.node[3].Application.isSink = true

# test 2 physical processes
SN.numPhysicalProcesses = 2  
SN.physicalProcess[0].printDebugInfo = true 
SN.physicalProcess[1].printDebugInfo = true 
SN.physicalProcess[0].description = "Degrees Celsius"  
SN.physicalProcess[1].description = "Blood Glucose"     
SN.physicalProcess[0].inputType = 1         
SN.physicalProcess[1].inputType = 1         
#SN.physicalProcess[0].directNodeValueAssignment = "(0) 0:25 1:23 2:21 3:24 4:26"
#SN.physicalProcess[1].directNodeValueAssignment = "(0) 0:360 1:380 2:375 3:390 4:390"
SN.node[*].SensorManager.​numSensingDevices = 2 
SN.node[*].SensorManager.​sensorTypes = "Temperature Bloodglucose" 
SN.node[*].SensorManager.​corrPhyProcess = "0 1"

在 SensorManager.ned 文件中,我更改了这些行,因为文件的其余部分保持原样

string sensorTypes = default ("Temperature,Bloodglucose");
    // string array of comma-separated Names for the sensing devices

string corrPhyProcess = default ("0,1");

现在温度物理过程文件TemperaturePhysicalProcess.ned

package physicalProcess.temperaturePhysicalProcess;

simple TemperaturePhysicalProcess like physicalProcess.iPhysicalProcess {
 parameters:
    bool collectTraceInfo = default (true);

    double temperature = default (37); //normal body temperature is 37 degrees celcius


    string description = default ("Degrees Celsius");

 gates:
    output toNode[];
    input fromNode[];
}

温度物理过程.h

#ifndef _TEMPERATUREPHYSICALPROCESS_H_
#define _TEMPERATUREPHYSICALPROCESS_H_

#define SIMTIME_STEP 0.01

#include "CastaliaModule.h"
#include "PhysicalProcessMessage_m.h"

using namespace std;

typedef struct {
    simtime_t time;
    double x;
    double y;
} sourceSnapshot;

class TemperaturePhysicalProcess: public CastaliaModule {
 private:
    bool printDebugInfo;

    int temperature; 

    const char *description;
protected:
    virtual void initialize();
    virtual void handleMessage(cMessage * msg);
    virtual void finishSpecific();
};

#endif

温度物理过程.cc

#include "TemperaturePhysicalProcess.h"

Define_Module(TemperaturePhysicalProcess);

void TemperaturePhysicalProcess::initialize()
{

    temperature=37;  
    //Search for snapshots in castalia manual
}

void TemperaturePhysicalProcess::handleMessage(cMessage * msg)
{
    if (msg->getKind() != PHYSICAL_PROCESS_SAMPLING)
    {
        opp_error("Physical Process received message other than PHYSICAL_PROCESS_SAMPLING");
    }

    PhysicalProcessMessage *receivedMsg = check_and_cast < PhysicalProcessMessage * >(msg);
    int nodeIndex = receivedMsg->getSrcID();

    // Send reply back to the node who made the request
    receivedMsg->setValue(temperature);
    send(receivedMsg, "toNode", nodeIndex);
}

void TemperaturePhysicalProcess::finishSpecific() {}

现在我们将进入血糖物理过程 BloodGlucoseLevelPhysicalProcess.ned

package physicalProcess.bloodGlucoseLevelPhysicalProcess;

simple BloodGlucoseLevelPhysicalProcess like physicalProcess.iPhysicalProcess {
 parameters:
    bool collectTraceInfo = default (false);
    int averagebloodglucose = default (100); // the amount is in mg per dL
    int age = default (20);
    string description = default ("Blood Glucose");

 gates:
    output toNode[];
    input fromNode[];
}   

BloodGlucoseLevelPhysicalProcess.h

#ifndef _BLOOODGLUCOSELEVELPHYSICALPROCESS_H_
#define _BLOOODGLUCOSELEVELPHYSICALPROCESS_H_

#define SIMTIME_STEP 0.01

#include "CastaliaModule.h"
#include "PhysicalProcessMessage_m.h"

using namespace std;

typedef struct {
    simtime_t time;
    double x;
    double y;
} sourceSnapshot;

class BloodGlucoseLevelPhysicalProcess: public CastaliaModule {
 private:
    bool printDebugInfo;
    int averagebloodglucose;
    double A1c;
    const char *description;
protected:
    virtual void initialize();
    virtual void handleMessage(cMessage * msg);
    virtual void finishSpecific();
};

#endif

BloodGlucoseLevelLevelPhysicalProcess.cc

#include "BloodGlucoseLevelPhysicalProcess.h"

Define_Module(BloodGlucoseLevelPhysicalProcess);

void BloodGlucoseLevelPhysicalProcess::initialize()
{
    averagebloodglucose = par("averagebloodglucose");
    description = par("description").stringValue();
    A1c = (46.7 + averagebloodglucose) / 28.7;
    //Search for snapshots in castalia manual

}

void BloodGlucoseLevelPhysicalProcess::handleMessage(cMessage * msg)
{
    if (msg->getKind() != PHYSICAL_PROCESS_SAMPLING)
        opp_error("Physical Process received message other than PHYSICAL_PROCESS_SAMPLING");

    PhysicalProcessMessage *receivedMsg = check_and_cast < PhysicalProcessMessage * >(msg);
    int nodeIndex = receivedMsg->getSrcID();
    //int sensorIndex = receivedMsg->getSensorIndex();
    double returnValue;

    // Send reply back to the node who made the request
    //receivedMsg->setValue(returnValue);
    receivedMsg->setValue(A1c);
    send(receivedMsg, "toNode", nodeIndex);

}

void BloodGlucoseLevelPhysicalProcess::finishSpecific() {

}

由于我正在使用 ValueReporting 应用程序 ValueReporting.h 运行模拟

#define _VALUEREPORTING_H_

#include "VirtualApplication.h"
#include "ValueReportingPacket_m.h"

using namespace std;

enum ValueReportingTimers {
    REQUEST_SAMPLE = 1,
    SEND_DATA = 2,

};

class ValueReporting: public VirtualApplication {
 private:
    double maxSampleInterval;
    double minSampleInterval;

    int routingLevel;
    double lastSensedValue;
    int currSentSampleSN;

    double randomBackoffIntervalFraction;
    bool sentOnce;

    int recipientId;
    string recipientAddress;

 protected:
    void startup();
    void fromNetworkLayer(ApplicationPacket *, const char *, double, double);
    void handleSensorReading(SensorReadingMessage *);
    void timerFiredCallback(int);
    void requestSensorReading(const char *);


};

#endif              // _VALUEREPORTING_APPLICATIONMODULE_H_

价值报告.cc

#include "ValueReporting.h"
#include <iostream>   // std::cout
#include <iomanip>
#include <string>     // std::string, std::to_string
#include <stdlib.h>     /* atof */
#include <math.h>
#include<sstream>
#include <cstring>
#include <vector>
#include <array>
#include <string>
#include <algorithm>

Define_Module(ValueReporting);

void ValueReporting::startup()
{
    maxSampleInterval = ((double)par("maxSampleInterval")) / 1000.0;
    minSampleInterval = ((double)par("minSampleInterval")) / 1000.0;
    currSentSampleSN = 0;
    randomBackoffIntervalFraction = genk_dblrand(0);
    sentOnce = false;
    setTimer(REQUEST_SAMPLE, maxSampleInterval * randomBackoffIntervalFraction);
}

void ValueReporting::timerFiredCallback(int index)
{
    switch (index) {

        case REQUEST_SAMPLE:{
            requestSensorReading("Temperature");
            //requestSensorReading("Urine");

            setTimer(REQUEST_SAMPLE, maxSampleInterval);

            break; 
        }      
    }
}

void ValueReporting::fromNetworkLayer(ApplicationPacket * genericPacket,
         const char *source, double rssi, double lqi)
{
    ValueReportingDataPacket *rcvPacket = check_and_cast<ValueReportingDataPacket*>(genericPacket);
    ValueReportData theData = rcvPacket->getExtraData();

        trace() << "Sink received from: " << theData.nodeID << " \tvalue=" << rcvPacket->getData();

}
void ValueReporting::handleSensorReading(SensorReadingMessage * rcvReading)
{
    int sensIndex =  rcvReading->getSensorIndex();

     string sensType(rcvReading->getSensorType());

    double sensValue = rcvReading->getSensedValue();

    double x_coor = mobilityModule->getLocation().x; 
    double y_coor = mobilityModule->getLocation().y;
string sensorindex = to_string(sensIndex);
    string sensvalue = to_string(sensValue);
    string xcoor = to_string(x_coor);
    string ycoor = to_string(y_coor);


    string sensorinfo= sensorindex + " " + sensvalue + " " + xcoor + " " + ycoor + " " + sensType;
    trace() << sensorinfo; 
ValueReportData tmpData;
    tmpData.nodeID = (unsigned short)self;
    tmpData.locX = mobilityModule->getLocation().x;
    tmpData.locY = mobilityModule->getLocation().y;

    ValueReportingDataPacket *packet2Net =
        new ValueReportingDataPacket("Value reporting pck", APPLICATION_PACKET);
    packet2Net->setExtraData(tmpData);
    packet2Net->setData(sensValue);
    packet2Net->setSequenceNumber(currSentSampleSN);
    currSentSampleSN++;

    toNetworkLayer(packet2Net, SINK_NETWORK_ADDRESS);
    //toNetworkLayer(packet2Net, "6");
    sentOnce = true;
}
void ValueReporting::requestSensorReading(const char * type){
    SensorReadingMessage *reqMsg =
        new SensorReadingMessage("App to Sensor Mgr: sample request", SENSOR_READING_MESSAGE);

    if(type == "Temperature"){
    reqMsg->setSensorType(type);
    reqMsg->setSensorIndex(0);
    }
if(type =="BloodGlucose"){
    reqMsg->setSensorType(type);
    reqMsg->setSensorIndex(1);
    }
    send(reqMsg, "toSensorDeviceManager");
}

标签: omnet++

解决方案


我注意到的一些事情:

PhysicalProcess 模块中没有printDebugInfo参数。可能你追求的是collectTraceInfo.

如果您只想更新某些参数所采用的值,那么编辑 ned 文件不是一个好主意。这就是ini文件的用途。因此,无需更改 ned 文件中的默认值,只需在您的 ini 文件中分配这些值即可。例如,您已经在 ini 文件中分配了这些参数:

SN.node[*].SensorManager.​sensorTypes = "Temperature Bloodglucose" 
SN.node[*].SensorManager.​corrPhyProcess = "0 1"

您也不需要在 ned 文件中设置它们。另请注意,在 ned 文件中,您将第二个字符串设置为“0,1”而不是“0 1”。ini 文件将覆盖 ned 文件的值,所以你会得到它“0 1”。幸运的是,空格分隔的值是正确的语法。

然后您开始定义新的 .ned .cc 和 .h 文件。为什么?这些没有任何影响。您尚未SN.physicalProcessName在 ini 文件中设置变量。这意味着它采用默认值,即CustomizablePhysicalProcess. 您似乎将您的物理过程模块视为CustomizablePhysicalProcess因为我看到您定义了它们的参数inputTypedirectNodeValueAssignment,它们仅存在于CustomizablePhysicalProcess模块中。所以我不明白你期望通过完全定义新的物理过程模块来获得什么。

由于您有 2 个物理进程,这意味着每个节点中的 SensorManager 都需要连接到这 2 个物理进程(定义您的物理进程的 2 个模块)。为此,只需将可定义为数组(格式为空格分隔的字符串)的 SensorManager 的所有参数设置为 2 项数组。

您可以在 SensorManager.ned 中找到所有相关参数(但不要编辑 ned 文件,只需在您的 ini 文件中设置它们)。以下是仅供参考的参数(请注意,您已经设置sensorTypescorrPhyProcess在您的 ini 文件中,您只需要设置其余参数):

string pwrConsumptionPerDevice = default ("0.02");
string sensorTypes = default ("Temperature");   // Humidity OR Temperature OR Light
string corrPhyProcess = default ("0");      //holds the indexes of the corresponding phy processes for
                                            //each sensor (usually it should be : "0 1 2 3")
string maxSampleRates = default ("1");      //number of samples per second for each sensor
string devicesBias = default ("0.1");       //If the output signal is not zero when the measured property is zero
string devicesDrift = default ("");         //If the output signal slowly changes independent of the 
                                            //measured property                     
string devicesNoise = default ("0.1");      //random deviation of the signal that varies in time
string devicesHysterisis = default ("");    //the sensor not instantly follows the change of the property 
                                            //being measured and therefore involves the history of the 
                                            //measured property
string devicesSensitivity = default ("0");  //holds the minimum value which can be sensed by each sensing device.
string devicesResolution = default ("0.001");   //holds the sensing resolution for each device 

我不确定多个 phyProcesses 和多个传感模式是否还有其他问题,因为这个功能在 2.0 之后的版本中还没有测试过,所以它可能根本不起作用(但希望它是一个小的调整让它起作用)。


推荐阅读