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
59
60
61
62
63
64
65
66 class GeneratorTag implements Serializable
67 {
68
69 private static final long serialVersionUID = 20150723L;
70
71
72 @SuppressWarnings("checkstyle:visibilitymodifier")
73 String laneName = null;
74
75
76 @SuppressWarnings("checkstyle:visibilitymodifier")
77 String positionStr = null;
78
79
80
81 GTUDirectionality gtuDirection = GTUDirectionality.DIR_PLUS;
82
83
84 @SuppressWarnings("checkstyle:visibilitymodifier")
85 GTUTag gtuTag = null;
86
87
88 @SuppressWarnings("checkstyle:visibilitymodifier")
89 GTUMixTag gtuMixTag = null;
90
91
92 @SuppressWarnings("checkstyle:visibilitymodifier")
93 String tacticalPlannerName = null;
94
95
96 @SuppressWarnings("checkstyle:visibilitymodifier")
97 ContinuousDistDoubleScalar.Rel<Duration, DurationUnit> iatDist = null;
98
99
100 @SuppressWarnings("checkstyle:visibilitymodifier")
101 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> initialSpeedDist = null;
102
103
104 @SuppressWarnings("checkstyle:visibilitymodifier")
105 int maxGTUs = Integer.MAX_VALUE;
106
107
108 @SuppressWarnings("checkstyle:visibilitymodifier")
109 Time startTime = null;
110
111
112 @SuppressWarnings("checkstyle:visibilitymodifier")
113 Time endTime = null;
114
115
116 @SuppressWarnings("checkstyle:visibilitymodifier")
117 RouteTag routeTag = null;
118
119
120 @SuppressWarnings("checkstyle:visibilitymodifier")
121 RouteMixTag routeMixTag = null;
122
123
124 @SuppressWarnings("checkstyle:visibilitymodifier")
125 ShortestRouteTag shortestRouteTag = null;
126
127
128 @SuppressWarnings("checkstyle:visibilitymodifier")
129 ShortestRouteMixTag shortestRouteMixTag = null;
130
131
132 @SuppressWarnings("checkstyle:visibilitymodifier")
133 GTUColorer gtuColorer;
134
135
136
137
138
139
140
141
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
174
175
176
177
178
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
291
292
293
294
295
296
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
309
310
311
312
313
314
315
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
381
382
383
384 }
385
386
387
388
389
390
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
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 }