]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - support/sdk/java/net/tinyos/sim/LinkLayerModel.java
Merge devel code into the trunk.
[tinyos-2.x.git] / support / sdk / java / net / tinyos / sim / LinkLayerModel.java
diff --git a/support/sdk/java/net/tinyos/sim/LinkLayerModel.java b/support/sdk/java/net/tinyos/sim/LinkLayerModel.java
new file mode 100644 (file)
index 0000000..edf875f
--- /dev/null
@@ -0,0 +1,751 @@
+/****************************************************************************
+ *       
+ * "Copyright (c) 2006 The University of Southern California"  
+ * All rights reserved.   
+ *       
+ * Permission to use, copy, modify, and distribute all components of 
+ * this software and its documentation for any purpose, without fee, 
+ * and without written agreement is hereby granted, 
+ * provided that the above copyright notice, the following two paragraphs 
+ * and the author names appear in all copies of this software.  
+ *     
+ * NO REPRESENTATIONS ARE MADE ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY  
+ * PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.  
+ *     
+ * Neither the software developers, the Autonomous Network Research Group  
+ * (ANRG), or USC, shall be liable for any damages suffered from using this  
+ * software.   
+ *     
+ * Author:  Marco Zuniga, Avinash Sridharan
+ * Director: Prof. Bhaskar Krishnamachari
+ * Autonomous Networks Reseach Group, University of Southern California
+ * http://ceng.usc.edu/~anrg
+ * Contact: marcozun@usc.edu
+ *
+ * Date last modified: 2004/07/02 marcozun
+ * Date last modified: 2006/02/05 asridhar
+ *       
+ *     
+ * Description: This file contains the code that generates the
+ * gains for all links in the network and noise floor values for
+ * all nodes.
+ *     
+ ****************************************************************************/
+
+package net.tinyos.sim;
+
+import java.io.*;
+import java.util.*;
+import java.text.DecimalFormat;
+
+/**
+ * Stores channel, radio and topology parameters provided by user
+ * through the configuration file.
+ */
+
+class InputVariables {
+
+  // Channel parameters
+  double n;  // path loss exponent
+  double sigma; // standard deviation shadowing variance
+  double  d0;  // reference distance
+  double pld0; // power decay for reference distance d0
+  // Radio parameters
+  double pn;  // radio noise floor
+  double wgn; // white gaussian noise 
+  // Covariance Matrix for hardware variance
+  double  s11;
+  double  s12;
+  double  s21;
+  double  s22;
+  // Topology parameters
+  int  numNodes; // number of nodes
+  int  top;  // topology option
+  double grid;  // grid unit
+  double Xterr;  // X dimension of Terrain
+  double Yterr;  // Y dimension of Terrain
+  String topFile; // file name with nodes' coordinates (user-defined)
+  // data directly derived from configuration file
+  double area;  // area of the terrain
+
+
+  InputVariables() { // Constructor, loading default values
+    n  = 3;
+    sigma = 3;
+    pld0 = 55;
+    d0  = 1;
+    pn  = -105;
+    wgn  = 4;
+    s11  = 3.7;
+    s12  = -3.3;
+    s21  = -3.3;
+    s22  = 6.0;
+    numNodes= 0;
+    top  = 0;
+    Xterr = 0;
+    Yterr = 0;
+    topFile = "";
+    area  = 0;
+  }
+
+}
+
+/**
+ * Stores nodes' coordinates, link gains and noise floor values for a given topology 
+ */
+
+class OutputVariables {
+
+  double[] nodePosX;  // X coordinate
+  double[] nodePosY;  // Y coordinate
+  double[] outputpowervar; // output power
+  double[] noisefloor;  // noise floor
+  double[][]  linkGain;  // link gain
+
+  OutputVariables(int numNodes) { // Constructor
+
+    nodePosX = new double[numNodes];
+    nodePosY = new double[numNodes];
+    outputpowervar = new double[numNodes];
+    noisefloor  = new double[numNodes];
+    linkGain = new double[numNodes][numNodes];
+  }
+
+}
+
+
+/**
+ * Simulates gains for all links of a specific topology, and noise
+ * floor values for all nodes.  <p>The link gain between nodes A and B
+ * is defined as the output power of A minus the pathloss between A
+ * and B.  The user specifies the desired channel, radio and topology
+ * parameters through a configuration file.  The configuration file is
+ * provided as a command line argument: <tt>$ java LinkLayerModel
+ * configurationFileName</tt>, and the link gains and noise floor
+ * values are provided on a file called <tt>linkgain.out</tt>.
+ */
+
+public class LinkLayerModel  {
+
+  public static void main (String args[]) {
+    if (args.length != 1) {
+      usage();
+      return;
+    }
+    // variable that contains input parameters
+    InputVariables inVar = new InputVariables();
+    // parse configuration file and store parameters in inVar
+    readFile  ( args[0], inVar );
+    // if user defined topology (TOPOLOGY = 4), obtain number of nodes
+    if (inVar.top == 4) {
+      obtainNumNodes (inVar.topFile, inVar);
+    }
+    // variable that contains output data
+    OutputVariables outVar = new OutputVariables( inVar.numNodes ); 
+    // create topology
+    System.out.print("Topology ...\t\t\t");
+    obtainTopology ( inVar, outVar );
+    System.out.println("done");
+    // obtain ouput power and noise floor for all nodes
+    System.out.print("Radio Pt and Pn ...\t\t");
+    obtainRadioPtPn ( inVar, outVar );
+    System.out.println("done");
+    // obtain link gains 
+    System.out.print("Links Gain .....\t\t");
+    obtainLinkGain ( inVar, outVar);
+    System.out.println("done");
+    // print linkgain.out (link gains and noise floor) and topology.out (x/y coordinates)
+    System.out.print("Printing Output File ...\t");
+    printFile  ( inVar, outVar);
+    System.out.println("done");
+  }
+
+
+  /**
+   * Parses configuration file provided by user and stores specified
+   * parameters
+   *
+   * @param inputFile configuration file containing channel, radio and
+   * deployment parameters
+   * @param  var   class that stores input parameters from configuration file
+   * @return    true if file parsing was performed without errors
+   */
+
+  protected static boolean readFile (String inputFile, InputVariables var )
+  {
+
+    String thisLine;
+    StringTokenizer st;
+
+    // open configuration file
+    try {
+      FileInputStream fin =  new FileInputStream(inputFile);
+      try {
+        BufferedReader myInput = new BufferedReader(new InputStreamReader(fin));
+        try {
+          // parse the file
+          while ((thisLine = myInput.readLine()) != null) {
+
+            if ( !thisLine.equals("") && !thisLine.startsWith("%") ) {
+              st = new StringTokenizer(thisLine, " =;\t");
+              String key = st.nextToken();
+              String value = st.nextToken();
+
+              if ( key.equals("PATH_LOSS_EXPONENT")) {
+                var.n = Double.valueOf(value).doubleValue();
+                if (var.n < 0) {
+                  System.out.println("Error: value of PATH_LOSS_EXPONENT must be positive");
+                  System.exit(1);
+                }
+              }
+              else if ( key.equals("SHADOWING_STANDARD_DEVIATION")) {
+                var.sigma = Double.valueOf(value).doubleValue();
+                if (var.sigma < 0) {
+                  System.out.println("Error: value of SHADOWING_STANDARD_DEVIATION must be positive");
+                  System.exit(1);
+                }
+              }
+              else if ( key.equals("PL_D0")) {
+                var.pld0 = Double.valueOf(value).doubleValue();
+                if (var.pld0 < 0) {
+                  System.out.println("Error: value of PL_D0 must be positive");
+                  System.exit(1);
+                }
+              }
+              else if ( key.equals("D0")) {
+                var.d0 = Double.valueOf(value).doubleValue();
+                if (var.d0 <= 0) {
+                  System.out.println("Error: value of D0 must be greater than zero");
+                  System.exit(1);
+                }
+              }
+              else if ( key.equals("NOISE_FLOOR")) {
+                var.pn = Double.valueOf(value).doubleValue();
+              }
+              else if ( key.equals("WHITE_GAUSSIAN_NOISE")) {
+                var.wgn = Double.valueOf(value).doubleValue();
+                if (var.wgn < 0) {
+                  System.out.println("Error: value of WHITE_GAUSSIAN_NOISE must be greater equal than 0");
+                  System.exit(1);
+                }
+              }
+              else if ( key.equals("S11")) {
+                var.s11 = Double.valueOf(value).doubleValue();
+                if (var.s11 < 0) {
+                  System.out.println("Error: value of S11 must be greater equal than 0");
+                  System.exit(1);
+                }
+              }
+              else if ( key.equals("S12")) {
+                var.s12 = Double.valueOf(value).doubleValue();
+              }
+              else if ( key.equals("S21")) {
+                var.s21 = Double.valueOf(value).doubleValue();
+              }
+              else if ( key.equals("S22")) {
+                var.s22 = Double.valueOf(value).doubleValue();
+                if (var.s22 < 0) {
+                  System.out.println("Error: value of S22 must be greater equal than 0");
+                  System.exit(1);
+                }
+              }
+              else if ( key.equals("NUMBER_OF_NODES")) {
+                var.numNodes = Integer.parseInt(value);
+                if (var.numNodes <= 0) {
+                  System.out.println("Error: value of NUMBER_OF_NODES must be positive");
+                  System.exit(1);
+                }
+              } 
+              else if ( key.equals("TOPOLOGY")) {
+                var.top = Integer.parseInt(value);
+                if ( (var.top < 1) | (var.top > 4) ) {
+                  System.out.println("Error: value of TOPOLOGY must be between 1 and 4");
+                  System.exit(1);
+                }
+              }
+              else if ( key.equals("GRID_UNIT")) {
+                var.grid = Double.valueOf(value).doubleValue();
+              }
+              else if ( key.equals("TOPOLOGY_FILE")) {
+                var.topFile = value;
+              }
+              else if ( key.equals("TERRAIN_DIMENSIONS_X")) {
+                var.Xterr = Double.valueOf(value).doubleValue();
+                if (var.Xterr < 0) {
+                  System.out.println("Error: value of TERRAIN_DIMENSIONS_X must be positive");
+                  System.exit(1);
+                }
+              } 
+              else if ( key.equals("TERRAIN_DIMENSIONS_Y")) {
+                var.Yterr = Double.valueOf(value).doubleValue();
+                if (var.Yterr < 0) {
+                  System.out.println("Error: value of TERRAIN_DIMENSIONS_Y must be positive");
+                  System.exit(1);
+                }
+                var.area = var.Xterr * var.Yterr;
+              } 
+              else {
+                System.out.println("Error: undefined parameter " + key + ", please review your configuration file");
+                System.exit(1);
+              } 
+            }
+          } // end while loop
+        }
+        catch (Exception e) {
+          System.out.println("Error1: " + e);
+          System.exit(1);
+        }
+
+      } // end try
+      catch (Exception e) {
+        System.out.println("Error2: " + e);
+        System.exit(1);
+      }
+
+    } // end try
+    catch (Exception e) {
+      System.out.println("Error Failed to Open file " + inputFile + e);
+      System.exit(1);
+    }
+
+    return true;
+
+  }
+
+  /**
+   * Obtain X and Y coordinates for all nodes. Different type of topologies are available 
+   * (grid, uniform, random, user-defined)
+   * 
+   * @param inVar class that contains input parameters from configuration file
+   * @param outVar class that stores x/y coordinates
+   * @return true if X/Y coordinates are obtained without errors
+   */
+
+  protected static boolean obtainTopology( InputVariables  inVar, 
+                                           OutputVariables outVar )
+  {
+
+    Random rand = new Random();
+    int i, j;
+    int sqrtNumNodes, nodesX;
+    double cellArea, cellLength;
+    double Xdist, Ydist, dist;
+    boolean wrongPlacement;
+
+    if (inVar.numNodes <= 0) {
+      System.out.println("\nError: value of NUMBER_OF_NODES must be positive");
+      System.exit(1);
+    }
+
+    switch (inVar.top) {
+    case 1: // GRID
+      if (inVar.grid < inVar.d0) {
+        System.out.println("\nError: value of GRID_UNIT must be equal or greater than D0");
+        System.exit(1);
+      }
+      sqrtNumNodes = (int) Math.sqrt(inVar.numNodes);
+      if ( sqrtNumNodes != Math.sqrt(inVar.numNodes) ) {
+        System.out.println ("\nError: on GRID topology, NUMBER_OF_NODES should be the square of a natural number");
+        System.exit(1);
+      }
+      for (i = 0; i < inVar.numNodes; i = i+1) {
+        outVar.nodePosX[i] = (i%sqrtNumNodes) * inVar.grid;
+        outVar.nodePosY[i] = (i/sqrtNumNodes) * inVar.grid;
+      }
+      break;
+    case 2: // UNIFORM
+      sqrtNumNodes = (int) Math.sqrt(inVar.numNodes);
+      if ( sqrtNumNodes != Math.sqrt(inVar.numNodes) ) {
+        System.out.println ("\nError: on UNIFORM topology, NUMBER_OF_NODES should be the square of a natural number");
+        System.exit(1);
+      }
+      if ( (inVar.Xterr <= 0) | (inVar.Yterr <= 0) ) {
+        System.out.println("\nError: values of TERRAIN_DIMENSIONS must be positive");
+        System.exit(1);
+      }
+      if ( inVar.Xterr != inVar.Yterr ) {
+        System.out.println("\nError: values of TERRAIN_DIMENSIONS_X and TERRAIN_DIMENSIONS_Y must be equal");
+        System.exit(1);
+      }
+      cellLength = Math.sqrt ( inVar.area / inVar.numNodes );
+      nodesX = sqrtNumNodes; 
+      if ( cellLength < (inVar.d0*1.4) ) {
+        System.out.println ("\nError: on UNIFORM topology, density is too high, increase physical terrain");
+        System.exit(1);
+      }
+      for (i = 0; i < inVar.numNodes; i = i+1) {
+        outVar.nodePosX[i] = (i%nodesX) * cellLength + rand.nextDouble()*cellLength;
+        outVar.nodePosY[i] = (i/nodesX) * cellLength + rand.nextDouble()*cellLength;
+        wrongPlacement = true;
+        while ( wrongPlacement ) {
+          for (j = 0; j < i; j = j+1) {
+            Xdist = outVar.nodePosX[i] - outVar.nodePosX[j];
+            Ydist = outVar.nodePosY[i] - outVar.nodePosY[j];
+            // distance between a given pair of nodes
+            dist = Math.pow((Xdist*Xdist + Ydist*Ydist), 0.5);
+            if (dist < inVar.d0) {
+              outVar.nodePosX[i] = (i%nodesX) * cellLength + rand.nextDouble()*cellLength;
+              outVar.nodePosY[i] = (i/nodesX) * cellLength + rand.nextDouble()*cellLength;
+              wrongPlacement = true;
+              break;
+            }
+          }
+          if ( j == i ) {
+            wrongPlacement = false;
+          }
+        }
+      }
+      break;
+    case 3: // RANDOM
+      if ( (inVar.Xterr <= 0) | (inVar.Yterr <= 0) ) {
+        System.out.println("\nError: values of TERRAIN_DIMENSIONS must be positive");
+        System.exit(1);
+      }
+      cellLength = Math.sqrt ( inVar.area / inVar.numNodes );   
+      if ( cellLength < (inVar.d0*1.4) ) {
+        System.out.println ("\nError: on RANDOM topology, density is too high, increase physical terrain");
+        System.exit(1);
+      }
+      for (i = 0; i < inVar.numNodes; i = i+1) {
+        outVar.nodePosX[i] = rand.nextDouble() * inVar.Xterr;
+        outVar.nodePosY[i] = rand.nextDouble() * inVar.Yterr;
+        wrongPlacement = true;
+        while ( wrongPlacement ) {
+          for (j = 0; j < i; j = j+1) {
+            Xdist = outVar.nodePosX[i] - outVar.nodePosX[j];
+            Ydist = outVar.nodePosY[i] - outVar.nodePosY[j];
+            // distance between a given pair of nodes
+            dist = Math.pow((Xdist*Xdist + Ydist*Ydist), 0.5);
+            if (dist < inVar.d0) {
+              outVar.nodePosX[i] = rand.nextDouble() * inVar.Xterr;
+              outVar.nodePosY[i] = rand.nextDouble() * inVar.Yterr;
+              wrongPlacement = true;
+              break;
+            }
+          }
+          if ( j == i ) {
+            wrongPlacement = false;
+          }
+        }
+      }
+      break;
+    case 4: // FILE (user-defined topology)
+      readTopologyFile(inVar.topFile, outVar);
+      correctTopology (inVar, outVar);
+      break;
+    default:
+      System.out.println("\nError: topology is not correct, please check TOPOLOGY in the configuration file");
+      System.exit(1);
+    }
+
+    return true;
+  }
+
+
+  /**
+   * Checks that user-defined topology does not have inter-node distances less than D0 meter, 
+   * where D0 is the reference distance in the channel model (specified in configuration file)
+   *
+   * @param inVar class that stores input parameters from configuration file
+   * @param outVar class that stores link gains, noise floors and x/y coordinates
+   * @return true if x/y coordinates provided by user satisfy the condition that no internode distance is lesss than D0
+   */
+
+  protected static boolean correctTopology ( InputVariables  inVar, 
+                                             OutputVariables outVar )
+  {
+    Random rand = new Random();
+    int i, j;
+    double Xdist, Ydist, dist, avgDecay;
+
+    for (i = 0; i < inVar.numNodes; i = i+1) {
+      for (j = i+1; j < inVar.numNodes; j = j+1 ) {
+        Xdist = outVar.nodePosX[i] - outVar.nodePosX[j];
+        Ydist = outVar.nodePosY[i] - outVar.nodePosY[j];
+        // distance between a given pair of nodes
+        dist = Math.pow((Xdist*Xdist + Ydist*Ydist), 0.5);
+        if (dist < inVar.d0) {
+          System.out.println("\nError: file " + inVar.topFile + " contains inter-node distances less than one.");
+          System.exit(1);
+        }
+      }
+    }
+    return true;
+  }
+
+
+  /**
+   * Obtains output power and noise floor for all nodes in the network
+   *
+   * @param inVar class that contains radio parameters
+   * @param outVar class that stores output powers and noise floors
+   * @return true if all output powers and noise floors were obtained correctly
+   */
+
+  protected static boolean obtainRadioPtPn ( InputVariables  inVar, 
+                                             OutputVariables outVar )
+  {
+    Random rand = new Random();
+    int i, j;
+    double t11, t12, t21, t22;
+    double rn1, rn2;
+
+    t11 = 0;
+    t12 = 0;
+    t21 = 0;
+    t22 = 0;
+
+    if ( (inVar.s11 == 0) && (inVar.s22 == 0) ) { // symmetric links do nothing
+    }
+    else if ( (inVar.s11 == 0) && (inVar.s22 != 0) ) { // both S11 and S22 must be 0 for symmetric links
+      System.out.println("\nError: symmetric links require both, S11 and S22 to be 0, not only S11.");
+      System.exit(1);
+    }
+    else {
+      if ( (inVar.s12 != inVar.s21) ) { // check that S is symmetric
+        System.out.println("\nError: S12 and S21 must have the same value.");
+        System.exit(1);
+      }
+      if ( Math.abs(inVar.s12) > Math.sqrt(inVar.s11*inVar.s22) ) { // check that correlation is within [-1,1]
+        System.out.println("\nError: S12 (and S21) must be less than sqrt(S11xS22).");
+        System.exit(1);
+      }
+      t11 = Math.sqrt(inVar.s11);
+      t12 = inVar.s12/Math.sqrt(inVar.s11);
+      t21 = 0;
+      t22 = Math.sqrt( (inVar.s11*inVar.s22 - Math.pow( inVar.s12, 2)) / inVar.s11 );
+    }
+
+    for (i = 0; i < inVar.numNodes; i = i+1) {
+      rn1 = rand.nextGaussian();
+      rn2 = rand.nextGaussian();
+      outVar.noisefloor[i]  = inVar.pn + t11 * rn1;
+      outVar.outputpowervar[i] = t12 * rn1 + t22 * rn2;
+    }
+    return true;
+  }
+
+
+  /**
+   * Obtains gain for all links in the network. The link gain between nodes A and B 
+   * is defined as the output power of A minus the pathloss between A and B.
+   *
+   * @param inVar class that contains channel parameters from configuration file
+   * @param outVar class that stores link gains
+   * @return true if all link gains were obtained correctly
+   */
+
+  protected static boolean obtainLinkGain ( InputVariables  inVar, 
+                                            OutputVariables outVar )
+  {
+    Random rand = new Random();
+    int i, j;
+    double Xdist, Ydist, dist, pathloss;
+
+    for (i = 0; i < inVar.numNodes; i = i+1) {
+      for (j = i+1; j < inVar.numNodes; j = j+1 ) {
+        Xdist = outVar.nodePosX[i] - outVar.nodePosX[j];
+        Ydist = outVar.nodePosY[i] - outVar.nodePosY[j];
+        // distance between a given pair of nodes
+        dist = Math.pow((Xdist*Xdist + Ydist*Ydist), 0.5);
+        // mean decay dependent on distance
+        pathloss = - inVar.pld0 - 10*inVar.n*(Math.log(dist/inVar.d0)/Math.log(10.0)) + ( rand.nextGaussian()*inVar.sigma );
+        // assymetric links are given by running two different
+        // R.V.s for each unidirectional link (output power variance).
+        outVar.linkGain[i][j] = outVar.outputpowervar[i] + pathloss;
+        outVar.linkGain[j][i] = outVar.outputpowervar[j] + pathloss;
+  
+      }
+    }
+    return true;
+
+  }
+
+
+  /**
+   * Provides link gain and noise floor in file linkgain.out, and the
+   * X/Y coordinates in file topology.out.
+   *
+   * @param inVar class that contains input parameters from configuration file
+   * @param outVar class that stores link gains, noise floors and x/y coordinates
+   * @return true if files linkgain.out and topology.out were printed correctly
+   */
+
+  protected static boolean printFile( InputVariables  inVar, 
+                                      OutputVariables outVar )
+  {
+
+    int i, j;
+
+    DecimalFormat posFormat = new DecimalFormat("##0.00");
+
+    /*
+     * Output file for xy coordinates.
+     */
+
+    try{
+      FileOutputStream fout =  new FileOutputStream("topology.out");
+      try {
+        PrintStream myOutput = new PrintStream(fout);
+        for (i = 0; i < inVar.numNodes; i = i+1) {
+          myOutput.print( i + "\t" + posFormat.format(outVar.nodePosX[i]) + "\t"+ posFormat.format(outVar.nodePosY[i]) + "\n");
+        }
+      }
+      catch (Exception e) {
+        System.out.println("\nError : Failed to open a print stream to the linkgain file" + e);
+      }
+
+    }
+    catch (Exception e) {
+      System.out.println("\nError : Failed to open the link gain file linkgains.out:" + e);
+    }
+
+   
+    /*
+     * Output file for link gains.
+     */
+    try{
+      FileOutputStream fout =  new FileOutputStream("linkgain.out");
+      try {
+        PrintStream myOutput = new PrintStream(fout);
+        for (i = 0; i < inVar.numNodes; i = i+1) {
+          for (j = (i+1); j < inVar.numNodes; j = j+1 ) {
+            if ( i != j) {
+              myOutput.print( "gain\t" + i + "\t" + j + "\t" + posFormat.format(outVar.linkGain[i][j]) + "\n");
+              myOutput.print( "gain\t" + j + "\t" + i + "\t" + posFormat.format(outVar.linkGain[j][i]) + "\n");
+            }
+          }
+        }
+        for (i = 0; i < inVar.numNodes; i = i+1) {
+          myOutput.print( "noise\t" + i + "\t" + posFormat.format(outVar.noisefloor[i]) + "\t" + posFormat.format(inVar.wgn) + "\n");
+        }
+      }
+      catch (Exception e) {
+        System.out.println("\nError : Failed to open a print stream to the linkgain file" + e);
+      }
+
+    }
+    catch (Exception e) {
+      System.out.println("\nError : Failed to open the link gain file linkgains.out:" + e);
+    }
+
+    return true;
+  }
+
+  /**
+   * Obtains nodes coordinates for user-defined topology.
+   *  
+   * @param inputTopoFile topology file provided by user
+   * @param outVar class that contains variables to store x/y coordinates of nodes
+   * @return true if x/y coordinates of user-defined topology file were read correctly.
+   */
+
+  protected static boolean readTopologyFile ( String inputTopoFile,
+                                              OutputVariables outVar )
+  {
+
+    String thisLine;
+    StringTokenizer st;
+    int counter = 0;
+
+    try {
+      FileInputStream fin =  new FileInputStream(inputTopoFile);
+      try {
+        BufferedReader myInput = new BufferedReader(new InputStreamReader(fin));
+
+        try {
+
+          while ((thisLine = myInput.readLine()) != null) {
+
+            if ( !thisLine.equals("")  && !thisLine.startsWith("%") && 
+                 !thisLine.startsWith(" ") ) {
+              st = new StringTokenizer(thisLine, " \t");
+              int node = Integer.parseInt(st.nextToken());
+              double x = Double.valueOf(st.nextToken()).doubleValue();
+              double y = Double.valueOf(st.nextToken()).doubleValue();
+              outVar.nodePosX[node] = x;
+              outVar.nodePosY[node] = y;
+              counter++;
+            }
+          }
+        } // end try
+        catch (Exception e) {
+          System.out.println("Error4: " + e);
+          System.exit(1);
+        }
+
+      } // end try
+      catch (Exception e) {
+        System.out.println("Error5: " + e);
+        System.exit(1);
+      }
+
+    } // end try
+    catch (Exception e) {
+      System.out.println("Error: Failed to Open TOPOLOGY_FILE " + inputTopoFile + e);
+      System.exit(1);
+    }
+
+    return true;
+  }
+
+
+  /**
+   * Obtains number of nodes in network when user defines the topology.
+   *
+   * @param inputTopoFile topology file provided by user
+   * @param inVar class that contains variable for number of nodes
+   * @return true if number of nodes from user-defined topology file were obtained correctly
+   */
+
+  protected static boolean obtainNumNodes ( String inputTopoFile,
+                                            InputVariables inVar )
+  {
+
+    String thisLine;
+    StringTokenizer st;
+    int counter = 0;
+
+    try {
+      FileInputStream fin =  new FileInputStream(inputTopoFile);
+      try {
+        BufferedReader myInput = new BufferedReader(new InputStreamReader(fin));
+
+        try {
+
+          while ((thisLine = myInput.readLine()) != null) {
+
+            if ( !thisLine.equals("")  && !thisLine.startsWith("%") && 
+                 !thisLine.startsWith(" ") ) {
+              counter++;
+            }
+          }
+          inVar.numNodes = counter; 
+
+        } // end try
+        catch (Exception e) {
+          System.out.println("Error4: " + e);
+          System.exit(1);
+        }
+
+      } // end try
+      catch (Exception e) {
+        System.out.println("Error5: " + e);
+        System.exit(1);
+      }
+
+    } // end try
+    catch (Exception e) {
+      System.out.println("Error: Failed to Open TOPOLOGY_FILE " + inputTopoFile + e);
+      System.exit(1);
+    }
+
+    return true;
+  }
+
+  private static void usage() {
+    System.err.println("usage: net.tinyos.sim.LinkLayerModel <config file>");
+  }
+}
+
+