View Javadoc
1   package org.opentrafficsim.road.network.factory.xml.parser;
2   
3   import java.util.ArrayList;
4   import java.util.LinkedHashSet;
5   import java.util.List;
6   import java.util.Map;
7   import java.util.Set;
8   
9   import org.djunits.unit.DurationUnit;
10  import org.djunits.value.vdouble.scalar.Duration;
11  import org.djunits.value.vdouble.scalar.Frequency;
12  import org.djunits.value.vdouble.scalar.Length;
13  import org.djunits.value.vdouble.scalar.Speed;
14  import org.opentrafficsim.base.parameters.ParameterException;
15  import org.opentrafficsim.core.distributions.Distribution;
16  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
17  import org.opentrafficsim.core.distributions.Generator;
18  import org.opentrafficsim.core.distributions.ProbabilityException;
19  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
20  import org.opentrafficsim.core.gtu.GTUDirectionality;
21  import org.opentrafficsim.core.gtu.GTUType;
22  import org.opentrafficsim.core.idgenerator.IdGenerator;
23  import org.opentrafficsim.core.network.NetworkException;
24  import org.opentrafficsim.core.network.route.FixedRouteGenerator;
25  import org.opentrafficsim.core.network.route.Route;
26  import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
27  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
28  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
29  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
30  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
31  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
32  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
33  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
34  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
35  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
36  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
37  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
38  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
39  import org.opentrafficsim.road.network.OTSRoadNetwork;
40  import org.opentrafficsim.road.network.factory.xml.XmlParserException;
41  import org.opentrafficsim.road.network.factory.xml.utils.Generators;
42  import org.opentrafficsim.road.network.factory.xml.utils.StreamInformation;
43  import org.opentrafficsim.road.network.factory.xml.utils.Transformer;
44  import org.opentrafficsim.road.network.lane.CrossSectionLink;
45  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
46  import org.opentrafficsim.road.network.lane.Lane;
47  import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
48  import org.opentrafficsim.xml.generated.GENERATOR;
49  import org.opentrafficsim.xml.generated.GTUTEMPLATE;
50  import org.opentrafficsim.xml.generated.NETWORKDEMAND;
51  import org.opentrafficsim.xml.generated.SINK;
52  
53  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
54  import nl.tudelft.simulation.jstats.streams.StreamInterface;
55  
56  /**
57   * GeneratorSinkParser.java. <br>
58   * <br>
59   * Copyright (c) 2003-2018 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
60   * for project information <a href="https://www.simulation.tudelft.nl/" target="_blank">www.simulation.tudelft.nl</a>. The
61   * source code and binary code of this software is proprietary information of Delft University of Technology.
62   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
63   */
64  public class GeneratorSinkParser
65  {
66  
67      /** */
68      private GeneratorSinkParser()
69      {
70          // utility class
71      }
72  
73      /**
74       * Parse the Generators.
75       * @param otsNetwork OTSRoadNetwork; the network to insert the parsed objects in
76       * @param demand NETWORK; the NETWORK tag
77       * @param gtuTemplates GGTUTEMPLATE tags
78       * @param simulator OTSSimulatorInterface; the simulator
79       * @param streamMap map with stream information
80       * @return list of created GTU generators
81       * @throws XmlParserException when the objects cannot be inserted into the network due to inconsistencies
82       */
83      public static List<LaneBasedGTUGenerator> parseGenerators(final OTSRoadNetwork otsNetwork, final NETWORKDEMAND demand,
84              Map<String, GTUTEMPLATE> gtuTemplates, final OTSSimulatorInterface simulator,
85              Map<String, StreamInformation> streamMap) throws XmlParserException
86      {
87          List<LaneBasedGTUGenerator> generators = new ArrayList<>();
88          try
89          {
90              for (GENERATOR generatorTag : demand.getGENERATOR())
91              {
92  
93                  if (simulator.getReplication().getStream("generation") == null)
94                  {
95                      simulator.getReplication().getStreams().put("generation", new MersenneTwister(1L));
96                  }
97                  StreamInterface stream = simulator.getReplication().getStream("generation");
98  
99                  Generator<Route> routeGenerator;
100                 if (generatorTag.getROUTE() != null)
101                 {
102                     Route route = otsNetwork.getRoute(generatorTag.getROUTE());
103                     if (route == null)
104                         throw new XmlParserException("Route " + generatorTag.getROUTE() + " not found");
105                     routeGenerator = new FixedRouteGenerator(route);
106                 }
107                 else if (generatorTag.getROUTEMIX() != null)
108                 {
109                     // TODO: ROUTEMIX
110                     throw new XmlParserException("RouteMix not implemented yet in GENERATOR");
111                     /*-
112                     List<FrequencyAndObject<Route>> probRoutes = new ArrayList<>();
113                     for (int i = 0; i < generatorTag.routeMixTag.weights.size(); i++)
114                     {
115                     List<Node> nodeList = new ArrayList<>();
116                     for (NodeTag nodeTag : generatorTag.routeMixTag.routes.get(i).routeNodeTags)
117                     {
118                         nodeList.add(parser.nodeTags.get(nodeTag.name).node);
119                     }
120                     probRoutes.add(new FrequencyAndObject<>(generatorTag.routeMixTag.weights.get(i),
121                             new Route(generatorTag.routeMixTag.routes.get(i).name, nodeList)));
122                     }
123                     try
124                     {
125                     routeGenerator = new ProbabilisticRouteGenerator(probRoutes, stream);
126                     }
127                     catch (ProbabilityException exception)
128                     {
129                     throw new RuntimeException("Could not generate route mix.");
130                     }
131                     */
132                 }
133                 else if (generatorTag.getSHORTESTROUTE() != null)
134                 {
135                     Route shortestRoute = otsNetwork.getRoute(generatorTag.getSHORTESTROUTE());
136                     if (shortestRoute == null)
137                         throw new XmlParserException("ShortestRoute " + generatorTag.getSHORTESTROUTE() + " not found");
138                     routeGenerator = new FixedRouteGenerator(shortestRoute);
139                 }
140                 else if (generatorTag.getSHORTESTROUTE() != null)
141                 {
142                     // TODO: SHORTESTROUTEMIX
143                     throw new XmlParserException("ShortestRouteMix not implemented yet in GENERATOR");
144                 }
145                 else
146                 {
147                     throw new XmlParserException("No route information in GENERATOR");
148                 }
149 
150                 CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streamMap.get("generation").getStream());
151                 LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
152                         new LMRSFactory(idmPlusFactory, new DefaultLMRSPerceptionFactory());
153                 LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
154                         new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory);
155 
156                 // the distribution of GTUs
157                 Distribution<LaneBasedTemplateGTUType> gtuTypeDistribution =
158                         new Distribution<>(streamMap.get("generation").getStream());
159                 if (generatorTag.getGTUTEMPLATE() != null)
160                 {
161                     GTUTEMPLATE templateTag = gtuTemplates.get(generatorTag.getGTUTEMPLATE());
162                     if (templateTag == null)
163                         throw new XmlParserException(
164                                 "GTUTEMPLATE " + generatorTag.getGTUTEMPLATE() + " in generator not defined");
165                     GTUType gtuType = otsNetwork.getGtuType(templateTag.getGTUTYPE());
166                     if (gtuType == null)
167                         throw new XmlParserException("GTUTYPE " + templateTag.getGTUTYPE() + " in GTUTEMPLATE "
168                                 + generatorTag.getGTUTEMPLATE() + " not defined");
169                     Generator<Length> lengthGenerator = Generators.makeLengthGenerator(streamMap, templateTag.getLENGTHDIST());
170                     Generator<Length> widthGenerator = Generators.makeLengthGenerator(streamMap, templateTag.getWIDTHDIST());
171                     Generator<Speed> maximumSpeedGenerator =
172                             Generators.makeSpeedGenerator(streamMap, templateTag.getMAXSPEEDDIST());
173                     LaneBasedTemplateGTUType templateGTUType = new LaneBasedTemplateGTUType(gtuType, lengthGenerator,
174                             widthGenerator, maximumSpeedGenerator, strategicalFactory, routeGenerator);
175                     gtuTypeDistribution.add(new FrequencyAndObject<>(1.0, templateGTUType));
176                 }
177                 else if (generatorTag.getGTUTEMPLATEMIX() != null)
178                 {
179                     // TODO: GTUTEMPLATEMIX
180                     throw new XmlParserException("GtuTemplateMix not implemented yet in GENERATOR");
181                 }
182                 else
183                 {
184                     throw new XmlParserException("No GTU information in GENERATOR");
185                 }
186 
187                 RoomChecker roomChecker = Transformer.parseRoomChecker(generatorTag.getROOMCHECKER());
188 
189                 Generator<Duration> headwayGenerator =
190                         new HeadwayGenerator(generatorTag.getFREQUENCY(), streamMap.get("generation").getStream());
191 
192                 CrossSectionLink link = (CrossSectionLink) otsNetwork.getLink(generatorTag.getLINK());
193                 Lane lane = (Lane) link.getCrossSectionElement(generatorTag.getLANE());
194                 // TODO: remove this hack for testing
195                 Length position = Length.createSI(5.0); //Transformer.parseLengthBeginEnd(generatorTag.getPOSITION(), lane.getLength());
196                 GTUDirectionality direction = GTUDirectionality.valueOf(generatorTag.getDIRECTION());
197                 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>();
198                 initialLongitudinalPositions
199                         .add(new DirectedLanePosition(lane, position, direction));
200 
201                 IdGenerator idGenerator = new IdGenerator(lane.getFullId());
202                 
203                 LaneBasedTemplateGTUTypeDistribution characteristicsGenerator =
204                         new LaneBasedTemplateGTUTypeDistribution(gtuTypeDistribution);
205                 generators.add(new LaneBasedGTUGenerator(lane.getFullId(), headwayGenerator, characteristicsGenerator,
206                         GeneratorPositions.create(initialLongitudinalPositions, stream), otsNetwork, simulator, roomChecker,
207                         idGenerator));
208             }
209         }
210         catch (Exception exception)
211         {
212             throw new XmlParserException(exception);
213         }
214         return generators;
215     }
216 
217     /**
218      * Parse the Sinks.
219      * @param otsNetwork OTSRoadNetwork; the network to insert the parsed objects in
220      * @param demand NETWORK; the NETWORK tag
221      * @param simulator OTSSimulatorInterface; the simulator
222      * @throws NetworkException when the objects cannot be inserted into the network due to inconsistencies
223      */
224     public static void parseSinks(final OTSRoadNetwork otsNetwork, final NETWORKDEMAND demand,
225             final OTSSimulatorInterface simulator) throws NetworkException
226     {
227         for (SINK sinkTag : demand.getSINK())
228         {
229             CrossSectionLink link = (CrossSectionLink) otsNetwork.getLink(sinkTag.getLINK());
230             Lane lane = (Lane) link.getCrossSectionElement(sinkTag.getLANE());
231             Length position = Transformer.parseLengthBeginEnd(sinkTag.getPOSITION(), lane.getLength());
232             new SinkSensor(lane, position, simulator);
233         }
234     }
235 
236     /**
237      * <p>
238      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
239      * <br>
240      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
241      * <p>
242      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 29 jan. 2017 <br>
243      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
244      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
245      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
246      */
247     private static class HeadwayGenerator implements Generator<Duration>
248     {
249         /** Demand level. */
250         private final Frequency demand;
251 
252         /** the stream information. */
253         private final StreamInterface stream;
254 
255         /**
256          * @param demand Frequency; demand
257          * @param stream the stream to use for generation
258          */
259         HeadwayGenerator(final Frequency demand, final StreamInterface stream)
260         {
261             this.demand = demand;
262             this.stream = stream;
263         }
264 
265         /** {@inheritDoc} */
266         @Override
267         public Duration draw() throws ProbabilityException, ParameterException
268         {
269             return new Duration(-Math.log(this.stream.nextDouble()) / this.demand.si, DurationUnit.SI);
270         }
271 
272     }
273 }