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