// package plugins; /* * This tool has been originally created by Christian Peters * * modified by Karl Koch BNetzA 412-10 fon: +49 (0) 681 9330 515 email: karl.koch@bnetza.de; karl.koch@ties.itu.int */ import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Vector; import org.seamcat.mathematics.Mathematics; import org.seamcat.model.plugin.*; /** * * @author Karl Koch (adhoc@heiseka.de) * @version This plugin modifies the antenna gain of the VLR depending on the simulated angle
* within the range of the angle of the first side lobe by choosing randomly a value between the gain at the first side lobe
* and the gain given by the simulated angle.

* For distances larger than the distance corresponding to the max antenna gain and outside the range of the first side lobe no correction is considered.

* In case the simulated distance is smaller than the min distance, the iRSS (unwanted and blocking) are set to -200 dBm simulating "no interfering transmitter". * */ public class SE7_TRR_AntennaGainCorrection implements PostProcessingPlugin, ConsistencyCheck { private PluginDistribution defaultDistribution; private boolean checkPropagationModel; public Vector tacticalRelayDataCollection; private TacticalRelayData singleDataSet; private double angleFirstSideLobe = 17.0; // dBi private double distanceToBS = 0.25; // km private double distanceAtMaxGain; private double gainFirstSideLobe; private double maxGain; private Boolean shouldBeSaved = false; private String pathToSave = "E:/position"; private String filename = "exportAngles"; private Boolean distanceToBSasLimit; private ProgressBarStoreFileSE7 progressBar; public void init(ParameterFactory param) { defaultDistribution = param.createDistribution(PluginDistribution.DistributionType.DiscreteUniform, 0, 360); } public void cleanUp() { // TODO Auto-generated method stub } public String getDescription() { return "This plug-in is to suit antenna gain to distance within a given beam width"; } /** * This method is called after each snapshot */ public void process(ScenarioInfo scenario) { if (scenario.getCurrentEventNumber() < 2) { initPlugin(scenario); } else if (scenario.getCurrentEventNumber() == scenario.getTotalNumberOfEvents()) { updateIRSS(scenario); if (shouldBeSaved) { progressBar = new ProgressBarStoreFileSE7(filename); progressBar.init(); createXMLoutput(); progressBar.stop(); } // scenario.requestSimulationStop(); } else { collectData(scenario); considerAntennaGain(scenario); } } /** * creates the XML file and saves it to the defined location */ private void createXMLoutput() { String pathToSaveFile = pathToSave + "\\" + filename + ".xml"; try { BufferedWriter out = new BufferedWriter(new FileWriter(pathToSaveFile)); String xmlDeclaration = ""; String xmlRoot = "result"; String xmlElement = "snapshot"; out.write(xmlDeclaration); out.newLine(); out.write("<" + xmlRoot + ">"); out.newLine(); String element = ""; for (int i = 0; i < tacticalRelayDataCollection.size(); i++) { element = "<" + xmlElement; element += " id = \"" + tacticalRelayDataCollection.get(i).id; element += " \" linkID = \"" + tacticalRelayDataCollection.get(i).linkID; element += " \" antennaGain = \"" + tacticalRelayDataCollection.get(i).antennaGain; element += " \" antennaGainCorrected = \"" + tacticalRelayDataCollection.get(i).antennaGainCorrected; element += " \" antennaDirection = \"" + tacticalRelayDataCollection.get(i).antennaDirection; element += " \" angleSimulated = \"" + tacticalRelayDataCollection.get(i).directionSimulated; element += " \" distanceToBS = \"" + tacticalRelayDataCollection.get(i).distanceToBS + "\">"; element += ""; out.write(element); out.newLine(); } out.write(""); out.flush(); out.close(); } catch (IOException e) { pathToSave = "C:"; // valid path before re-starting this method createXMLoutput(); } } /** * in case more than one interfering system is simulated * @param scenario */ private void updateIRSS(ScenarioInfo scenario) { int numberOfSimulatedSystems = getNumberOfSimulatedSystems(); double[] sumUnw = new double[numberOfSimulatedSystems + 1]; // considers one more to ease the counting of the loops double[] sumBlock = new double[numberOfSimulatedSystems + 1]; if (numberOfSimulatedSystems > 1 || scenario.getNumberOfInterferingLinks() > 1) { for (int i = 0; i < tacticalRelayDataCollection.size(); i++) { for (int j = 1; j <= numberOfSimulatedSystems; j++) { if (tacticalRelayDataCollection.get(i).linkID == j) { sumUnw[j] += Math.pow(10, tacticalRelayDataCollection.get(i).iRSSunw / 10); sumBlock[j] += Math.pow(10, tacticalRelayDataCollection.get(i).iRSSblock / 10); } } } double iRSSchangedUnw = 0; double iRSSchangedBlock = 0; for (int k = 1; k <= numberOfSimulatedSystems; k++) { iRSSchangedUnw = 10 * Math.log10(sumUnw[k]); scenario.getProcessingResults().setIRSSUnwanted(k, iRSSchangedUnw); iRSSchangedBlock = 10 * Math.log10(sumBlock[k]); scenario.getProcessingResults().setIRSSBlocking(k, iRSSchangedBlock); } } } /** * * @return numberOfSystems */ private int getNumberOfSimulatedSystems() { int numberOfSystems = 1; for (int i = 0; i < tacticalRelayDataCollection.size(); i++) { numberOfSystems = Math.max(numberOfSystems, tacticalRelayDataCollection.get(i).linkID); } return numberOfSystems; } /** * this method considers the changed antenna gain within the range of +/- first side lobe and increases the iRSS * vectors accordingly * * @param scenario */ private void considerAntennaGain(ScenarioInfo scenario) { double gainCorrection = 0; for (int i = 0; i < tacticalRelayDataCollection.size(); i++) { if (tacticalRelayDataCollection.get(i).distanceToBS < distanceAtMaxGain) { if (tacticalRelayDataCollection.get(i).antennaDirection <= angleFirstSideLobe) { gainCorrection = getGainCorrection(tacticalRelayDataCollection.get(i), scenario); double corrected = tacticalRelayDataCollection.get(i).antennaGain + gainCorrection; corrected = Math.min(tacticalRelayDataCollection.get(i).antennaGain, corrected); tacticalRelayDataCollection.get(i).antennaGainCorrected = corrected; tacticalRelayDataCollection.get(i).iRSSunw += gainCorrection; tacticalRelayDataCollection.get(i).iRSSblock += gainCorrection; } } } } /** * the method getGainCorrection generates a uniformly distributed random value
within the range of the gain of the first side lobe and the actual antenna gain
* it is assumed that the operator of FS avoids the main beam direction towards the interfering BS, but the * probability of not being aware of the BS increases with the distance
* The relation between distance and the amount of the correction might become an issue of a modified version of this plugin. * * @param tacticalRelayData * @param scenario * @return */ private double getGainCorrection(TacticalRelayData tacticalRelayData, ScenarioInfo scenario) { double rgainCorrection = Math.random() * (gainFirstSideLobe - tacticalRelayData.antennaGain); return rgainCorrection; } /** * initializes the plugin by assigning the global variables * * @param scenario */ private void initPlugin(ScenarioInfo scenario) { tacticalRelayDataCollection = new Vector(); gainFirstSideLobe = getAntennaGainFistSideLobe(scenario, angleFirstSideLobe); // 0 for elevation maxGain = scenario.getVictimLink().getReceiver().getAntennaGain(); double lossAtDistanceToBS = 32.4 + 20 * Math.log10(scenario.getVictimLink().getFrequency()) + 20 * Math.log10(distanceToBS); distanceAtMaxGain = Math.pow(10, (lossAtDistanceToBS + (-gainFirstSideLobe) - 32.4 - 20 * Math.log10(scenario .getVictimLink().getFrequency())) / 20); System.out.println(distanceAtMaxGain); } /** * * @param scenario * @param angleFirstSideLobe * @return antennaGain at first side lobe */ private double getAntennaGainFistSideLobe(ScenarioInfo scenario, double angleFirstSideLobe) { Function2D antennaPattern = scenario.getVictimLink().getReceiver().getSphericalAntennaPattern(); double antennaGain = 0; try { double sphericalAngle = Mathematics.acosD(Mathematics.cosD(0) * Mathematics.cosD(angleFirstSideLobe)); antennaGain = antennaPattern.evaluate(sphericalAngle); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return antennaGain; } /** * collects the data needed for the gain correction and used for the file export * * @param scenario */ private void collectData(ScenarioInfo scenario) { for (InterferingLink ilk : scenario.getInterferingLinks()) { singleDataSet = new TacticalRelayData(); singleDataSet.id = ilk.getLinkIndex(); singleDataSet.linkID = ilk.getOrigLinkIndex(); singleDataSet.distanceToBS = scenario.getVictimLink().getReceiver().getDistanceTo(ilk.getTransmitter()); singleDataSet.iRSSunw = ilk.getIRSSUnwanted(); singleDataSet.iRSSblock = ilk.getIRSSBlocking(); singleDataSet.antennaElevation = scenario.getVictimLink().getReceiver().getAntennaElevation(); double angleSimulated = getAntennaDirection(scenario, ilk); singleDataSet.directionSimulated = angleSimulated; singleDataSet.antennaDirection = angleSimulated; if (angleSimulated > 180) singleDataSet.antennaDirection = 360 - angleSimulated; // as the pattern are defined in the range 0 ... 180 singleDataSet.antennaGain = getAntennaGain(scenario, singleDataSet, ilk); if (singleDataSet.distanceToBS < distanceToBS) { singleDataSet.iRSSunw = -200 ; // considers a interfering power of -200 dBm simulating 'no interferer' singleDataSet.iRSSblock = -200; } singleDataSet.antennaGainCorrected = singleDataSet.antennaGain; tacticalRelayDataCollection.add(singleDataSet); } } /** * * @param scenario * @param singleDataSet * @param ilk * @return antennaGain */ private double getAntennaGain(ScenarioInfo scenario, TacticalRelayData singleDataSet, InterferingLink ilk) { double antennaGain = 0; double deltaAntennaHeights = ilk.getTransmitter().getAntennaHeight() - scenario.getVictimLink().getReceiver().getAntennaHeight() ; double elevationVLK_ILT = Mathematics.atan2D(singleDataSet.distanceToBS, deltaAntennaHeights/1000); double antennaElevation = elevationVLK_ILT + singleDataSet.antennaElevation; // effective vertical angle Function2D antennaPattern = scenario.getVictimLink().getReceiver().getSphericalAntennaPattern(); try { double sphericalAngle = Mathematics.acosD(Mathematics.cosD(antennaElevation) * Mathematics.cosD(singleDataSet.antennaDirection)); antennaGain = antennaPattern.evaluate(sphericalAngle); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return antennaGain; } /** * calculates the antenna direction of the VLR depending on the positions of VLR, VLT and ILT * * @param scenario * @param ilk * @return beam direction towards the ILT */ private double getAntennaDirection(ScenarioInfo scenario, InterferingLink ilk) { double vPosX = scenario.getVictimLink().getReceiver().getPositionX(); double vPosY = scenario.getVictimLink().getReceiver().getPositionY(); double iPosX = ilk.getTransmitter().getPositionX(); double iPosY = ilk.getTransmitter().getPositionY(); double ivX = iPosX - vPosX; double ivY = iPosY - vPosY; double angle = Mathematics.atan2D(ivX, ivY); if (angle < 0) angle += 360; double vtPosX = scenario.getVictimLink().getTransmitter().getPositionX(); double vtPosY = scenario.getVictimLink().getTransmitter().getPositionY(); double vtDeltaX = vtPosX - vPosX; double vtDeltaY = vtPosY - vPosY; double vtAngle = Mathematics.atan2D(vtDeltaX, vtDeltaY); double antennaDirection = angle - vtAngle; return antennaDirection; } public int getNumberOfParameters() { return 6; } public ParameterType getParameterType(int id) { switch (id) { case 1: { return ParameterType.Double; } case 2: { return ParameterType.Boolean; } case 3: { return ParameterType.Double; } case 4: { return ParameterType.Boolean; } case 5: { return ParameterType.String; } case 6: { return ParameterType.String; } default: { throw new IllegalArgumentException("illegal parameter id"); } } } public void setParameterValue(int id, Object value) { try { switch (id) { case 1: { distanceToBS = (Double) value; break; } case 2: { distanceToBSasLimit = (Boolean) value; break; } case 3: { angleFirstSideLobe = (Double) value; break; } case 4: { shouldBeSaved = (Boolean) value; break; } case 5: { pathToSave = (String) value; break; } case 6: { filename = (String) value; break; } default: { throw new IllegalArgumentException("illegal parameter id"); } } } catch (Exception e) { } } public Object getParameterValue(int id) { switch (id) { case 1: { return distanceToBS; } case 2: { return distanceToBSasLimit; } case 3: { return angleFirstSideLobe; } case 4: { return shouldBeSaved; } case 5: { return pathToSave; } case 6: { return filename; } default: { throw new IllegalArgumentException("illegal parameter id"); } } } public String getParameterName(int id) { switch (id) { case 1: { return "min distance to MFCN BS [km]"; } case 2: { return "min distance to be used as lowest distance"; } case 3: { return "angle of first side lobe [degrees]"; } case 4: { return "should collected data be exported to XML"; } case 5: { return "path to save "; } case 6: { return "file name (without extension)"; } default: { throw new IllegalArgumentException("illegal parameter id"); } } } /* * check consistency of the workspace */ public boolean check(ScenarioInfo info) { checkPropagationModel = true; String warning = ""; if (pathToSave == null || pathToSave.length() == 0) { pathToSave = "C:/"; warning += "

path to save has been set to its default \"C:/ \"
"; checkPropagationModel = false; } if (filename == null || filename.length() == 0 || filename.equals(".xml")) { filename = "testOutput.xml"; warning += "filename has been set to its default \"testOutput \"
"; checkPropagationModel = false; } warning += ""; if (checkPropagationModel == false) { info.addConsistencyWarning(warning); return false; } else { return true; } } @Override public Vector getAllowedParameterValues(int index) { // TODO Auto-generated method stub return null; } } class TacticalRelayData { int id, linkID; double distanceToBS, antennaGain, antennaGainCorrected; double iRSSunw, iRSSblock; double antennaDirection, antennaElevation, directionSimulated; }