Package se.sics.cooja.plugins.skins

Source Code of se.sics.cooja.plugins.skins.UDGMVisualizerSkin$SuccessRatioMenuAction

/*
* Copyright (c) 2009, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: UDGMVisualizerSkin.java,v 1.6 2009/04/20 18:09:54 fros4943 Exp $
*/

package se.sics.cooja.plugins.skins;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.apache.log4j.Logger;

import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.RadioConnection;
import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
import se.sics.cooja.plugins.Visualizer.SimulationMenuAction;
import se.sics.cooja.radiomediums.UDGM;

/**
* Visualizer skin for Unit Disk Graph radio medium.
*
* Allows a user to change the collective TX/interference ranges,
* and the TX/RX success ratio.
*
* Transmitting motes are painted blue. XXXXXXXX
* Receiving motes are painted green.
* Interfered motes are painted red.
* Motes without radios are painted gray.
* All other motes are painted white.
*
* @see UDGM
* @author Fredrik Osterlind
*/
@ClassDescription("Radio environment (UDGM)")
public class UDGMVisualizerSkin implements VisualizerSkin {
  private static Logger logger = Logger.getLogger(UDGMVisualizerSkin.class);

  private static final boolean DRAW_ARROWS = true;
 
  private Simulation simulation = null;
  private Visualizer visualizer = null;
  private UDGM radioMedium = null;
  private Observer radioMediumObserver;

  private JLabel txCounter = null;
  private JLabel rxCounter = null;
  private JLabel interferedCounter = null;

  private JSpinner txRangeSpinner = null;
  private JSpinner interferenceRangeSpinner = null;
  private JSpinner successRatioTxSpinner = null;
  private JSpinner successRatioRxSpinner = null;

  private Mote selectedMote = null;

  private MouseListener selectMoteMouseListener = new MouseListener() {
    public void mouseExited(MouseEvent e) { }
    public void mouseEntered(MouseEvent e) { }
    public void mouseReleased(MouseEvent e) { }
    public void mouseClicked(MouseEvent e) { }

    public void mousePressed(MouseEvent e) {
      Mote[] motes = visualizer.findMotesAtPosition(e.getX(), e.getY());
      if (motes == null || motes.length == 0) {
        selectedMote = null;
        txRangeSpinner.setVisible(false);
        interferenceRangeSpinner.setVisible(false);
        successRatioTxSpinner.setVisible(false);
        successRatioRxSpinner.setVisible(false);
        visualizer.repaint();
        return;
      }

      selectedMote = motes[0];
      visualizer.repaint();
    }
  };

