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