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
53
54
55
56
57
58
59
60 class GeneratorTag implements Serializable
61 {
62
63 private static final long serialVersionUID = 20150723L;
64
65
66 @SuppressWarnings("checkstyle:visibilitymodifier")
67 String laneName = null;
68
69
70 @SuppressWarnings("checkstyle:visibilitymodifier")
71 String positionStr = null;
72
73
74
75 GTUDirectionality gtuDirection = GTUDirectionality.DIR_PLUS;
76
77
78 @SuppressWarnings("checkstyle:visibilitymodifier")
79 GTUTag gtuTag = null;
80
81
82 @SuppressWarnings("checkstyle:visibilitymodifier")
83 GTUMixTag gtuMixTag = null;
84
85
86 @SuppressWarnings("checkstyle:visibilitymodifier")
87 ContinuousDistDoubleScalar.Rel<Duration, DurationUnit> iatDist = null;
88
89
90 @SuppressWarnings("checkstyle:visibilitymodifier")
91 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> initialSpeedDist = null;
92
93
94 @SuppressWarnings("checkstyle:visibilitymodifier")
95 int maxGTUs = Integer.MAX_VALUE;
96
97
98 @SuppressWarnings("checkstyle:visibilitymodifier")
99 Time startTime = null;
100
101
102 @SuppressWarnings("checkstyle:visibilitymodifier")
103 Time endTime = null;
104
105
106 @SuppressWarnings("checkstyle:visibilitymodifier")
107 RouteTag routeTag = null;
108
109
110 @SuppressWarnings("checkstyle:visibilitymodifier")
111 RouteMixTag routeMixTag = null;
112
113
114 @SuppressWarnings("checkstyle:visibilitymodifier")
115 ShortestRouteTag shortestRouteTag = null;
116
117
118 @SuppressWarnings("checkstyle:visibilitymodifier")
119 ShortestRouteMixTag shortestRouteMixTag = null;
120
121
122 @SuppressWarnings("checkstyle:visibilitymodifier")
123 String tacticalPlannerName = null;
124
125
126 @SuppressWarnings("checkstyle:visibilitymodifier")
127 GTUColorer gtuColorer;
128
129
130
131
132
133
134
135
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
180
181
182
183
184
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
327
328
329
330
331
332
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
345
346
347
348
349
350
351
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
377
378
379
380
381 }
382
383
384
385
386
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
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
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 }