答案会因所使用的 PhysicalProcess 模块指定的行为而异。既然您在评论中说您可能正在使用 CarsPhysicalProcess,让我们以此为例。
应用程序发起的传感器读取请求首先通过SensorReadingMessage 消息发送到 SensorManager。在SensorManager.cc 中,您可以看到它是如何在其handleMessage 函数中处理的:
...
case SENSOR_READING_MESSAGE: {
SensorReadingMessage *rcvPacket =check_and_cast<SensorReadingMessage*>(msg);
int sensorIndex = rcvPacket->getSensorIndex();
simtime_t currentTime = simTime();
simtime_t interval = currentTime - sensorlastSampleTime[sensorIndex];
int getNewSample = (interval < minSamplingIntervals[sensorIndex]) ? 0 : 1;
if (getNewSample) { //the last request for sample was more than minSamplingIntervals[sensorIndex] time ago
PhysicalProcessMessage *requestMsg =
new PhysicalProcessMessage("sample request", PHYSICAL_PROCESS_SAMPLING);
requestMsg->setSrcID(self); //insert information about the ID of the node
requestMsg->setSensorIndex(sensorIndex); //insert information about the index of the sensor
requestMsg->setXCoor(nodeMobilityModule->getLocation().x);
requestMsg->setYCoor(nodeMobilityModule->getLocation().y);
// send the request to the physical process (using the appropriate
// gate index for the respective sensor device )
send(requestMsg, "toNodeContainerModule", corrPhyProcess[sensorIndex]);
// update the most recent sample times in sensorlastSampleTime[]
sensorlastSampleTime[sensorIndex] = currentTime;
} else { // send back the old sample value
rcvPacket->setSensorType(sensorTypes[sensorIndex].c_str());
rcvPacket->setSensedValue(sensorLastValue[sensorIndex]);
send(rcvPacket, "toApplicationModule");
return;
}
break;
}
....
如您所见,它首先计算自该传感器的最后一次传感器读取请求以来经过了多长时间。如果小于此传感器可能的 minSamplingInterval 指定的时间(这由 SensorManager 的 maxSampleRates NED 参数确定),它只返回给定的最后一个传感器读数。如果它更大,则会进行新的传感器读数。
通过向 PhysicalProcess 模块(通过toNodeContainerModule 门)发送PhysicalProcessMessage 消息来读取新的传感器读数。在消息中,我们传递了节点的 X 和 Y 坐标。
现在,如果我们将 CarsPhysicalProcess 指定为要在 omnetpp.ini 文件中使用的物理进程,CarsPhysicalProcess 模块将收到此消息。你可以在CarsPhysicalProcess.cc看到这个:
....
case PHYSICAL_PROCESS_SAMPLING: {
PhysicalProcessMessage *phyMsg = check_and_cast < PhysicalProcessMessage * >(msg);
// get the sensed value based on node location
phyMsg->setValue(calculateScenarioReturnValue(
phyMsg->getXCoor(), phyMsg->getYCoor(), phyMsg->getSendingTime()));
// Send reply back to the node who made the request
send(phyMsg, "toNode", phyMsg->getSrcID());
return;
}
...
您可以看到,我们根据节点的 X 和 Y 坐标以及传感器读数的时间来计算传感器值。响应通过toNode 门发送回 SensorManager。所以我们需要查看calculateScenarioReturnValue 函数来了解发生了什么:
double CarsPhysicalProcess::calculateScenarioReturnValue(const double &x_coo,
const double &y_coo, const simtime_t &stime)
{
double retVal = 0.0f;
int i;
double linear_coeff, distance, x, y;
for (i = 0; i < max_num_cars; i++) {
if (sources_snapshots[i][1].time >= stime) {
linear_coeff = (stime - sources_snapshots[i][0].time) /
(sources_snapshots[i][1].time - sources_snapshots[i][0].time);
x = sources_snapshots[i][0].x + linear_coeff *
(sources_snapshots[i][1].x - sources_snapshots[i][0].x);
y = sources_snapshots[i][0].y + linear_coeff *
(sources_snapshots[i][1].y - sources_snapshots[i][0].y);
distance = sqrt((x_coo - x) * (x_coo - x) +
(y_coo - y) * (y_coo - y));
retVal += pow(K_PARAM * distance + 1, -A_PARAM) * car_value;
}
}
return retVal;
}
我们从传感器返回值 0 开始。然后我们循环遍历道路上的每辆车(如果您查看 handleMessage 函数中的 TIMER_SERVICE 案例语句,您会看到 CarsPhysicalProcess 将汽车放在道路随机按照car_interarrival率,最多max_num_cars车数)。对于每辆汽车,我们计算汽车在道路上行驶了多远,然后计算汽车与节点之间的距离。然后对于每辆车我们根据公式添加到返回值:
pow(K_PARAM * distance + 1, -A_PARAM) * car_value
其中distance 是我们计算的汽车和节点之间的距离,K_PARAM = 0.1、A_PARAM = 1(定义在 CarsPhysicalProcess.cc 的顶部)和car_value 是在 CarsPhysicalProcess.ned 中指定的数字参数文件(默认为 30)。
这个值被传回给 SensorManager。然后,SensorManager 可能会根据传感器的灵敏度、分辨率、噪声和偏差(定义为 SensorManager 参数)更改此值:
....
case PHYSICAL_PROCESS_SAMPLING:
{
PhysicalProcessMessage *phyReply = check_and_cast<PhysicalProcessMessage*>(msg);
int sensorIndex = phyReply->getSensorIndex();
double theValue = phyReply->getValue();
// add the sensor's Bias and the random noise
theValue += sensorBias[sensorIndex];
theValue += normal(0, sensorNoiseSigma[sensorIndex], 1);
// process the limitations of the sensing device (sensitivity, resoultion and saturation)
if (theValue < sensorSensitivity[sensorIndex])
theValue = sensorSensitivity[sensorIndex];
if (theValue > sensorSaturation[sensorIndex])
theValue = sensorSaturation[sensorIndex];
theValue = sensorResolution[sensorIndex] * lrint(theValue / sensorResolution[sensorIndex]);
....
所以你可以看到,如果该值低于传感器的灵敏度,则返回灵敏度的下限。
所以基本上你可以看到 Castalia 中没有特定的“感应范围”——这完全取决于特定的 PhysicalProcess 如何处理消息。在 CarsPhysicalProcess 的情况下,只要路上有一辆车,它总是会返回一个值,无论距离多远——如果汽车离节点很远,它可能会非常小。如果该值非常小,您可能会收到最低的传感器灵敏度。您可以增加或减少car_value 参数以从传感器获得更强的响应(所以这有点像传感器范围)
编辑---
默认灵敏度(您可以在SensorManager.ned 中找到)为 0。因此对于 CarsPhysicalProcess,应检测到道路上任何距离的任何汽车并将其返回为大于 0 的值。换句话说,范围是无限的。如果汽车非常非常远,它可能会返回一个小到被截断为零的数字(这取决于 c++ 实现中双精度值的限制)
如果您想实现感应范围,则必须在SensorManager.ned 中为devicesSensitivity 设置一个值。然后在您的应用程序中,您将测试返回值是否大于灵敏度值 - 如果是,则汽车“在范围内”,如果它(几乎)等于灵敏度,则超出范围。我说几乎是因为(如我们之前所见)SensorManager 将 noise 添加到返回的值中,例如,如果您的灵敏度值为 5,并且没有汽车,你会得到会在 5 左右徘徊的值(例如 5.0001、4.99)
在设置灵敏度值的情况下,要计算感应距离(假设道路上只有 1 辆车),这意味着只需求解上述距离等式,使用最小灵敏度值作为返回值。即,如果我们使用 5 的灵敏度值:
5 = pow(K_PARAM * distance + 1, -A_PARAM) * car_value
代入参数值,用代数求解距离。