omnet++ - 为什么 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");
}
解决方案
我注意到的一些事情:
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
因为我看到您定义了它们的参数inputType
和directNodeValueAssignment
,它们仅存在于CustomizablePhysicalProcess
模块中。所以我不明白你期望通过完全定义新的物理过程模块来获得什么。
由于您有 2 个物理进程,这意味着每个节点中的 SensorManager 都需要连接到这 2 个物理进程(定义您的物理进程的 2 个模块)。为此,只需将可定义为数组(格式为空格分隔的字符串)的 SensorManager 的所有参数设置为 2 项数组。
您可以在 SensorManager.ned 中找到所有相关参数(但不要编辑 ned 文件,只需在您的 ini 文件中设置它们)。以下是仅供参考的参数(请注意,您已经设置sensorTypes
并corrPhyProcess
在您的 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 之后的版本中还没有测试过,所以它可能根本不起作用(但希望它是一个小的调整让它起作用)。
推荐阅读
- ios - Swift - UISearchController Results displayed Large spacing between search bar and TableView Cells
- python - AttributeError:“DatasetSeries”对象没有属性“all_data”
- c# - Add an Node by index to custom LinkedList, with shift to right
- reactjs - ComponentDidMount not firing in ReactJS
- java - Create PDF file with embedded SVG in Java
- discord.js - Discord poll bot async issues
- java - 在应用程序被刷并重新启动后处理服务
- javascript - How to deal with NextJS exporting files with .html extension but in there is no .html
- python - python - 如何将现有字典作为嵌套字典添加到python中已经存在的字典中?
- c++ - 仅标头库的 cmake 错误:`include 找不到加载文件`