  public void setActive(Simulation simulation, Visualizer vis) {
    if (!(simulation.getRadioMedium() instanceof UDGM)) {
      logger.fatal("Cannot activate UDGM skin for unknown radio medium: " + simulation.getRadioMedium());
      return;
    }
    this.simulation = simulation;
    this.visualizer = vis;
    this.radioMedium = (UDGM) simulation.getRadioMedium();

    /* Spinner GUI components */
    SpinnerNumberModel transmissionModel = new SpinnerNumberModel();
    transmissionModel.setValue(new Double(radioMedium.TRANSMITTING_RANGE));
    transmissionModel.setStepSize(new Double(1.0)); // 1m
    transmissionModel.setMinimum(new Double(0.0));

    SpinnerNumberModel interferenceModel = new SpinnerNumberModel();
    interferenceModel.setValue(new Double(radioMedium.INTERFERENCE_RANGE));
    interferenceModel.setStepSize(new Double(1.0)); // 1m
    interferenceModel.setMinimum(new Double(0.0));

    SpinnerNumberModel successRatioTxModel = new SpinnerNumberModel();
    successRatioTxModel.setValue(new Double(radioMedium.SUCCESS_RATIO_TX));
    successRatioTxModel.setStepSize(new Double(0.001)); // 0.1%
    successRatioTxModel.setMinimum(new Double(0.0));
    successRatioTxModel.setMaximum(new Double(1.0));

    SpinnerNumberModel successRatioRxModel = new SpinnerNumberModel();
    successRatioRxModel.setValue(new Double(radioMedium.SUCCESS_RATIO_RX));
    successRatioRxModel.setStepSize(new Double(0.001)); // 0.1%
    successRatioRxModel.setMinimum(new Double(0.0));
    successRatioRxModel.setMaximum(new Double(1.0));

    JSpinner.NumberEditor editor;
    txRangeSpinner = new JSpinner(transmissionModel);
    editor = new JSpinner.NumberEditor(txRangeSpinner, "0m");
    txRangeSpinner.setEditor(editor);
    interferenceRangeSpinner = new JSpinner(interferenceModel);
    editor = new JSpinner.NumberEditor(interferenceRangeSpinner, "0m");
    interferenceRangeSpinner.setEditor(editor);
    successRatioTxSpinner = new JSpinner(successRatioTxModel);
    editor = new JSpinner.NumberEditor(successRatioTxSpinner, "0.0%");
    successRatioTxSpinner.setEditor(editor);
    successRatioRxSpinner = new JSpinner(successRatioRxModel);
    editor = new JSpinner.NumberEditor(successRatioRxSpinner, "0.0%");
    successRatioRxSpinner.setEditor(editor);

    ((JSpinner.DefaultEditor) txRangeSpinner.getEditor()).getTextField().setColumns(5);
    ((JSpinner.DefaultEditor) interferenceRangeSpinner.getEditor()).getTextField().setColumns(5);
    ((JSpinner.DefaultEditor) successRatioTxSpinner.getEditor()).getTextField().setColumns(5);
    ((JSpinner.DefaultEditor) successRatioRxSpinner.getEditor()).getTextField().setColumns(5);
    txRangeSpinner.setToolTipText("Transmitting range (m)");
    interferenceRangeSpinner.setToolTipText("Interference range (m)");
    successRatioTxSpinner.setToolTipText("Transmission success ratio (%)");
    successRatioRxSpinner.setToolTipText("Reception success ratio (%)");

    txRangeSpinner.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        radioMedium.TRANSMITTING_RANGE = ((SpinnerNumberModel)
            txRangeSpinner.getModel()).getNumber().doubleValue();
        visualizer.repaint();
      }
    });

    interferenceRangeSpinner.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        radioMedium.INTERFERENCE_RANGE = ((SpinnerNumberModel)
            interferenceRangeSpinner.getModel()).getNumber().doubleValue();
        visualizer.repaint();
      }
    });

    successRatioTxSpinner.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        radioMedium.SUCCESS_RATIO_TX = ((SpinnerNumberModel)
            successRatioTxSpinner.getModel()).getNumber().doubleValue();
        visualizer.repaint();
      }
    });

    successRatioRxSpinner.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        radioMedium.SUCCESS_RATIO_RX = ((SpinnerNumberModel)
            successRatioRxSpinner.getModel()).getNumber().doubleValue();
        visualizer.repaint();
      }
    });

    txRangeSpinner.setVisible(false);
    interferenceRangeSpinner.setVisible(false);
    successRatioTxSpinner.setVisible(false);
    successRatioRxSpinner.setVisible(false);

    /* Register mouse listener */
    visualizer.getCurrentCanvas().addMouseListener(selectMoteMouseListener);

    /* Register menu actions */
    visualizer.registerSimulationMenuAction(RangeMenuAction.class);
    visualizer.registerSimulationMenuAction(SuccessRatioMenuAction.class);

    /* Add (currently invisible) spinners */
    txCounter = new JLabel("TX: " + radioMedium.COUNTER_TX);
    rxCounter = new JLabel("RX: " + radioMedium.COUNTER_RX);
    interferedCounter = new JLabel("INT: " +  + radioMedium.COUNTER_INTERFERED);
    visualizer.getCurrentCanvas().add(txCounter);
    visualizer.getCurrentCanvas().add(rxCounter);
    visualizer.getCurrentCanvas().add(interferedCounter);

    visualizer.getCurrentCanvas().add(txRangeSpinner);
    visualizer.getCurrentCanvas().add(interferenceRangeSpinner);
    visualizer.getCurrentCanvas().add(successRatioTxSpinner);
    visualizer.getCurrentCanvas().add(successRatioRxSpinner);

    /* Start observing radio medium */
    radioMedium.addRadioMediumObserver(radioMediumObserver = new Observer() {
      public void update(Observable obs, Object obj) {
        if (txCounter != null) {
          txCounter.setText("TX: " + radioMedium.COUNTER_TX);
        }
        if (rxCounter != null) {
          rxCounter.setText("RX: " + radioMedium.COUNTER_RX);
        }
        if (interferedCounter != null) {
          interferedCounter.setText("INT: " +  + radioMedium.COUNTER_INTERFERED);
        }

        visualizer.repaint();
      }
    });
  }

  public void setInactive() {
    if (simulation == null) {
      /* Skin was never activated */
      return;
    }

    /* Remove mouse listener */
    visualizer.getCurrentCanvas().removeMouseListener(selectMoteMouseListener);

    /* Stop observing radio medium */
    radioMedium.deleteRadioMediumObserver(radioMediumObserver);
    radioMediumObserver = null;
    radioMedium = null;

    visualizer.getCurrentCanvas().remove(txCounter);
    visualizer.getCurrentCanvas().remove(rxCounter);
    visualizer.getCurrentCanvas().remove(interferedCounter);

    /* Remove spinners */
    visualizer.getCurrentCanvas().remove(txRangeSpinner);
    visualizer.getCurrentCanvas().remove(interferenceRangeSpinner);
    visualizer.getCurrentCanvas().remove(successRatioTxSpinner);
    visualizer.getCurrentCanvas().remove(successRatioRxSpinner);

    /* Unregister menu actions */
    visualizer.unregisterSimulationMenuAction(RangeMenuAction.class);
    visualizer.unregisterSimulationMenuAction(SuccessRatioMenuAction.class);
  }

  public Color[] getColorOf(Mote mote) {
    if (simulation == null) {
      /* Skin was never activated */
      return null;
    }

    if (mote.getState() == Mote.State.DEAD) {
      return null;
    }

    Radio moteRadio = mote.getInterfaces().getRadio();
    if (moteRadio == null) {
      return null;
    }

    if (selectedMote != null && mote == selectedMote) {
      return new Color[] { Color.CYAN };
    }

    if (!moteRadio.isReceiverOn()) {
      return new Color[] { Color.GRAY };
    }

    if (moteRadio.isTransmitting()) {
      return new Color[] { Color.BLUE };
    }

    if (moteRadio.isInterfered()) {
      return new Color[] { Color.RED };
    }

    if (moteRadio.isReceiving()) {
      return new Color[] { Color.GREEN };
    }

    return null;
  }

  private static Color COLOR_INTERFERENCE = new Color(
      Color.DARK_GRAY.getRed(),
      Color.DARK_GRAY.getGreen(),
      Color.DARK_GRAY.getBlue(),
      100
  );
  private static Color COLOR_TX = new Color(
      Color.GREEN.getRed(),
      Color.GREEN.getGreen(),
      Color.GREEN.getBlue(),
      100
  );
  public void paintSkin(Graphics g) {
    if (simulation == null) {
      /* Skin was never activated */
      return;
    }

    /* Paint transmission and interference range for select mote */
    if (selectedMote != null) {
      Graphics2D g2 = (Graphics2D) g;
      Position motePos = selectedMote.getInterfaces().getPosition();

      Point pixelCoord = visualizer.transformPositionToPixel(motePos);
      int x = pixelCoord.x;
      int y = pixelCoord.y;

      // Fetch current output power indicator (scale with as percent)
      if (selectedMote.getInterfaces().getRadio() != null) {
        Radio selectedRadio = selectedMote.getInterfaces().getRadio();
        double moteInterferenceRange =
          radioMedium.INTERFERENCE_RANGE
          * ((double) selectedRadio.getCurrentOutputPowerIndicator()
              / (double) selectedRadio.getOutputPowerIndicatorMax());
        double moteTransmissionRange =
          radioMedium.TRANSMITTING_RANGE
          * ((double) selectedRadio.getCurrentOutputPowerIndicator()
              / (double) selectedRadio.getOutputPowerIndicatorMax());

        Point translatedZero = visualizer.transformPositionToPixel(0.0, 0.0, 0.0);
        Point translatedInterference = visualizer.transformPositionToPixel(moteInterferenceRange, moteInterferenceRange, 0.0);
        Point translatedTransmission = visualizer.transformPositionToPixel(moteTransmissionRange, moteTransmissionRange, 0.0);

        translatedInterference.x = Math.abs(translatedInterference.x - translatedZero.x);
        translatedInterference.y = Math.abs(translatedInterference.y - translatedZero.y);
        translatedTransmission.x = Math.abs(translatedTransmission.x - translatedZero.x);
        translatedTransmission.y = Math.abs(translatedTransmission.y - translatedZero.y);

        /* Interference range */
        g.setColor(COLOR_INTERFERENCE);
        g.fillOval(
            x - translatedInterference.x,
            y - translatedInterference.y,
            2 * translatedInterference.x,
            2 * translatedInterference.y);

        /* Transmission range */
        g.setColor(COLOR_TX);
        g.fillOval(
            x - translatedTransmission.x,
            y - translatedTransmission.y,
            2 * translatedTransmission.x,
            2 * translatedTransmission.y);
      }
    }

    /* Paint active connections in black */
    RadioConnection[] conns = radioMedium.getActiveConnections();
    if (conns != null) {
      g.setColor(Color.BLACK);
      for (RadioConnection conn : conns) {
        Radio source = conn.getSource();
        Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition());
        for (Radio destRadio : conn.getDestinations()) {
          Position destPos = destRadio.getPosition();
          Point destPoint = visualizer.transformPositionToPixel(destPos);
          g.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y);

          /* Draw arrows */
          if (DRAW_ARROWS) {
            Point centerPoint = new Point(
                destPoint.x/2 + sourcePoint.x/2,
                destPoint.y/2 + sourcePoint.y/2
            );
            int startAngle = (int) (-180 * Math.atan2(destPoint.y - sourcePoint.y, destPoint.x - sourcePoint.x)/Math.PI - 90);
            g.drawArc(centerPoint.x-5, centerPoint.y-5, 10, 10, startAngle, 180);
          }
        }
      }
    }

    /* Paint past connections in gray */
    /*conns = radioMedium.getLastTickConnections();
    if (conns != null) {
      g.setColor(Color.GRAY);
      for (RadioConnection conn : conns) {
        Point sourcePoint = visualizer.transformPositionToPixel(conn.getSource().getPosition());
        for (Radio dest : conn.getDestinations()) {
          Position destPos = dest.getPosition();
          Point destPoint = visualizer.transformPositionToPixel(destPos);
          g.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y);
        }
      }
    }*/
  }

  public static class RangeMenuAction implements SimulationMenuAction {
    public boolean isEnabled(Simulation simulation) {
      return true;
    }

    public String getDescription(Simulation simulation) {
      return "Change transmission ranges";
    }

    public void doAction(Visualizer visualizer, Simulation simulation) {
      VisualizerSkin[] skins = visualizer.getCurrentSkins();
      for (VisualizerSkin skin: skins) {
        if (skin instanceof UDGMVisualizerSkin) {
          ((UDGMVisualizerSkin)skin).txRangeSpinner.setVisible(true);
          ((UDGMVisualizerSkin)skin).interferenceRangeSpinner.setVisible(true);
          visualizer.repaint();
        }
      }
    }
  };

  public static class SuccessRatioMenuAction implements SimulationMenuAction {
    public boolean isEnabled(Simulation simulation) {
      return true;
    }

    public String getDescription(Simulation simulation) {
      return "Change TX/RX success ratio";
    }

    public void doAction(Visualizer visualizer, Simulation simulation) {
      VisualizerSkin[] skins = visualizer.getCurrentSkins();
      for (VisualizerSkin skin: skins) {
        if (skin instanceof UDGMVisualizerSkin) {
          ((UDGMVisualizerSkin)skin).successRatioTxSpinner.setVisible(true);
          ((UDGMVisualizerSkin)skin).successRatioRxSpinner.setVisible(true);
          visualizer.repaint();
        }
      }
    }
  };

  public Visualizer getVisualizer() {
    return visualizer;
  }
}
TOP

Related Classes of se.sics.cooja.plugins.skins.UDGMVisualizerSkin$SuccessRatioMenuAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.