From ffa4482799851a4f54b0066c1ee6b59cbe7ef86b Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Thu, 3 Nov 2011 11:23:51 +0100 Subject: [PATCH] improved capture effect support in mrm: capture effect is effective if the latter transmission is stronger and no later than half the preamble --- .../mrm/java/se/sics/mrm/ChannelModel.java | 20 ++++- .../mrm/java/se/sics/mrm/FormulaViewer.java | 21 +++++ .../cooja/apps/mrm/java/se/sics/mrm/MRM.java | 84 ++++++++++++++++--- .../java/se/sics/cooja/RadioConnection.java | 27 ++++++ 4 files changed, 138 insertions(+), 14 deletions(-) diff --git a/tools/cooja/apps/mrm/java/se/sics/mrm/ChannelModel.java b/tools/cooja/apps/mrm/java/se/sics/mrm/ChannelModel.java index 17ae7f8d4..74eeff717 100644 --- a/tools/cooja/apps/mrm/java/se/sics/mrm/ChannelModel.java +++ b/tools/cooja/apps/mrm/java/se/sics/mrm/ChannelModel.java @@ -135,7 +135,10 @@ public class ChannelModel { rt_reflec_coefficient, rt_diffr_coefficient, rt_scatt_coefficient, - obstacle_attenuation; + obstacle_attenuation, + captureEffect, + captureEffectPreambleDuration, + captureEffectSignalTreshold; public static Object getDefaultValue(Parameter p) { switch (p) { @@ -187,6 +190,12 @@ public class ChannelModel { return new Double(-20); case obstacle_attenuation: return new Double(-3); + case captureEffect: + return true; + case captureEffectPreambleDuration: + return (double) (1000*1000*4*0.5*8/250000); /* 2 bytes, 250kbit/s, us */ + case captureEffectSignalTreshold: + return (double) 3; /* dB, according to previous 802.15.4 studies */ } throw new RuntimeException("Unknown default value: " + p); } @@ -235,6 +244,12 @@ public class ChannelModel { return rt_scatt_coefficient; } else if (name.equals("obstacle_attenuation")) { return obstacle_attenuation; + } else if (name.equals("captureEffect")) { + return captureEffect; + } else if (name.equals("captureEffectPreambleDuration")) { + return captureEffectPreambleDuration; + } else if (name.equals("captureEffectSignalTreshold")) { + return captureEffectSignalTreshold; } return null; } @@ -263,6 +278,9 @@ public class ChannelModel { case rt_reflec_coefficient: return "Reflection coefficient (dB)"; case rt_diffr_coefficient: return "Diffraction coefficient (dB)"; case obstacle_attenuation: return "Obstacle attenuation (dB/m)"; + case captureEffect: return "Use Capture Effect"; + case captureEffectPreambleDuration: return "Capture effect preamble (us)"; + case captureEffectSignalTreshold: return "Capture effect threshold (dB)"; } throw new RuntimeException("Unknown decrption: " + p); } diff --git a/tools/cooja/apps/mrm/java/se/sics/mrm/FormulaViewer.java b/tools/cooja/apps/mrm/java/se/sics/mrm/FormulaViewer.java index 96f34388d..07029d50c 100644 --- a/tools/cooja/apps/mrm/java/se/sics/mrm/FormulaViewer.java +++ b/tools/cooja/apps/mrm/java/se/sics/mrm/FormulaViewer.java @@ -151,6 +151,27 @@ public class FormulaViewer extends se.sics.cooja.VisPlugin { channelModel.getParameterDoubleValue(Parameter.frequency) ); + addBooleanParameter( + Parameter.captureEffect, + Parameter.getDescription(Parameter.captureEffect), + collapsableArea, + channelModel.getParameterBooleanValue(Parameter.captureEffect) + ); + + addDoubleParameter( + Parameter.captureEffectPreambleDuration, + Parameter.getDescription(Parameter.captureEffectPreambleDuration), + collapsableArea, + channelModel.getParameterDoubleValue(Parameter.captureEffectPreambleDuration) + ); + + addDoubleParameter( + Parameter.captureEffectSignalTreshold, + Parameter.getDescription(Parameter.captureEffectSignalTreshold), + collapsableArea, + channelModel.getParameterDoubleValue(Parameter.captureEffectSignalTreshold) + ); + // Transmitter parameters collapsableArea = createCollapsableArea("Transmitter parameters", allComponents); areaTransmitter = collapsableArea; diff --git a/tools/cooja/apps/mrm/java/se/sics/mrm/MRM.java b/tools/cooja/apps/mrm/java/se/sics/mrm/MRM.java index f97520265..6ef04e93a 100644 --- a/tools/cooja/apps/mrm/java/se/sics/mrm/MRM.java +++ b/tools/cooja/apps/mrm/java/se/sics/mrm/MRM.java @@ -80,8 +80,13 @@ public class MRM extends AbstractRadioMedium { public final static boolean WITH_NOISE = true; /* NoiseSourceRadio */ public final static boolean WITH_DIRECTIONAL = true; /* DirectionalAntennaRadio */ - public final static boolean WITH_CAPTURE_EFFECT = true; + private Observer channelModelObserver = null; + + private boolean WITH_CAPTURE_EFFECT; + private double CAPTURE_EFFECT_THRESHOLD; + private double CAPTURE_EFFECT_PREAMBLE_DURATION; + private Simulation sim; private Random random = null; private ChannelModel currentChannelModel = null; @@ -100,7 +105,19 @@ public class MRM extends AbstractRadioMedium { sim = simulation; random = simulation.getRandomGenerator(); currentChannelModel = new ChannelModel(sim); - + + WITH_CAPTURE_EFFECT = currentChannelModel.getParameterBooleanValue(ChannelModel.Parameter.captureEffect); + CAPTURE_EFFECT_THRESHOLD = currentChannelModel.getParameterDoubleValue(ChannelModel.Parameter.captureEffectSignalTreshold); + CAPTURE_EFFECT_PREAMBLE_DURATION = currentChannelModel.getParameterDoubleValue(ChannelModel.Parameter.captureEffectPreambleDuration); + + currentChannelModel.addSettingsObserver(channelModelObserver = new Observer() { + public void update(Observable o, Object arg) { + WITH_CAPTURE_EFFECT = currentChannelModel.getParameterBooleanValue(ChannelModel.Parameter.captureEffect); + CAPTURE_EFFECT_THRESHOLD = currentChannelModel.getParameterDoubleValue(ChannelModel.Parameter.captureEffectSignalTreshold); + CAPTURE_EFFECT_PREAMBLE_DURATION = currentChannelModel.getParameterDoubleValue(ChannelModel.Parameter.captureEffectPreambleDuration); + } + }); + /* Register plugins */ sim.getGUI().registerPlugin(AreaViewer.class); sim.getGUI().registerPlugin(FormulaViewer.class); @@ -114,6 +131,8 @@ public class MRM extends AbstractRadioMedium { sim.getGUI().unregisterPlugin(AreaViewer.class); sim.getGUI().unregisterPlugin(FormulaViewer.class); Visualizer.unregisterVisualizerSkin(MRMVisualizerSkin.class); + + currentChannelModel.deleteSettingsObserver(channelModelObserver); } private NoiseLevelListener noiseListener = new NoiseLevelListener() { @@ -177,22 +196,26 @@ public class MRM extends AbstractRadioMedium { newConnection.addInterfered(recv); recv.interfereAnyReception(); } else if (recv.isInterfered()) { - /* Was interfered: keep interfering */ - newConnection.addInterfered(recv, recvSignalStrength); + if (WITH_CAPTURE_EFFECT) { + /* XXX TODO This may be wrong: + * If the interfering signal is both weaker and the SFD has not + * been received, then the stronger signal may actually be received. + */ + + /* Was interfered: keep interfering */ + newConnection.addInterfered(recv, recvSignalStrength); + } else { + /* 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); + + if (!WITH_CAPTURE_EFFECT) { + newConnection.addInterfered(recv, recvSignalStrength); recv.interfereAnyReception(); /* Interfere receiver in all other active radio connections */ @@ -201,7 +224,42 @@ public class MRM extends AbstractRadioMedium { conn.addInterfered(recv); } } + } else { + /* CAPTURE EFFECT */ + double currSignal = recv.getCurrentSignalStrength(); + /* Capture effect: recv-radio is already receiving. + * Are we strong enough to interfere? */ + + if (recvSignalStrength < currSignal - CAPTURE_EFFECT_THRESHOLD /* config */) { + /* No, we are too weak */ + } else { + /* New signal is strong enough to either interfere with ongoing transmission, + * or to be received/captured */ + long startTime = newConnection.getReceptionStartTime(); + boolean interfering = (sim.getSimulationTime()-startTime) >= CAPTURE_EFFECT_PREAMBLE_DURATION; /* us */ + if (interfering) { + newConnection.addInterfered(recv, recvSignalStrength); + recv.interfereAnyReception(); + + /* Interfere receiver in all other active radio connections */ + for (RadioConnection conn : getActiveConnections()) { + if (conn.isDestination(recv)) { + conn.addInterfered(recv); + } } + } else { + /* XXX Warning: removing destination from other connections */ + for (RadioConnection conn : getActiveConnections()) { + if (conn.isDestination(recv)) { + conn.removeDestination(recv); + } + } + + /* Success: radio starts receiving */ + newConnection.addDestination(recv, recvSignalStrength); + } + } + } } else { /* Success: radio starts receiving */ diff --git a/tools/cooja/java/se/sics/cooja/RadioConnection.java b/tools/cooja/java/se/sics/cooja/RadioConnection.java index cb1819f52..6cf24d722 100644 --- a/tools/cooja/java/se/sics/cooja/RadioConnection.java +++ b/tools/cooja/java/se/sics/cooja/RadioConnection.java @@ -90,6 +90,15 @@ public class RadioConnection { return startTime; } + /** + * @return Start time of ongoing reception + */ + public long getReceptionStartTime() { + /* TODO XXX: This may currently return the start time of an ongoing + * interference. */ + return getStartTime(); + } + /** * Add (non-interfered) destination radio to connection. * @@ -98,6 +107,24 @@ public class RadioConnection { public void addDestination(Radio radio) { addDestination(radio, new Long(0)); } + + /** + * Experimental: remove destination. + * + * @param radio Radio + */ + public void removeDestination(Radio radio) { + int idx = allDestinations.indexOf(radio); + if (idx < 0) { + logger.fatal("Radio is not a connection destination: " + radio); + return; + } + + allDestinations.remove(idx); + allDestinationDelays.remove(idx); + destinationsNonInterfered.remove(radio); + onlyInterfered.remove(radio); + } /** * Add (non-interfered) destination radio to connection.