Changeset 422 in tmcsimulator for trunk/src/tmcsim/highwaymodel/Highways.java


Ignore:
Timestamp:
06/23/2019 10:27:35 AM (7 years ago)
Author:
jdalbey
Message:

Remove ATMS functionality. Reworked and simplified the Highway model to use only VDS data from PeMS. Updated all unit tests.

Location:
trunk/src/tmcsim/highwaymodel
Files:
1 added
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/tmcsim/highwaymodel/Highways.java

    r398 r422  
    1 package atmsdriver.model; 
     1package tmcsim.highwaymodel; 
    22 
    33import atmsdriver.trafficeventseditor.TrafficLaneEvent; 
    4 import atmsdriver.model.LoopDetector.DOTCOLOR; 
    5 import atmsdriver.model.Station.DIRECTION; 
     4import tmcsim.highwaymodel.Station.DIRECTION; 
    65import java.io.File; 
    76import java.io.FileInputStream; 
    87import java.io.FileNotFoundException; 
    9 import java.io.IOException; 
    10 import java.io.PrintWriter; 
    11 import java.io.StringWriter; 
    12 import java.io.Writer; 
    13 import java.net.Socket; 
    148import java.util.ArrayList; 
    159import java.util.Collections; 
     
    2115import java.util.logging.Level; 
    2216import java.util.logging.Logger; 
    23 import javax.xml.parsers.DocumentBuilder; 
    24 import javax.xml.parsers.DocumentBuilderFactory; 
    25 import javax.xml.transform.OutputKeys; 
    26 import javax.xml.transform.Transformer; 
    27 import javax.xml.transform.TransformerFactory; 
    28 import javax.xml.transform.dom.DOMSource; 
    29 import javax.xml.transform.stream.StreamResult; 
    30 import org.w3c.dom.Document; 
    31 import org.w3c.dom.Element; 
    32 import tmcsim.common.SimulationException; 
    3317 
    3418/** 
    35  * The Highways class aggregates all Highway instances within a geographic 
    36  * region, and all of the FEPLines within an electronic detector network, in the 
    37  * same geographic region. An instance of Highways.java comprises the underlying 
    38  * model for the ATMSDriver application. 
     19 * Highways represents California state highways supervised by CalTrans.  
     20 * The highways have sensors to detect traffic flow.  In the simulation 
     21 * the traffic flow is artificially created and Highways maintains the 
     22 * current levels of traffic flow throughout the network. 
    3923 * 
    40  * Highways uses method writeToFEP() to communicate with the FEP Simulator. It 
    41  * creates a socket client which sends the FEP Simulator a highways status 
    42  * message over the socket. This message is sent in the format required by the 
    43  * FEP Simulator. 
     24 * Highways builds an internal representation of the highway network 
     25 * from VDS data (obtained from PeMS) The current state of the network 
     26 * is output to a json file for use by CPTMS.  
    4427 * 
    45  * 
    46  * @author John A. Torres 
     28 * @author John A. Torres, jdalbey 
    4729 */ 
    4830final public class Highways 
    4931{ 
    50  
    51     final private String FEPHostName; 
    52     final private int FEPPortNum; 
    53      
    54     final private List<FEPLine> lines; 
    5532    final public List<Highway> highways; 
    5633 
    57     public Highways(String highwaysMapFileName, String FEPHostName, int FEPPortNum) 
    58     { 
    59         // load FEP Lines 
    60         lines = loadLines(highwaysMapFileName); 
    61         // build highways data structure 
    62         this.highways = buildHighways(); 
    63  
    64         // write to FEP host and port number 
    65         this.FEPHostName = FEPHostName; 
    66         this.FEPPortNum = FEPPortNum; 
    67     } 
    68  
    69     private ArrayList<Highway> buildHighways() 
    70     { 
     34    public Highways(String highwaysMapFileName) 
     35    { 
     36       // build highways data structure 
     37        this.highways = buildHighwayNetwork(highwaysMapFileName); 
     38    } 
     39     
     40    private ArrayList<Highway> buildHighwayNetwork(String highwaysMapFileName) 
     41    { 
     42        // NOTE: Could this method be streamlined? Is it necessary to have the 
     43        // second data structure? 
    7144        System.out.println("Building highways..."); 
    7245        // The list of highways to return 
     
    7649        Map<Integer, ArrayList<Station>> highwayMap = new HashMap<>(); 
    7750         
    78         // iterate through FEPLines and get data to add to the above map 
    79         for (FEPLine line : lines) 
    80         { 
    81             // grab all stations from the current FEPLine 
    82             ArrayList<Station> lineStations = (ArrayList<Station>) line.stations; 
    83             // iterate through each station in the list of stations 
    84             for (Station station : lineStations) 
    85             { 
     51        // Open the postmile file and scan each line 
     52        File file = new File(highwaysMapFileName); 
     53        try  
     54        { 
     55            Scanner scanner = new Scanner(file); 
     56            while (scanner.hasNext()) 
     57            { 
     58                Station station = loadStation(scanner);  
    8659                Integer hwyNum = station.routeNumber; 
    8760                // if the map does not contain an entry for the highway, create 
     
    10174                } 
    10275            } 
    103         } 
    104          
     76        }catch (FileNotFoundException e) { 
     77            e.printStackTrace(); 
     78        } 
    10579        // get the set of highway numbers 
    10680        Set<Integer> hwyKeys = highwayMap.keySet(); 
     
    229203    } 
    230204     
     205     
    231206    /** 
    232      * Loads all FEPLines from the specified highways map file. 
    233      *  
    234      * @param highwaysMapFileName 
    235      * @return List of FEPLines 
    236      */ 
    237     private ArrayList<FEPLine> loadLines(String highwaysMapFileName) 
    238     { 
    239         ArrayList<FEPLine> lines = new ArrayList<>(); 
    240         try 
    241         { 
    242             Scanner sc = new Scanner(new File(highwaysMapFileName)); 
    243             // first line of file contains number of FEP Lines 
    244             String firstLine = sc.nextLine(); 
    245             Scanner linesc = new Scanner(firstLine); 
    246             int numLines = linesc.nextInt(); 
    247             linesc.close(); 
    248             // FOR each FEP Line 
    249             for (int i = 0; i < numLines; i++) 
    250             { 
    251                 lines.add(loadLine(sc)); 
    252             } 
    253             sc.close(); 
    254  
    255         } catch (FileNotFoundException ex) 
    256         { 
    257             Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex); 
    258         } 
    259         return lines; 
    260     } 
    261      
    262     /** 
    263      * Load all the stations for a single FEP Line from the highways map file. 
    264      *  
    265      * @param sc scanner at the current FEPLine line 
    266      * @return FEPLine 
    267      */ 
    268     private FEPLine loadLine(Scanner sc) 
     207     * Loads a single Station from the postmile coordinates file 
     208     * @param sc scanner at the current station line 
     209     * @return Station 
     210     */ 
     211    private Station loadStation(Scanner sc) 
    269212    { 
    270213        String line = sc.nextLine(); 
    271214        Scanner scline = new Scanner(line); 
    272         // Get the attributes of this FEP Line 
    273         int lineNum = scline.nextInt(); 
    274         int count = scline.nextInt(); 
    275         int numStations = scline.nextInt(); 
     215        scline.useDelimiter(","); 
    276216         
    277         // initialze stations array 
    278         ArrayList<Station> stations = new ArrayList<>(); 
    279         // Read all the stations for thie FEP Line 
    280         for (int i = 0; i < numStations; i++) 
    281         { 
    282             stations.add(loadStation(sc, lineNum)); 
    283         } 
    284  
    285         return new FEPLine(lineNum, stations, count); 
    286     } 
    287      
    288     /** 
    289      * Loads a single Station from the highways map file 
    290      * @param sc scanner at the current station line 
    291      * @param lineNum the FEPLine number for the station 
    292      * @return Station 
    293      */ 
    294     private Station loadStation(Scanner sc, int lineNum) 
    295     { 
    296         String line = sc.nextLine(); 
    297         Scanner scline = new Scanner(line); 
    298          
    299         int ldsID = scline.nextInt(); 
    300         int drop = scline.nextInt(); 
    301         int fwy = scline.nextInt(); 
    302         DIRECTION dir = DIRECTION.toDirection(scline.next()); 
    303         double postmile = scline.nextDouble(); 
    304         int numLoops = scline.nextInt(); 
    305         String location = getStationLoc(line); 
     217        String route  = scline.next(); // FWY DIR POSTMILE 
     218        scline.next();  // skip lat 
     219        scline.next();  // skip long 
     220        String description = scline.next(); // the description of the location 
     221 
     222        Scanner rteScan = new Scanner(route); 
     223        int fwy = rteScan.nextInt(); 
     224        DIRECTION dir = DIRECTION.toDirection(rteScan.next()); 
     225        double postmile = rteScan.nextDouble(); 
     226 
    306227        ArrayList<LoopDetector> loops = new ArrayList<>(); 
    307         for (int i = 0; i < numLoops; i++) 
    308         { 
    309             loops.add(loadLoop(sc)); 
    310         } 
    311  
    312         return new Station(lineNum, ldsID, drop, location, loops, fwy, dir, postmile); 
    313     } 
    314      
    315     /** 
    316      * Loads a single loop from the highways map file 
    317      * 
    318      * @param sc scanner at the current loop line 
    319      * @return LoopDetector 
    320      */ 
    321     private LoopDetector loadLoop(Scanner sc) 
    322     { 
    323         String line = sc.nextLine(); 
    324         Scanner scline = new Scanner(line); 
    325  
    326         int loopID = scline.nextInt(); 
    327         String loopLocID = scline.next(); 
    328         String loopLoc = scline.next(); 
    329         scline.close(); 
    330         return new LoopDetector(loopID, loopLocID, loopLoc); 
    331     } 
    332  
    333     /** 
    334      * Scans the LoopDetector line and grabs the String location from the line. 
    335      *  
    336      * @param line the line containing the location 
    337      * @return A String loop location. 
    338      */ 
    339     private String getLoopLoc(String line) 
    340     { 
    341         Scanner sc = new Scanner(line); 
    342         sc.nextInt(); 
    343  
    344      // GRABS FROM CURRENT TO END OF LINE 
    345         sc.useDelimiter("\\z"); 
    346         String loc = sc.next().trim(); 
    347         sc.close(); 
    348         return loc; 
    349     } 
    350  
    351     /** 
    352      * Scans the Station line and grabs the String location from the line. 
    353      *  
    354      * @param line the line containing the location 
    355      * @return A String station location. 
    356      */ 
    357     private String getStationLoc(String line) 
    358     { 
    359         Scanner scline = new Scanner(line); 
    360         scline.nextInt(); 
    361         scline.nextInt(); 
    362         scline.nextInt(); 
    363         scline.next(); 
    364         scline.nextDouble(); 
    365         scline.nextInt(); 
    366  
    367         // GRABS FROM CURRENT TO END OF LINE 
    368         scline.useDelimiter("\\z"); 
    369         String loc = scline.next().trim(); 
    370         scline.close(); 
    371         return loc; 
    372     } 
    373      
    374     /**  
    375      * Creates a socket client that writes the Highways data to the FEP Simulator. 
    376      *  
    377      * @throws SimulationException  
    378      */ 
    379     public void writeToFEP() throws SimulationException 
    380     { 
    381         try 
    382         { 
    383             // Create the socket to the FEP Simulator 
    384             Socket sock = new Socket(FEPHostName, FEPPortNum); 
    385             PrintWriter out = new PrintWriter(sock.getOutputStream(), true); 
    386              
    387             // Print the number of bytes the highways data message contains 
    388             System.out.println("Highways sending " + this.toCondensedFormat(false).toCharArray().length + 1 + "bytes to FEPSIM."); 
    389             String outMsg = this.toCondensedFormat(false); 
    390             // Write the highways data over the socket 
    391             out.println(outMsg); 
    392              
    393             // close the socket 
    394             sock.close(); 
    395         } catch (java.net.ConnectException ex) 
    396         { 
    397             //Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex); 
    398             System.out.println("writeToFEP() can't connect, no data sent to FEP."); 
    399             throw new SimulationException(SimulationException.BINDING); 
    400         } catch (IOException ex) 
    401         { 
    402             //Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex); 
    403             System.out.println("Highway Model failed writing to FEPSim."); 
    404             throw new SimulationException(SimulationException.BINDING); 
    405         } 
    406     } 
    407      
    408     /** Returns a string of highways data. If MetaDataOnly is true, you get a full 
    409      *  dump of the highways meta data, which does not include dynamic loop values, 
    410      *  and does include the string location names. If MetaDataOnly is false, 
    411      *  dynamic loop values are included, and unnecessary information like string 
    412      *  location values are not included. 
    413      *  
    414      *  The FEPSimulator takes in the toCondensedFormat() output, with a MetaDataOnly 
    415      *  value of false, over the socket. 
    416      *  
    417      *  The MetaDataOnly flag should be used to get a full dump of the highways 
    418      *  information. This was used to get the highways_fullmap.txt output. 
    419      *  
    420      * @param MetaDataOnly Whether you want meta data, or a full dump for FEPSim 
    421      * @return String, highways data in condensed format 
    422      *  
    423      * Example toCondensedFormat(MetaDataOnly = false) output: 
    424      *  
    425      * 43                       // "number of lines" 
    426      * 32 0 13                  // "line id" "count num" "number of stations" 
    427      * 1210831 1 5 S 0.9 8      // "station id" "drop num" "route num"... 
    428      *                          //      ..."direction" "postmile" "number of loops" 
    429      * 1210832  0.0 0  ML_1     // "loop id" "occ" "vol" 
    430      * 1210833  0.0 0  ML_2     // .. 
    431      * 1210834  0.0 0  ML_3     // .. 
    432      * 1210835  0.0 0  ML_4     // .. 
    433      * 1210836  0.0 0  PASSAGE  // .. 
    434      * 1210837  0.0 0  DEMAND   // .. 
    435      * 1210838  0.0 0  QUEUE    // .. 
    436      * 1210839  0.0 0  RAMP_OFF // .. 
    437      * ... 
    438      *  
    439      * Example toCondensedFormat(MetaDataOnly = true) output: 
    440      *  
    441      * 43                           // "number of lines" 
    442      * 32 0 13                      // "line id" "count num" "number of stations" 
    443      * 1210831 1 5 S 0.9 8 CALAFIA  // "station id" "drop num" "route num"... 
    444      *                              //      ..."direction" "postmile"... 
    445      *                              //      ..."number of loops" "string location" 
    446      * 1210832 ML_1                 // "loop id" "loop location" 
    447      * 1210833 ML_2                 // "            " 
    448      * 1210834 ML_3                 // "            " 
    449      * 1210835 ML_4                 // "            " 
    450      * 1210836 PASSAGE              // "            " 
    451      * 1210837 DEMAND               // "            " 
    452      * 1210838 QUEUE                // "            " 
    453      * 1210839 RAMP_OFF             // "            " 
    454      * ... 
    455      */ 
    456     public String toCondensedFormat(boolean MetaDataOnly) 
    457     { 
    458         // first line: number of FEPLines 
    459         StringBuilder build = new StringBuilder(); 
    460         build.append(lines.size()); 
    461         build.append("\n"); 
    462         // append each fep line to the string 
    463         for(FEPLine line : lines) 
    464         { 
    465             build.append(line.toCondensedFormat(MetaDataOnly)); 
    466         } 
    467         // return the full condensed format string 
    468         return build.toString(); 
    469     } 
    470      
    471     /** 
    472      * Returns the Highways model data in XML format. 
    473      * Probably obsolete, since we aren't using exchange.xml any longer. 
    474      * @return highways data in XML format 
    475      */ 
    476     public String toXML() 
    477     { 
    478         String xml = null; 
    479         try 
    480         { 
    481             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    482             DocumentBuilder builder = factory.newDocumentBuilder(); 
    483             Document theDoc = builder.newDocument(); 
    484  
    485             Element networkElement = theDoc.createElement(XML_TAGS.NETWORK.tag); 
    486             theDoc.appendChild(networkElement); 
    487  
    488             for (FEPLine line : lines) 
    489             { 
    490                 line.toXML(networkElement); 
    491             } 
    492  
    493             Transformer tf = TransformerFactory.newInstance().newTransformer(); 
    494  
    495             tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 
    496             tf.setOutputProperty(OutputKeys.INDENT, "yes"); 
    497             tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 
    498  
    499             Writer out = new StringWriter(); 
    500             tf.transform(new DOMSource(theDoc), new StreamResult(out)); 
    501             xml = out.toString(); 
    502             out.close(); 
    503         } catch (Exception ex) 
    504         { 
    505             Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex); 
    506         } 
    507         return xml; 
    508  
    509     } 
    510  
     228        // For now we'll use just a dummy loop detector 
     229        LoopDetector detector = new LoopDetector(1,"ML","ML_1"); 
     230        loops.add(detector); 
     231 
     232        return new Station(11, 123, 99, description, loops, fwy, dir, postmile); 
     233    } 
     234      
    511235    /** 
    512236     * Returns a highway by given highway number. 
     
    531255    } 
    532256 
    533     /** Return a string representation of the Highways */ 
     257    /** Return a string representation of the Highways - for debugging */ 
    534258    public String toString() 
    535259    { 
     
    543267                StringBuilder lineout = new StringBuilder(); 
    544268                // Examine every station on this highway and direction 
    545                 for (Station stat: hwy.stations) 
    546                 { 
    547                     if (stat.direction.equals(dir)) 
     269                for (Station station: hwy.stations) 
     270                { 
     271                    if (station.direction.equals(dir)) 
    548272                    { 
    549273                    //lineout.append("" + dir.getLetter() + stat.postmile); 
    550                     lineout.append(stat.getColor()); 
     274                    lineout.append(station.getColor().symbol()); 
    551275                    //lineout.append("  "); 
    552276                    } 
     
    616340                    String outString = currentPM.toJson(); 
    617341                    // replace the color code with the color name 
    618                     String colorName=stat.getColorName(); 
     342                    String colorName=stat.getColor().htmlColor(); 
    619343                    outString = outString.replace("desiredcolor",colorName); 
    620344                    lineout.append(outString); 
     
    664388    } 
    665389     
    666     public void reset() 
    667     { 
    668         for(FEPLine line : lines) 
    669         { 
    670             for(Station stn : line.stations) 
     390    /** Reset all the traffic levels to free flowing (green) */ 
     391    public void reset()             
     392    { 
     393        for(Highway hwy: highways) 
     394        { 
     395            for(Station stn : hwy.stations) 
    671396            { 
    672397                for(LoopDetector ld : stn.loops) 
    673398                { 
    674                     ld.occ = 0; 
    675                     ld.vol = 0; 
     399                    ld.setAttributes(LoopDetector.DOTCOLOR.GREEN); 
    676400                } 
    677401            } 
Note: See TracChangeset for help on using the changeset viewer.