View Javadoc
1   package org.opentrafficsim.road.network.factory.xml;
2   
3   import java.io.Serializable;
4   import java.rmi.RemoteException;
5   import java.util.ArrayList;
6   import java.util.List;
7   
8   import javax.naming.NamingException;
9   
10  import org.djunits.unit.DurationUnit;
11  import org.djunits.unit.SpeedUnit;
12  import org.djunits.unit.TimeUnit;
13  import org.djunits.value.vdouble.scalar.Duration;
14  import org.djunits.value.vdouble.scalar.Length;
15  import org.djunits.value.vdouble.scalar.Speed;
16  import org.djunits.value.vdouble.scalar.Time;
17  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
18  import org.opentrafficsim.core.distributions.ProbabilityException;
19  import org.opentrafficsim.core.gtu.GTUDirectionality;
20  import org.opentrafficsim.core.gtu.GTUException;
21  import org.opentrafficsim.core.gtu.animation.GTUColorer;
22  import org.opentrafficsim.core.network.NetworkException;
23  import org.opentrafficsim.core.network.factory.xml.units.Distributions;
24  import org.opentrafficsim.core.network.factory.xml.units.TimeUnits;
25  import org.opentrafficsim.core.network.route.FixedRouteGenerator;
26  import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
27  import org.opentrafficsim.core.network.route.Route;
28  import org.opentrafficsim.core.network.route.RouteGenerator;
29  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
30  import org.opentrafficsim.road.gtu.generator.GTUGeneratorAnimation;
31  import org.opentrafficsim.road.gtu.generator.GTUGeneratorIndividual;
32  import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
33  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory;
34  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory;
35  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingTacticalPlannerFactory;
36  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
37  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
38  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
39  import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
40  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
41  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
42  import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory;
43  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
44  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
45  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
46  import org.opentrafficsim.road.network.factory.xml.CrossSectionElementTag.ElementType;
47  import org.opentrafficsim.road.network.lane.Lane;
48  import org.w3c.dom.NamedNodeMap;
49  import org.w3c.dom.Node;
50  import org.xml.sax.SAXException;
51  
52  import nl.tudelft.simulation.dsol.SimRuntimeException;
53  import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
54  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
55  import nl.tudelft.simulation.jstats.streams.StreamInterface;
56  
57  /**
58   * <p>
59   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
60   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
61   * <p>
62   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
63   * initial version Jul 23, 2015 <br>
64   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
65   */
66  class GeneratorTag implements Serializable
67  {
68      /** */
69      private static final long serialVersionUID = 20150723L;
70  
71      /** Lane name. */
72      @SuppressWarnings("checkstyle:visibilitymodifier")
73      String laneName = null;
74  
75      /** Position of the sink on the link, relative to the design line, stored as a string to parse when the length is known. */
76      @SuppressWarnings("checkstyle:visibilitymodifier")
77      String positionStr = null;
78  
79      /** Direction in which to generate the GTU, relative to the design line of the Link. */
80      // TOO parse direction, and add to XML formal
81      GTUDirectionality gtuDirection = GTUDirectionality.DIR_PLUS;
82  
83      /** GTU tag. */
84      @SuppressWarnings("checkstyle:visibilitymodifier")
85      GTUTag gtuTag = null;
86  
87      /** GTU mix tag. */
88      @SuppressWarnings("checkstyle:visibilitymodifier")
89      GTUMixTag gtuMixTag = null;
90  
91      /** Tactical planner name. */
92      @SuppressWarnings("checkstyle:visibilitymodifier")
93      String tacticalPlannerName = null;
94  
95      /** Interarrival time. */
96      @SuppressWarnings("checkstyle:visibilitymodifier")
97      ContinuousDistDoubleScalar.Rel<Duration, DurationUnit> iatDist = null;
98  
99      /** Initial speed. */
100     @SuppressWarnings("checkstyle:visibilitymodifier")
101     ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> initialSpeedDist = null;
102 
103     /** Maximimum number of generated GTUs. */
104     @SuppressWarnings("checkstyle:visibilitymodifier")
105     int maxGTUs = Integer.MAX_VALUE;
106 
107     /** Start time of generation. */
108     @SuppressWarnings("checkstyle:visibilitymodifier")
109     Time startTime = null;
110 
111     /** End time of generation. */
112     @SuppressWarnings("checkstyle:visibilitymodifier")
113     Time endTime = null;
114 
115     /** Route tag. */
116     @SuppressWarnings("checkstyle:visibilitymodifier")
117     RouteTag routeTag = null;
118 
119     /** Route mix tag. */
120     @SuppressWarnings("checkstyle:visibilitymodifier")
121     RouteMixTag routeMixTag = null;
122 
123     /** Shortest route tag. */
124     @SuppressWarnings("checkstyle:visibilitymodifier")
125     ShortestRouteTag shortestRouteTag = null;
126 
127     /** Shortest route mix tag. */
128     @SuppressWarnings("checkstyle:visibilitymodifier")
129     ShortestRouteMixTag shortestRouteMixTag = null;
130 
131     /** GTU colorer. */
132     @SuppressWarnings("checkstyle:visibilitymodifier")
133     GTUColorer gtuColorer;
134 
135     /**
136      * Parse the GENERATOR tag.
137      * @param node the GENERATOR node to parse
138      * @param parser the parser with the lists of information
139      * @param linkTag the parent LINK tag
140      * @throws SAXException when parsing of the tag fails
141      * @throws NetworkException when parsing of the tag fails
142      */
143     @SuppressWarnings("checkstyle:needbraces")
144     static void parseGenerator(final Node node, final XmlNetworkLaneParser parser, final LinkTag linkTag)
145             throws SAXException, NetworkException
146     {
147         NamedNodeMap attributes = node.getAttributes();
148         GeneratorTag generatorTag = new GeneratorTag();
149 
150         if (attributes.getNamedItem("LANE") == null)
151             throw new SAXException("GENERATOR: missing attribute LANE" + " for link " + linkTag.name);
152         String laneName = attributes.getNamedItem("LANE").getNodeValue().trim();
153         if (linkTag.roadLayoutTag == null)
154             throw new NetworkException("GENERATOR: LANE " + laneName + " no ROADTYPE for link " + linkTag.name);
155         CrossSectionElementTag cseTag = linkTag.roadLayoutTag.cseTags.get(laneName);
156         if (cseTag == null)
157             throw new NetworkException("GENERATOR: LANE " + laneName + " not found in elements of link " + linkTag.name
158                     + " - roadtype " + linkTag.roadLayoutTag.name);
159         if (cseTag.elementType != ElementType.LANE)
160             throw new NetworkException("GENERATOR: LANE " + laneName + " not a real GTU lane for link " + linkTag.name
161                     + " - roadtype " + linkTag.roadLayoutTag.name);
162         if (linkTag.generatorTags.containsKey(laneName))
163             throw new SAXException("GENERATOR for LANE with NAME " + laneName + " defined twice");
164         generatorTag.laneName = laneName;
165 
166         Node position = attributes.getNamedItem("POSITION");
167         if (position == null)
168             throw new NetworkException("GENERATOR: POSITION element not found in elements of link " + linkTag.name
169                     + " - roadtype " + linkTag.roadLayoutTag.name);
170         generatorTag.positionStr = position.getNodeValue().trim();
171 
172         /*-
173         // TODO parse direction
174         Node directionStr = attributes.getNamedItem("DIRECTION");
175         if (directionStr == null)
176             throw new NetworkException("GENERATOR: DIRECTION element not found in elements of link " + linkTag.name
177                 + " - roadtype " + linkTag.roadLayoutTag.name);
178         generatorTag.gtuDirection = parseDirection(directionStr.getNodeValue().trim());
179          */
180 
181         if (attributes.getNamedItem("GTU") != null)
182         {
183             String gtuName = attributes.getNamedItem("GTU").getNodeValue().trim();
184             if (!parser.gtuTags.containsKey(gtuName))
185                 throw new NetworkException(
186                         "GENERATOR: LANE " + laneName + " GTU " + gtuName + " in link " + linkTag.name + " not defined");
187             generatorTag.gtuTag = parser.gtuTags.get(gtuName);
188         }
189 
190         if (attributes.getNamedItem("GTUMIX") != null)
191         {
192             String gtuMixName = attributes.getNamedItem("GTUMIX").getNodeValue().trim();
193             if (!parser.gtuMixTags.containsKey(gtuMixName))
194                 throw new NetworkException(
195                         "GENERATOR: LANE " + laneName + " GTUMIX " + gtuMixName + " in link " + linkTag.name + " not defined");
196             generatorTag.gtuMixTag = parser.gtuMixTags.get(gtuMixName);
197         }
198 
199         if (generatorTag.gtuTag == null && generatorTag.gtuMixTag == null)
200             throw new SAXException(
201                     "GENERATOR: missing attribute GTU or GTUMIX for Lane with NAME " + laneName + " of link " + linkTag.name);
202 
203         if (generatorTag.gtuTag != null && generatorTag.gtuMixTag != null)
204             throw new SAXException("GENERATOR: both attribute GTU and GTUMIX defined for Lane with NAME " + laneName
205                     + " of link " + linkTag.name);
206 
207         if (attributes.getNamedItem("TACTICALPLANNER") != null)
208         {
209             generatorTag.tacticalPlannerName = attributes.getNamedItem("TACTICALPLANNER").getNodeValue().trim();
210         }
211 
212         Node iat = attributes.getNamedItem("IAT");
213         if (iat == null)
214             throw new SAXException("GENERATOR: missing attribute IAT");
215         generatorTag.iatDist = Distributions.parseDurationDist(iat.getNodeValue());
216 
217         Node initialSpeed = attributes.getNamedItem("INITIALSPEED");
218         if (initialSpeed == null)
219             throw new SAXException("GENERATOR: missing attribute INITIALSPEED");
220         generatorTag.initialSpeedDist = Distributions.parseSpeedDist(initialSpeed.getNodeValue());
221 
222         Node maxGTU = attributes.getNamedItem("MAXGTU");
223         generatorTag.maxGTUs = maxGTU == null ? Integer.MAX_VALUE : Integer.parseInt(maxGTU.getNodeValue().trim());
224 
225         if (attributes.getNamedItem("STARTTIME") != null)
226             generatorTag.startTime = TimeUnits.parseTime(attributes.getNamedItem("STARTTIME").getNodeValue());
227 
228         if (attributes.getNamedItem("ENDTIME") != null)
229             generatorTag.endTime = TimeUnits.parseTime(attributes.getNamedItem("ENDTIME").getNodeValue());
230 
231         int numberRouteTags = 0;
232 
233         if (attributes.getNamedItem("ROUTE") != null)
234         {
235             String routeName = attributes.getNamedItem("ROUTE").getNodeValue().trim();
236             if (!parser.routeTags.containsKey(routeName))
237                 throw new NetworkException(
238                         "GENERATOR: LANE " + laneName + " ROUTE " + routeName + " in link " + linkTag.name + " not defined");
239             generatorTag.routeTag = parser.routeTags.get(routeName);
240             numberRouteTags++;
241         }
242 
243         if (attributes.getNamedItem("ROUTEMIX") != null)
244         {
245             String routeMixName = attributes.getNamedItem("ROUTEMIX").getNodeValue().trim();
246             if (!parser.routeMixTags.containsKey(routeMixName))
247                 throw new NetworkException("GENERATOR: LANE " + laneName + " ROUTEMIX " + routeMixName + " in link "
248                         + linkTag.name + " not defined");
249             generatorTag.routeMixTag = parser.routeMixTags.get(routeMixName);
250             numberRouteTags++;
251         }
252 
253         if (attributes.getNamedItem("SHORTESTROUTE") != null)
254         {
255             String shortestRouteName = attributes.getNamedItem("SHORTESTROUTE").getNodeValue().trim();
256             if (!parser.shortestRouteTags.containsKey(shortestRouteName))
257                 throw new NetworkException("GENERATOR: LANE " + laneName + " SHORTESTROUTE " + shortestRouteName + " in link "
258                         + linkTag.name + " not defined");
259             generatorTag.shortestRouteTag = parser.shortestRouteTags.get(shortestRouteName);
260             numberRouteTags++;
261         }
262 
263         if (attributes.getNamedItem("SHORTESTROUTEMIX") != null)
264         {
265             String shortestRouteMixName = attributes.getNamedItem("SHORTESTROUTEMIX").getNodeValue().trim();
266             if (!parser.shortestRouteMixTags.containsKey(shortestRouteMixName))
267                 throw new NetworkException("GENERATOR: LANE " + laneName + " SHORTESTROUTEMIX " + shortestRouteMixName
268                         + " in link " + linkTag.name + " not defined");
269             generatorTag.shortestRouteMixTag = parser.shortestRouteMixTags.get(shortestRouteMixName);
270             numberRouteTags++;
271         }
272 
273         if (numberRouteTags > 1)
274             throw new SAXException(
275                     "GENERATOR: multiple ROUTE tags defined for Lane with NAME " + laneName + " of link " + linkTag.name);
276 
277         if (numberRouteTags == 0)
278             throw new SAXException(
279                     "GENERATOR: no ROUTE tags defined for Lane with NAME " + laneName + " of link " + linkTag.name);
280 
281         Node gtuColorerNode = attributes.getNamedItem("GTUCOLORER");
282         if (gtuColorerNode == null)
283             throw new SAXException("GENERATOR: missing attribute GTUCOLORER");
284         generatorTag.gtuColorer = GTUColorerTag.parseGTUColorer(gtuColorerNode.getNodeValue().trim(), parser.globalTag);
285 
286         linkTag.generatorTags.put(generatorTag.laneName, generatorTag);
287     }
288 
289     /**
290      * Make the generators for this link, if available.
291      * @param linkTag the parent LINK tag
292      * @param parser the parser with the lists of information
293      * @param simulator the simulator to schedule GTU generation
294      * @throws SimRuntimeException in case of simulation problems building the car generator
295      * @throws NetworkException when route generator cannot be instantiated
296      * @throws GTUException when construction of the Strategical Planner failed
297      */
298     static void makeGenerators(final LinkTag linkTag, final XmlNetworkLaneParser parser,
299             final DEVSSimulatorInterface.TimeDoubleUnit simulator) throws SimRuntimeException, NetworkException, GTUException
300     {
301         for (GeneratorTag generatorTag : linkTag.generatorTags.values())
302         {
303             makeGenerator(generatorTag, parser, linkTag, simulator);
304         }
305     }
306 
307     /**
308      * Make a generator.
309      * @param generatorTag XML tag for the generator to build
310      * @param parser the parser with the lists of information
311      * @param linkTag the parent LINK tag
312      * @param simulator the simulator to schedule GTU generation
313      * @throws SimRuntimeException in case of simulation problems building the car generator
314      * @throws NetworkException when route generator cannot be instantiated
315      * @throws GTUException when construction of the Strategical Planner failed
316      */
317     static void makeGenerator(final GeneratorTag generatorTag, final XmlNetworkLaneParser parser, final LinkTag linkTag,
318             final DEVSSimulatorInterface.TimeDoubleUnit simulator) throws SimRuntimeException, NetworkException, GTUException
319     {
320         Lane lane = linkTag.lanes.get(generatorTag.laneName);
321         Class<?> gtuClass = LaneBasedIndividualGTU.class;
322 
323         RouteGenerator routeGenerator;
324         if (generatorTag.routeMixTag == null)
325         {
326             List<org.opentrafficsim.core.network.Node> nodeList = new ArrayList<>();
327             for (NodeTag nodeTag : generatorTag.routeTag.routeNodeTags)
328             {
329                 nodeList.add(parser.nodeTags.get(nodeTag.name).node);
330             }
331             routeGenerator = new FixedRouteGenerator(new Route(generatorTag.laneName, nodeList));
332         }
333         else
334         {
335             List<FrequencyAndObject<Route>> probRoutes = new ArrayList<>();
336             for (int i = 0; i < generatorTag.routeMixTag.weights.size(); i++)
337             {
338                 List<org.opentrafficsim.core.network.Node> nodeList = new ArrayList<>();
339                 for (NodeTag nodeTag : generatorTag.routeMixTag.routes.get(i).routeNodeTags)
340                 {
341                     nodeList.add(parser.nodeTags.get(nodeTag.name).node);
342                 }
343                 probRoutes.add(new FrequencyAndObject<>(generatorTag.routeMixTag.weights.get(i),
344                         new Route(generatorTag.routeMixTag.routes.get(i).name, nodeList)));
345             }
346             try
347             {
348                 if (simulator.getReplication().getStream("GENERAL") == null)
349                 {
350                     simulator.getReplication().getStreams().put("GENERAL", new MersenneTwister(1L));
351                 }
352                 routeGenerator = new ProbabilisticRouteGenerator(probRoutes, simulator.getReplication().getStream("GENERAL"));
353             }
354             catch (ProbabilityException exception)
355             {
356                 throw new RuntimeException("Could not generate route mix.");
357             }
358         }
359         Time startTime = generatorTag.startTime != null ? generatorTag.startTime : Time.ZERO;
360         Time endTime = generatorTag.endTime != null ? generatorTag.endTime : new Time(Double.MAX_VALUE, TimeUnit.BASE_SECOND);
361         Length position = LinkTag.parseBeginEndPosition(generatorTag.positionStr, lane);
362         LaneBasedTacticalPlannerFactory<?> tacticalPlannerFactory =
363                 makeTacticalPlannerFactory(generatorTag, simulator.getReplication().getStream("GENERAL"));
364         LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactory =
365                 new LaneBasedStrategicalRoutePlannerFactory(tacticalPlannerFactory);
366         GTUGeneratorIndividual generator = new GTUGeneratorIndividual(linkTag.name + "." + generatorTag.laneName, simulator,
367                 generatorTag.gtuTag.gtuType, gtuClass, generatorTag.initialSpeedDist, generatorTag.iatDist,
368                 generatorTag.gtuTag.lengthDist, generatorTag.gtuTag.widthDist, generatorTag.gtuTag.maxSpeedDist,
369                 generatorTag.maxGTUs, startTime, endTime, lane, position, generatorTag.gtuDirection, generatorTag.gtuColorer,
370                 strategicalPlannerFactory, routeGenerator, parser.network);
371         try
372         {
373             new GTUGeneratorAnimation(generator, simulator);
374         }
375         catch (RemoteException | NamingException exception)
376         {
377             exception.printStackTrace();
378         }
379 
380         // TODO GTUMix
381         // TODO RouteMix
382         // TODO ShortestRoute
383         // TODO ShortestRouteMix
384     }
385 
386     /**
387      * Factories are: IDM|MOBIL/IDM|DIRECTION/IDM|LMRS|TOLEDO.
388      * @param generatorTag the tag to parse
389      * @param stream random number stream
390      * @return a LaneBasedTacticalPlannerFactory according to the tag
391      */
392     static LaneBasedTacticalPlannerFactory<?> makeTacticalPlannerFactory(final GeneratorTag generatorTag,
393             final StreamInterface stream)
394     {
395         if (generatorTag.tacticalPlannerName == null || generatorTag.tacticalPlannerName.equals("IDM"))
396         {
397             return new LaneBasedGTUFollowingTacticalPlannerFactory(new IDMPlusOld());
398         }
399         if (generatorTag.tacticalPlannerName.equals("MOBIL/IDM"))
400         {
401             return new LaneBasedCFLCTacticalPlannerFactory(new IDMPlusOld(), new Egoistic());
402         }
403         if (generatorTag.tacticalPlannerName.equals("DIRECTION/IDM"))
404         {
405             return new LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory(new IDMPlusOld());
406         }
407         if (generatorTag.tacticalPlannerName.equals("LMRS"))
408         {
409             try
410             {
411                 return new LMRSFactory(new IDMPlusFactory(stream), new DefaultLMRSPerceptionFactory());
412             }
413             catch (GTUException exception)
414             {
415                 exception.printStackTrace();
416             }
417         }
418         if (generatorTag.tacticalPlannerName.equals("TOLEDO"))
419         {
420             return new ToledoFactory();
421         }
422         System.err.println("Unknown generatorTag.tacticalPlannerName: " + generatorTag.tacticalPlannerName
423                 + ", not one of: IDM|MOBIL/IDM|DIRECTION/IDM|LMRS|TOLEDO");
424         return new LaneBasedGTUFollowingTacticalPlannerFactory(new IDMPlusOld());
425     }
426 
427     /** {@inheritDoc} */
428     @Override
429     public final String toString()
430     {
431         return "GeneratorTag [laneName=" + this.laneName + ", positionStr=" + this.positionStr + ", gtuDirection="
432                 + this.gtuDirection + ", gtuTag=" + this.gtuTag + ", gtuMixTag=" + this.gtuMixTag + ", iatDist=" + this.iatDist
433                 + ", initialSpeedDist=" + this.initialSpeedDist + ", maxGTUs=" + this.maxGTUs + ", startTime=" + this.startTime
434                 + ", endTime=" + this.endTime + ", routeTag=" + this.routeTag + ", routeMixTag=" + this.routeMixTag
435                 + ", shortestRouteTag=" + this.shortestRouteTag + ", shortestRouteMixTag=" + this.shortestRouteMixTag
436                 + ", gtuColorer=" + this.gtuColorer + "]";
437     }
438 
439 }