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.gtu.GTUDirectionality;
15 import org.opentrafficsim.core.gtu.GTUException;
16 import org.opentrafficsim.core.gtu.animation.GTUColorer;
17 import org.opentrafficsim.core.network.NetworkException;
18 import org.opentrafficsim.core.network.factory.xml.units.Distributions;
19 import org.opentrafficsim.core.network.factory.xml.units.TimeUnits;
20 import org.opentrafficsim.core.network.route.FixedRouteGenerator;
21 import org.opentrafficsim.core.network.route.Route;
22 import org.opentrafficsim.core.network.route.RouteGenerator;
23 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
24 import org.opentrafficsim.road.gtu.generator.GTUGeneratorIndividual;
25 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
26 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory;
27 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory;
28 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingTacticalPlannerFactory;
29 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
30 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
31 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
32 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
33 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
34 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
35 import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory;
36 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
37 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
38 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
39 import org.opentrafficsim.road.network.factory.vissim.CrossSectionElementTag.ElementType;
40 import org.opentrafficsim.road.network.lane.Lane;
41 import org.w3c.dom.NamedNodeMap;
42 import org.w3c.dom.Node;
43 import org.xml.sax.SAXException;
44
45 import nl.tudelft.simulation.dsol.SimRuntimeException;
46 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
47 import nl.tudelft.simulation.jstats.streams.StreamInterface;
48
49
50
51
52
53
54
55
56
57
58 class GeneratorTag implements Serializable
59 {
60
61 private static final long serialVersionUID = 20150723L;
62
63
64 @SuppressWarnings("checkstyle:visibilitymodifier")
65 String laneName = null;
66
67
68 @SuppressWarnings("checkstyle:visibilitymodifier")
69 String positionStr = null;
70
71
72
73 GTUDirectionality gtuDirection = GTUDirectionality.DIR_PLUS;
74
75
76 @SuppressWarnings("checkstyle:visibilitymodifier")
77 GTUTag gtuTag = null;
78
79
80 @SuppressWarnings("checkstyle:visibilitymodifier")
81 GTUMixTag gtuMixTag = null;
82
83
84 @SuppressWarnings("checkstyle:visibilitymodifier")
85 ContinuousDistDoubleScalar.Rel<Duration, DurationUnit> iatDist = null;
86
87
88 @SuppressWarnings("checkstyle:visibilitymodifier")
89 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> initialSpeedDist = null;
90
91
92 @SuppressWarnings("checkstyle:visibilitymodifier")
93 int maxGTUs = Integer.MAX_VALUE;
94
95
96 @SuppressWarnings("checkstyle:visibilitymodifier")
97 Time startTime = null;
98
99
100 @SuppressWarnings("checkstyle:visibilitymodifier")
101 Time endTime = null;
102
103
104 @SuppressWarnings("checkstyle:visibilitymodifier")
105 RouteTag routeTag = null;
106
107
108 @SuppressWarnings("checkstyle:visibilitymodifier")
109 RouteMixTag routeMixTag = null;
110
111
112 @SuppressWarnings("checkstyle:visibilitymodifier")
113 ShortestRouteTag shortestRouteTag = null;
114
115
116 @SuppressWarnings("checkstyle:visibilitymodifier")
117 ShortestRouteMixTag shortestRouteMixTag = null;
118
119
120 @SuppressWarnings("checkstyle:visibilitymodifier")
121 String tacticalPlannerName = null;
122
123
124 @SuppressWarnings("checkstyle:visibilitymodifier")
125 GTUColorer gtuColorer;
126
127
128
129
130
131
132
133
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
178
179
180
181
182
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
325
326
327
328
329
330
331
332 static void makeGenerators(final LinkTag linkTag, final VissimNetworkLaneParser parser,
333 final DEVSSimulatorInterface.TimeDoubleUnit 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
343
344
345
346
347
348
349
350
351 static void makeGenerator(final GeneratorTag generatorTag, final VissimNetworkLaneParser parser, final LinkTag linkTag,
352 final DEVSSimulatorInterface.TimeDoubleUnit 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 RouteGenerator 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
366 LaneBasedTacticalPlannerFactory<?> tacticalPlannerFactory =
367 makeTacticalPlannerFactory(generatorTag, simulator.getReplication().getStream("default"));
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
377
378
379
380
381 }
382
383
384
385
386
387
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
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 }