capture effect (3dB) + noise source radio support

This commit is contained in:
Fredrik Osterlind 2011-02-22 20:19:36 +01:00
parent 148dbc7fb7
commit fc3bf315ab
3 changed files with 205 additions and 158 deletions

View File

@ -696,7 +696,7 @@ public class AreaViewer extends VisPlugin {
String logHtml = String logHtml =
"<html>" + "<html>" +
trackedComponents.log.replace("\n", "<br>") + trackedComponents.log.replace("\n", "<br>").replace(" pi", " &pi;") +
"</html>"; "</html>";
t.setTipText(logHtml); t.setTipText(logHtml);

View File

@ -1327,11 +1327,14 @@ public class ChannelModel {
* the random variable mean, and the second is the variance. * the random variable mean, and the second is the variance.
*/ */
public double[] getReceivedSignalStrength(double sourceX, double sourceY, double destX, double destY) { public double[] getReceivedSignalStrength(double sourceX, double sourceY, double destX, double destY) {
return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.SIGNAL_STRENGTH); return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.SIGNAL_STRENGTH, null);
} }
public double[] getReceivedSignalStrength(double sourceX, double sourceY, double destX, double destY, Double txPower) {
return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.SIGNAL_STRENGTH, txPower);
}
// TODO Fix better data type support // TODO Fix better data type support
private double[] getTransmissionData(double sourceX, double sourceY, double destX, double destY, TransmissionData dataType) { private double[] getTransmissionData(double sourceX, double sourceY, double destX, double destY, TransmissionData dataType, Double txPower) {
Point2D source = new Point2D.Double(sourceX, sourceY); Point2D source = new Point2D.Double(sourceX, sourceY);
Point2D dest = new Point2D.Double(destX, destY); Point2D dest = new Point2D.Double(destX, destY);
double accumulatedVariance = 0; double accumulatedVariance = 0;
@ -1515,7 +1518,12 @@ public class ChannelModel {
// Using formula (dB) // Using formula (dB)
// Received power = Output power + System gain + Transmitter gain + Path Loss + Receiver gain // Received power = Output power + System gain + Transmitter gain + Path Loss + Receiver gain
// TODO Update formulas // TODO Update formulas
double outputPower = getParameterDoubleValue("tx_power"); double outputPower;
if (txPower == null) {
outputPower = getParameterDoubleValue("tx_power");
} else {
outputPower = txPower;
}
double systemGain = getParameterDoubleValue("system_gain_mean"); double systemGain = getParameterDoubleValue("system_gain_mean");
if (getParameterBooleanValue("apply_random")) { if (getParameterBooleanValue("apply_random")) {
Random random = new Random(); /* TODO Use main random generator? */ Random random = new Random(); /* TODO Use main random generator? */
@ -1579,19 +1587,19 @@ public class ChannelModel {
* variable. This method uses current parameters such as transmitted power, * variable. This method uses current parameters such as transmitted power,
* obstacles, overall system loss etc. * obstacles, overall system loss etc.
* *
* @param sourceX * @param sourceX Source position X
* Source position X * @param sourceY Source position Y
* @param sourceY * @param destX Destination position X
* Source position Y * @param destY Destination position Y
* @param destX * @return Received SNR (dB) random variable:
* Destination position X * The first value in the array is the random variable mean.
* @param destY * The second is the variance.
* Destination position Y * The third value is the received signal strength which may be used in comparison with interference etc.
* @return Received SNR (dB) random variable. The first value is the random
* variable mean, and the second is the variance. The third value is the received signal strength which may be used in comparison with interference etc.
*/ */
public double[] getSINR(double sourceX, double sourceY, double destX, double destY, double interference) { public double[] getSINR(double sourceX, double sourceY, double destX, double destY, double interference) {
/* TODO Cache values: called repeatedly with noise sources. */
// Calculate received signal strength // Calculate received signal strength
double[] signalStrength = getReceivedSignalStrength(sourceX, sourceY, destX, destY); double[] signalStrength = getReceivedSignalStrength(sourceX, sourceY, destX, destY);
@ -1619,27 +1627,26 @@ public class ChannelModel {
snrData[1] += noiseVariance; snrData[1] += noiseVariance;
if (logMode) { if (logMode) {
logInfo.append("\nReceived SNR: " + String.format("%2.3f", snrData[0]) + " (variance " + snrData[1] + ")\n"); logInfo.append("\nReceived SNR: " + String.format("%2.3f", snrData[0]) + " dB (variance " + snrData[1] + ")\n");
} }
return snrData; return snrData;
} }
/** /**
* Calculates and returns probability that a receiver at given destination receives a packet from a transmitter at given source. * Calculates probability that a receiver at given destination receives
* a packet from a transmitter at given source.
* This method uses current parameters such as transmitted power, * This method uses current parameters such as transmitted power,
* obstacles, overall system loss, packet size etc. TODO Packet size?! TODO Interfering signal strength * obstacles, overall system loss, packet size etc.
*
* TODO Packet size
* TODO External interference/Background noise
* *
* @param sourceX * @param sourceX Source position X
* Source position X * @param sourceY Source position Y
* @param sourceY * @param destX Destination position X
* Source position Y * @param destY Destination position Y
* @param destX * @param interference Current interference at destination (dBm)
* Destination position X
* @param destY
* Destination position Y
* @param interference
* Current interference at destination (dBm)
* @return [Probability of reception, signal strength at destination] * @return [Probability of reception, signal strength at destination]
*/ */
public double[] getProbability(double sourceX, double sourceY, double destX, double destY, double interference) { public double[] getProbability(double sourceX, double sourceY, double destX, double destY, double interference) {
@ -1675,11 +1682,9 @@ public class ChannelModel {
// current threshold. // current threshold.
// (Using error algorithm method, much faster than taylor approximation!) // (Using error algorithm method, much faster than taylor approximation!)
double probReception = 1 - GaussianWrapper.cdfErrorAlgo( double probReception = 1 - GaussianWrapper.cdfErrorAlgo(threshold, snrMean, snrStdDev);
threshold, snrMean, snrStdDev);
if (logMode) { if (logMode) {
logInfo.append("\nReceived SNR: " + String.format("%2.3f", snrData[0]) + " (variance " + snrData[1] + ")\n");
logInfo.append("Reception probability: " + String.format("%1.1f%%", 100*probReception) + "\n"); logInfo.append("Reception probability: " + String.format("%1.1f%%", 100*probReception) + "\n");
} }
@ -1703,7 +1708,7 @@ public class ChannelModel {
* @return RMS delay spread * @return RMS delay spread
*/ */
public double getRMSDelaySpread(double sourceX, double sourceY, double destX, double destY) { public double getRMSDelaySpread(double sourceX, double sourceY, double destX, double destY) {
return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.DELAY_SPREAD)[1]; return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.DELAY_SPREAD, null)[1];
} }
/** /**

View File

@ -43,13 +43,14 @@ import org.jdom.Element;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.RadioConnection; import se.sics.cooja.RadioConnection;
import se.sics.cooja.Simulation; import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.NoiseSourceRadio;
import se.sics.cooja.interfaces.NoiseSourceRadio.NoiseLevelListener;
import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.radiomediums.AbstractRadioMedium; import se.sics.cooja.radiomediums.AbstractRadioMedium;
/** /**
* This is the main class of the COOJA Multi-path Ray-tracing Medium (MRM) * Multi-path Ray-tracing radio medium (MRM).
* package.
* *
* MRM is an alternative to the simpler radio mediums available in * MRM is an alternative to the simpler radio mediums available in
* COOJA. It is packet based and uses a 2D ray-tracing approach to approximate * COOJA. It is packet based and uses a 2D ray-tracing approach to approximate
@ -57,22 +58,27 @@ import se.sics.cooja.radiomediums.AbstractRadioMedium;
* ray-tracing only supports reflections and refractions through homogeneous * ray-tracing only supports reflections and refractions through homogeneous
* obstacles. * obstacles.
* *
* MRM registers two plugins: a plugin for visualizing the radio * MRM provides two plugins: one for visualizing the radio environment,
* environments, and a plugin for configuring the radio medium parameters. * and one for configuring the radio medium parameters.
* *
* Future work includes adding support for diffraction and scattering. * Future work includes adding support for diffraction and scattering.
* *
* MRM supports noise source radios.
*
* @see NoiseSourceRadio
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ClassDescription("Multi-path Ray-tracer Medium (MRM)") @ClassDescription("Multi-path Ray-tracer Medium (MRM)")
public class MRM extends AbstractRadioMedium { public class MRM extends AbstractRadioMedium {
private static Logger logger = Logger.getLogger(MRM.class); private static Logger logger = Logger.getLogger(MRM.class);
private ChannelModel currentChannelModel = null; public final static boolean WITH_NOISE = true; /* NoiseSourceRadio:s */
public final static boolean WITH_CAPTURE_EFFECT = true;
private Random random = null;
private Simulation sim; private Simulation sim;
private Random random = null;
private ChannelModel currentChannelModel = null;
/** /**
* Notifies observers when this radio medium has changed settings. * Notifies observers when this radio medium has changed settings.
*/ */
@ -83,11 +89,9 @@ public class MRM extends AbstractRadioMedium {
*/ */
public MRM(Simulation simulation) { public MRM(Simulation simulation) {
super(simulation); super(simulation);
sim = simulation;
random = simulation.getRandomGenerator();
// Create the channel model sim = simulation;
random = simulation.getRandomGenerator();
currentChannelModel = new ChannelModel(); currentChannelModel = new ChannelModel();
/* Register plugins */ /* Register plugins */
@ -95,6 +99,26 @@ public class MRM extends AbstractRadioMedium {
sim.getGUI().registerPlugin(FormulaViewer.class); sim.getGUI().registerPlugin(FormulaViewer.class);
} }
private NoiseLevelListener noiseListener = new NoiseLevelListener() {
public void noiseLevelChanged(NoiseSourceRadio radio, int signal) {
updateSignalStrengths();
};
};
public void registerRadioInterface(Radio radio, Simulation sim) {
super.registerRadioInterface(radio, sim);
if (radio instanceof NoiseSourceRadio) {
((NoiseSourceRadio)radio).addNoiseLevelListener(noiseListener);
}
}
public void unregisterRadioInterface(Radio radio, Simulation sim) {
super.unregisterRadioInterface(radio, sim);
if (radio instanceof NoiseSourceRadio) {
((NoiseSourceRadio)radio).removeNoiseLevelListener(noiseListener);
}
}
public void removed() { public void removed() {
super.removed(); super.removed();
@ -103,90 +127,82 @@ public class MRM extends AbstractRadioMedium {
sim.getGUI().unregisterPlugin(FormulaViewer.class); sim.getGUI().unregisterPlugin(FormulaViewer.class);
} }
public MRMRadioConnection createConnections(Radio sendingRadio) { public MRMRadioConnection createConnections(Radio sender) {
Position sendingPosition = sendingRadio.getPosition(); MRMRadioConnection newConnection = new MRMRadioConnection(sender);
MRMRadioConnection newConnection = new MRMRadioConnection(sendingRadio); Position senderPos = sender.getPosition();
// Loop through all radios /* TODO Cache potential destination in DGRM */
for (Radio listeningRadio: getRegisteredRadios()) { /* Loop through all potential destinations */
// Ignore sending radio and radios on different channels for (Radio recv: getRegisteredRadios()) {
if (sendingRadio == listeningRadio) { if (sender == recv) {
continue;
}
if (sendingRadio.getChannel() >= 0 &&
listeningRadio.getChannel() >= 0 &&
sendingRadio.getChannel() != listeningRadio.getChannel()) {
continue; continue;
} }
/* TODO Use DGRM to cache link information. /* Fail if radios are on different (but configured) channels */
* (No need to loop over all receivers) */ if (sender.getChannel() >= 0 &&
recv.getChannel() >= 0 &&
double listeningPositionX = listeningRadio.getPosition().getXCoordinate(); sender.getChannel() != recv.getChannel()) {
double listeningPositionY = listeningRadio.getPosition().getYCoordinate(); continue;
}
Position recvPos = recv.getPosition();
// Calculate probability of reception of listening radio /* Calculate receive probability */
double[] probData = currentChannelModel.getProbability( double[] probData = currentChannelModel.getProbability(
sendingPosition.getXCoordinate(), senderPos.getXCoordinate(),
sendingPosition.getYCoordinate(), senderPos.getYCoordinate(),
listeningPositionX, recvPos.getXCoordinate(),
listeningPositionY, recvPos.getYCoordinate(),
-Double.MAX_VALUE -Double.MAX_VALUE /* TODO Include interference */
); );
//logger.info("Probability of reception is " + probData[0]); double recvProb = probData[0];
//logger.info("Signal strength at destination is " + probData[1]); double recvSignalStrength = probData[1];
if (random.nextFloat() < probData[0]) { if (recvProb == 1.0 || random.nextDouble() < recvProb) {
// Check if this radio is able to receive transmission /* Yes, the receiver *may* receive this packet (it's strong enough) */
if (listeningRadio.isInterfered()) { if (!recv.isReceiverOn()) {
// Keep interfering radio newConnection.addInterfered(recv);
newConnection.addInterfered(listeningRadio, probData[1]); recv.interfereAnyReception();
} else if (recv.isInterfered()) {
/* Was interfered: keep interfering */
newConnection.addInterfered(recv, recvSignalStrength);
} else if (recv.isTransmitting()) {
newConnection.addInterfered(recv, recvSignalStrength);
} else if (recv.isReceiving()) {
/* Was already receiving: start interfering.
* Assuming no continuous preambles checking */
double currSignal = recv.getCurrentSignalStrength();
/* Capture effect: recv-radio is already receiving.
* Are we strong enough to interfere? */
if (WITH_CAPTURE_EFFECT &&
recvSignalStrength < currSignal - 3 /* config */) {
/* No, we are too weak */
} else {
newConnection.addInterfered(recv, recvSignalStrength);
recv.interfereAnyReception();
} else if (listeningRadio.isReceiving()) { /* Interfere receiver in all other active radio connections */
newConnection.addInterfered(listeningRadio, probData[1]); for (RadioConnection conn : getActiveConnections()) {
if (conn.isDestination(recv)) {
// Start interfering radio conn.addInterfered(recv);
listeningRadio.interfereAnyReception();
// Update connection that is transmitting to this radio
MRMRadioConnection existingConn = null;
for (RadioConnection conn : getActiveConnections()) {
for (Radio dstRadio : ((MRMRadioConnection) conn).getDestinations()) {
if (dstRadio == listeningRadio) {
existingConn = (MRMRadioConnection) conn;
break;
} }
} }
} }
if (existingConn != null) {
/* Flag radio as interfered */
existingConn.addInterfered(listeningRadio);
listeningRadio.interfereAnyReception();
}
} else { } else {
// Radio OK to receive /* Success: radio starts receiving */
//logger.info("OK, creating connection and starting to transmit"); newConnection.addDestination(recv, recvSignalStrength);
newConnection.addDestination(listeningRadio, probData[1]);
} }
} else if (probData[1] > currentChannelModel.getParameterDoubleValue("bg_noise_mean")) { } else if (recvSignalStrength > currentChannelModel.getParameterDoubleValue("bg_noise_mean")) {
// Interfere radio /* The incoming signal is strong, but strong enough to interfere? */
newConnection.addInterfered(listeningRadio, probData[1]);
listeningRadio.interfereAnyReception();
// TODO Radios always get interfered right now, should recalculate probability
// if (maxInterferenceSignalStrength + SOME_RELEVANT_LIMIT > transmissionSignalStrength) {
// // Recalculating probability of delivery
// double[] probData = currentChannelModel.getProbability(
// mySource.source.position.getXCoordinate(),
// mySource.source.position.getYCoordinate(),
// myDestination.position.getXCoordinate(),
// myDestination.position.getYCoordinate(),
// maxInterferenceSignalStrength);
//
// if (new Random().nextFloat() >= probData[0]) {
// return true;
// }
if (!WITH_CAPTURE_EFFECT) {
newConnection.addInterfered(recv, recvSignalStrength);
recv.interfereAnyReception();
} else {
/* TODO Implement new type: newConnection.addNoise()?
* Currently, this connection will never disturb this radio... */
}
} }
} }
@ -195,57 +211,92 @@ public class MRM extends AbstractRadioMedium {
} }
public void updateSignalStrengths() { public void updateSignalStrengths() {
// // Save old signal strengths
// double[] oldSignalStrengths = new double[registeredRadios.size()];
// for (int i = 0; i < registeredRadios.size(); i++) {
// oldSignalStrengths[i] = registeredRadios.get(i)
// .getCurrentSignalStrength();
// }
// Reset signal strength on all radios /* Reset: Background noise */
double background =
currentChannelModel.getParameterDoubleValue(("bg_noise_mean"));
for (Radio radio : getRegisteredRadios()) { for (Radio radio : getRegisteredRadios()) {
radio.setCurrentSignalStrength(currentChannelModel.getParameterDoubleValue(("bg_noise_mean"))); radio.setCurrentSignalStrength(background);
} }
// Set signal strength on all OK transmissions /* Active radio connections */
for (RadioConnection conn : getActiveConnections()) { RadioConnection[] conns = getActiveConnections();
// ((MRMRadioConnection) conn).getSource().setCurrentSignalStrength(12345); // TODO Set signal strength on source? for (RadioConnection conn : conns) {
for (Radio dstRadio : ((MRMRadioConnection) conn).getDestinations()) { for (Radio dstRadio : ((MRMRadioConnection) conn).getDestinations()) {
double signalStrength = ((MRMRadioConnection) conn).getDestinationSignalStrength(dstRadio); double signalStrength = ((MRMRadioConnection) conn).getDestinationSignalStrength(dstRadio);
if (signalStrength > dstRadio.getCurrentSignalStrength()) { if (dstRadio.getCurrentSignalStrength() < signalStrength) {
dstRadio.setCurrentSignalStrength(signalStrength); dstRadio.setCurrentSignalStrength(signalStrength);
} }
} }
} }
// Set signal strength on all interferences /* Interfering/colliding radio connections */
for (RadioConnection conn : getActiveConnections()) { for (RadioConnection conn : conns) {
for (Radio interferedRadio : ((MRMRadioConnection) conn).getInterfered()) { for (Radio intfRadio : ((MRMRadioConnection) conn).getInterfered()) {
double signalStrength = ((MRMRadioConnection) conn).getInterferenceSignalStrength(interferedRadio); double signalStrength = ((MRMRadioConnection) conn).getInterferenceSignalStrength(intfRadio);
if (signalStrength > interferedRadio.getCurrentSignalStrength()) { if (intfRadio.getCurrentSignalStrength() < signalStrength) {
interferedRadio.setCurrentSignalStrength(signalStrength); intfRadio.setCurrentSignalStrength(signalStrength);
} }
if (!interferedRadio.isInterfered()) { if (!intfRadio.isInterfered()) {
// Set to interfered again /*logger.warn("Radio was not interfered: " + intfRadio);*/
interferedRadio.interfereAnyReception(); intfRadio.interfereAnyReception();
} }
} }
} }
// // Fetch new signal strengths /* Check for noise sources */
// double[] newSignalStrengths = new double[registeredRadios.size()]; if (!WITH_NOISE) return;
// for (int i = 0; i < registeredRadios.size(); i++) { for (Radio noiseRadio: getRegisteredRadios()) {
// newSignalStrengths[i] = registeredRadios.get(i) if (!(noiseRadio instanceof NoiseSourceRadio)) {
// .getCurrentSignalStrength(); continue;
// } }
// NoiseSourceRadio radio = (NoiseSourceRadio) noiseRadio;
// // Compare new and old signal strengths int signalStrength = radio.getNoiseLevel();
// for (int i = 0; i < registeredRadios.size(); i++) { if (signalStrength == Integer.MIN_VALUE) {
// if (oldSignalStrengths[i] != newSignalStrengths[i]) continue;
// logger.warn("Signal strengths changed on radio[" + i + "]: " }
// + oldSignalStrengths[i] + " -> " + newSignalStrengths[i]);
// } /* Calculate how noise source affects surrounding radios */
for (Radio affectedRadio : getRegisteredRadios()) {
if (noiseRadio == affectedRadio) {
continue;
}
/* Update noise levels */
double[] signalMeanVar = currentChannelModel.getReceivedSignalStrength(
noiseRadio.getPosition().getXCoordinate(),
noiseRadio.getPosition().getYCoordinate(),
affectedRadio.getPosition().getXCoordinate(),
affectedRadio.getPosition().getYCoordinate(),
(double) signalStrength); /* TODO Convert to dBm */
double signal = signalMeanVar[0];
if (signal < background) {
continue;
}
/* TODO Additive signals strengths? */
/* TODO XXX Consider radio channels */
/* TODO XXX Potentially interfere even when signal is weaker (~3dB)...
* (we may alternatively just use the getSINR method...) */
if (affectedRadio.getCurrentSignalStrength() < signal) {
affectedRadio.setCurrentSignalStrength(signal);
/* TODO Interfere with radio connections? */
if (affectedRadio.isReceiving() && !affectedRadio.isInterfered()) {
for (RadioConnection conn : conns) {
if (conn.isDestination(affectedRadio)) {
/* Intefere with current reception, mark radio as interfered */
conn.addInterfered(affectedRadio);
if (!affectedRadio.isInterfered()) {
affectedRadio.interfereAnyReception();
}
}
}
}
}
}
}
} }
public Collection<Element> getConfigXML() { public Collection<Element> getConfigXML() {
@ -279,20 +330,11 @@ public class MRM extends AbstractRadioMedium {
settingsObservable.deleteObserver(obs); settingsObservable.deleteObserver(obs);
} }
/**
* Returns position of given radio.
*
* @param radio Registered radio
* @return Position of given radio
*/
public Position getRadioPosition(Radio radio) {
return radio.getPosition();
}
/** /**
* @return Number of registered radios. * @return Number of registered radios.
*/ */
public int getRegisteredRadioCount() { public int getRegisteredRadioCount() {
/* TODO Expensive operation */
return getRegisteredRadios().length; return getRegisteredRadios().length;
} }