1 package org.opentrafficsim.road.network.factory.xml.parser;
2
3 import java.util.ArrayList;
4 import java.util.LinkedHashMap;
5 import java.util.LinkedHashSet;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9
10 import org.djunits.unit.DurationUnit;
11 import org.djunits.value.vdouble.scalar.Duration;
12 import org.djunits.value.vdouble.scalar.Frequency;
13 import org.djunits.value.vdouble.scalar.Length;
14 import org.djunits.value.vdouble.scalar.Speed;
15 import org.opentrafficsim.base.parameters.ParameterException;
16 import org.opentrafficsim.core.distributions.Distribution;
17 import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
18 import org.opentrafficsim.core.distributions.Generator;
19 import org.opentrafficsim.core.distributions.ProbabilityException;
20 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
21 import org.opentrafficsim.core.gtu.GTUDirectionality;
22 import org.opentrafficsim.core.gtu.GTUType;
23 import org.opentrafficsim.core.idgenerator.IdGenerator;
24 import org.opentrafficsim.core.network.NetworkException;
25 import org.opentrafficsim.core.network.Node;
26 import org.opentrafficsim.core.network.route.FixedRouteGenerator;
27 import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
28 import org.opentrafficsim.core.network.route.Route;
29 import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
30 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
31 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
32 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
33 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
34 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
35 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
36 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
37 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
38 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
39 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
40 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
41 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
42 import org.opentrafficsim.road.network.OTSRoadNetwork;
43 import org.opentrafficsim.road.network.factory.xml.XmlParserException;
44 import org.opentrafficsim.road.network.factory.xml.utils.Generators;
45 import org.opentrafficsim.road.network.factory.xml.utils.StreamInformation;
46 import org.opentrafficsim.road.network.factory.xml.utils.Transformer;
47 import org.opentrafficsim.road.network.lane.CrossSectionLink;
48 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
49 import org.opentrafficsim.road.network.lane.Lane;
50 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
51 import org.opentrafficsim.xml.generated.GENERATOR;
52 import org.opentrafficsim.xml.generated.GTUTEMPLATE;
53 import org.opentrafficsim.xml.generated.NETWORKDEMAND;
54 import org.opentrafficsim.xml.generated.ROUTE;
55 import org.opentrafficsim.xml.generated.ROUTEMIX;
56 import org.opentrafficsim.xml.generated.SHORTESTROUTE;
57 import org.opentrafficsim.xml.generated.SHORTESTROUTEMIX;
58 import org.opentrafficsim.xml.generated.SINK;
59
60 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
61 import nl.tudelft.simulation.jstats.streams.StreamInterface;
62
63
64
65
66
67
68
69
70
71 public final class GeneratorSinkParser
72 {
73
74 private GeneratorSinkParser()
75 {
76
77 }
78
79
80
81
82
83
84
85 @SuppressWarnings("checkstyle:needbraces")
86 static void parseRoutes(final OTSRoadNetwork otsNetwork, final NETWORKDEMAND demand) throws NetworkException
87 {
88 for (ROUTE routeTag : demand.getROUTE())
89 {
90 Route route = new Route(routeTag.getID());
91 GTUType gtuType = otsNetwork.getGtuType(routeTag.getGTUTYPE());
92 if (gtuType == null)
93 throw new NetworkException("GTUTYPE " + routeTag.getGTUTYPE() + " not found in ROUTE " + routeTag.getID());
94 for (ROUTE.NODE nodeTag : routeTag.getNODE())
95 {
96 Node node = otsNetwork.getNode(nodeTag.getID());
97 if (node == null)
98 throw new NetworkException("NODE " + nodeTag.getID() + " not found in ROUTE " + routeTag.getID());
99 route.addNode(node);
100 }
101 otsNetwork.addRoute(gtuType, route);
102 }
103 }
104
105
106
107
108
109
110
111 @SuppressWarnings("checkstyle:needbraces")
112 static void parseShortestRoutes(final OTSRoadNetwork otsNetwork, final NETWORKDEMAND demand) throws NetworkException
113 {
114 for (SHORTESTROUTE shortestRouteTag : demand.getSHORTESTROUTE())
115 {
116 Route route = new Route(shortestRouteTag.getID());
117 GTUType gtuType = otsNetwork.getGtuType(shortestRouteTag.getGTUTYPE());
118 if (gtuType == null)
119 throw new NetworkException(
120 "GTUTYPE " + shortestRouteTag.getGTUTYPE() + " not found in SHORTESTROUTE " + shortestRouteTag.getID());
121 Node nodeFrom = otsNetwork.getNode(shortestRouteTag.getFROM().getNODE());
122 if (nodeFrom == null)
123 throw new NetworkException("FROM NODE " + shortestRouteTag.getFROM().getNODE() + " not found in SHORTESTROUTE "
124 + shortestRouteTag.getID());
125 Node nodeTo = otsNetwork.getNode(shortestRouteTag.getTO().getNODE());
126 if (nodeTo == null)
127 throw new NetworkException("TO NODE " + shortestRouteTag.getTO().getNODE() + " not found in SHORTESTROUTE "
128 + shortestRouteTag.getID());
129 List<Node> nodesVia = new ArrayList<>();
130 for (SHORTESTROUTE.VIA nodeViaTag : shortestRouteTag.getVIA())
131 {
132 Node nodeVia = otsNetwork.getNode(nodeViaTag.getNODE());
133 if (nodeTo == null)
134 throw new NetworkException(
135 "VIA NODE " + nodeViaTag.getNODE() + " not found in SHORTESTROUTE " + shortestRouteTag.getID());
136 nodesVia.add(nodeVia);
137 }
138
139 Route shortestRoute = otsNetwork.getShortestRouteBetween(gtuType, nodeFrom, nodeTo, nodesVia);
140 if (shortestRoute == null)
141 {
142 throw new NetworkException("Cannot find shortest route from " + nodeFrom.getId() + " to " + nodeTo.getId());
143 }
144 for (Node node : shortestRoute.getNodes())
145 {
146 route.addNode(node);
147 }
148 otsNetwork.addRoute(gtuType, route);
149 }
150 }
151
152
153
154
155
156
157
158
159 @SuppressWarnings("checkstyle:needbraces")
160 static Map<String, List<FrequencyAndObject<Route>>> parseRouteMix(final OTSRoadNetwork otsNetwork,
161 final NETWORKDEMAND demand) throws NetworkException
162 {
163 Map<String, List<FrequencyAndObject<Route>>> routeMixMap = new LinkedHashMap<>();
164 for (ROUTEMIX routeMixTag : demand.getROUTEMIX())
165 {
166 List<FrequencyAndObject<Route>> probRoutes = new ArrayList<>();
167 for (ROUTEMIX.ROUTE mixRoute : routeMixTag.getROUTE())
168 {
169 String routeName = mixRoute.getID();
170 double weight = mixRoute.getWEIGHT();
171 Route route = otsNetwork.getRoute(routeName);
172 if (route == null)
173 throw new NetworkException(
174 "Parsing ROUTEMIX " + routeMixTag.getID() + " -- ROUTE " + routeName + " not found");
175 probRoutes.add(new FrequencyAndObject<>(weight, route));
176 }
177 routeMixMap.put(routeMixTag.getID(), probRoutes);
178 }
179 return routeMixMap;
180 }
181
182
183
184
185
186
187
188
189 @SuppressWarnings("checkstyle:needbraces")
190 static Map<String, List<FrequencyAndObject<Route>>> parseShortestRouteMix(final OTSRoadNetwork otsNetwork,
191 final NETWORKDEMAND demand) throws NetworkException
192 {
193 Map<String, List<FrequencyAndObject<Route>>> shortestRouteMixMap = new LinkedHashMap<>();
194 for (SHORTESTROUTEMIX routeMixTag : demand.getSHORTESTROUTEMIX())
195 {
196 List<FrequencyAndObject<Route>> probRoutes = new ArrayList<>();
197 for (SHORTESTROUTEMIX.SHORTESTROUTE mixRoute : routeMixTag.getSHORTESTROUTE())
198 {
199 String routeName = mixRoute.getID();
200 double weight = mixRoute.getWEIGHT();
201 Route route = otsNetwork.getRoute(routeName);
202 if (route == null)
203 throw new NetworkException(
204 "Parsing SHORTESTROUTEMIX " + routeMixTag.getID() + " -- SHORESTROUTE " + routeName + " not found");
205 probRoutes.add(new FrequencyAndObject<>(weight, route));
206 }
207 shortestRouteMixMap.put(routeMixTag.getID(), probRoutes);
208 }
209 return shortestRouteMixMap;
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223 @SuppressWarnings("checkstyle:needbraces")
224 public static List<LaneBasedGTUGenerator> parseGenerators(final OTSRoadNetwork otsNetwork, final NETWORKDEMAND demand,
225 final Map<String, GTUTEMPLATE> gtuTemplates, final Map<String, List<FrequencyAndObject<Route>>> routeMixMap,
226 final Map<String, List<FrequencyAndObject<Route>>> shortestRouteMixMap,
227 final Map<String, StreamInformation> streamMap) throws XmlParserException
228 {
229 OTSSimulatorInterface simulator = otsNetwork.getSimulator();
230 List<LaneBasedGTUGenerator> generators = new ArrayList<>();
231 try
232 {
233 for (GENERATOR generatorTag : demand.getGENERATOR())
234 {
235
236 if (simulator.getReplication().getStream("generation") == null)
237 {
238 simulator.getReplication().getStreams().put("generation", new MersenneTwister(1L));
239 }
240 StreamInterface stream = simulator.getReplication().getStream("generation");
241
242 Generator<Route> routeGenerator;
243 if (generatorTag.getROUTE() != null)
244 {
245 Route route = otsNetwork.getRoute(generatorTag.getROUTE());
246 if (route == null)
247 throw new XmlParserException("GENERATOR for LANE " + generatorTag.getLINK() + "."
248 + generatorTag.getLANE() + ": Route " + generatorTag.getROUTE() + " not found");
249 routeGenerator = new FixedRouteGenerator(route);
250 }
251
252 else if (generatorTag.getROUTEMIX() != null)
253 {
254 List<FrequencyAndObject<Route>> routeMix = routeMixMap.get(generatorTag.getROUTEMIX());
255 if (routeMix == null)
256 throw new XmlParserException("GENERATOR for LANE " + generatorTag.getLINK() + "."
257 + generatorTag.getLANE() + ": RouteMix " + generatorTag.getROUTEMIX() + " not found");
258 try
259 {
260 routeGenerator = new ProbabilisticRouteGenerator(routeMix, stream);
261 }
262 catch (ProbabilityException exception)
263 {
264 throw new RuntimeException("GENERATOR for LANE " + generatorTag.getLINK() + "." + generatorTag.getLANE()
265 + "Could not generate RouteMix " + generatorTag.getROUTEMIX());
266 }
267 }
268
269 else if (generatorTag.getSHORTESTROUTE() != null)
270 {
271 Route shortestRoute = otsNetwork.getRoute(generatorTag.getSHORTESTROUTE());
272 if (shortestRoute == null)
273 throw new XmlParserException("GENERATOR for LANE " + generatorTag.getLINK() + "."
274 + generatorTag.getLANE() + ": ShortestRoute " + generatorTag.getSHORTESTROUTE() + " not found");
275 routeGenerator = new FixedRouteGenerator(shortestRoute);
276 }
277
278 else if (generatorTag.getSHORTESTROUTEMIX() != null)
279 {
280 List<FrequencyAndObject<Route>> shortestRouteMix =
281 shortestRouteMixMap.get(generatorTag.getSHORTESTROUTEMIX());
282 if (shortestRouteMix == null)
283 throw new XmlParserException(
284 "GENERATOR for LANE " + generatorTag.getLINK() + "." + generatorTag.getLANE()
285 + ": ShortestRouteMix " + generatorTag.getSHORTESTROUTEMIX() + " not found");
286 try
287 {
288 routeGenerator = new ProbabilisticRouteGenerator(shortestRouteMix, stream);
289 }
290 catch (ProbabilityException exception)
291 {
292 throw new RuntimeException("GENERATOR for LANE " + generatorTag.getLINK() + "." + generatorTag.getLANE()
293 + "Could not generate ShortestRouteMix " + generatorTag.getSHORTESTROUTEMIX());
294 }
295 }
296
297 else
298 {
299 throw new XmlParserException("GENERATOR for LANE " + generatorTag.getLINK() + "." + generatorTag.getLANE()
300 + ": No route information");
301 }
302
303 CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streamMap.get("generation").getStream());
304 LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
305 new LMRSFactory(idmPlusFactory, new DefaultLMRSPerceptionFactory());
306 LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
307 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory);
308
309
310 Distribution<LaneBasedTemplateGTUType> gtuTypeDistribution =
311 new Distribution<>(streamMap.get("generation").getStream());
312 if (generatorTag.getGTUTEMPLATE() != null)
313 {
314 GTUTEMPLATE templateTag = gtuTemplates.get(generatorTag.getGTUTEMPLATE());
315 if (templateTag == null)
316 throw new XmlParserException(
317 "GTUTEMPLATE " + generatorTag.getGTUTEMPLATE() + " in generator not defined");
318 GTUType gtuType = otsNetwork.getGtuType(templateTag.getGTUTYPE());
319 if (gtuType == null)
320 throw new XmlParserException("GTUTYPE " + templateTag.getGTUTYPE() + " in GTUTEMPLATE "
321 + generatorTag.getGTUTEMPLATE() + " not defined");
322 Generator<Length> lengthGenerator = Generators.makeLengthGenerator(streamMap, templateTag.getLENGTHDIST());
323 Generator<Length> widthGenerator = Generators.makeLengthGenerator(streamMap, templateTag.getWIDTHDIST());
324 Generator<Speed> maximumSpeedGenerator =
325 Generators.makeSpeedGenerator(streamMap, templateTag.getMAXSPEEDDIST());
326 LaneBasedTemplateGTUType templateGTUType = new LaneBasedTemplateGTUType(gtuType, lengthGenerator,
327 widthGenerator, maximumSpeedGenerator, strategicalFactory, routeGenerator);
328 gtuTypeDistribution.add(new FrequencyAndObject<>(1.0, templateGTUType));
329 }
330 else if (generatorTag.getGTUTEMPLATEMIX() != null)
331 {
332
333 throw new XmlParserException("GtuTemplateMix not implemented yet in GENERATOR");
334 }
335 else
336 {
337 throw new XmlParserException("No GTU information in GENERATOR");
338 }
339
340 RoomChecker roomChecker = Transformer.parseRoomChecker(generatorTag.getROOMCHECKER());
341
342 Generator<Duration> headwayGenerator =
343 new HeadwayGenerator(generatorTag.getFREQUENCY(), streamMap.get("generation").getStream());
344
345 CrossSectionLink link = (CrossSectionLink) otsNetwork.getLink(generatorTag.getLINK());
346 Lane lane = (Lane) link.getCrossSectionElement(generatorTag.getLANE());
347
348 Length position = Length.instantiateSI(5.0);
349
350 GTUDirectionality direction = GTUDirectionality.valueOf(generatorTag.getDIRECTION());
351 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>();
352 initialLongitudinalPositions.add(new DirectedLanePosition(lane, position, direction));
353
354 IdGenerator idGenerator = new IdGenerator(lane.getFullId());
355
356 LaneBasedTemplateGTUTypeDistribution characteristicsGenerator =
357 new LaneBasedTemplateGTUTypeDistribution(gtuTypeDistribution);
358 generators.add(new LaneBasedGTUGenerator(lane.getFullId(), headwayGenerator, characteristicsGenerator,
359 GeneratorPositions.create(initialLongitudinalPositions, stream), otsNetwork, simulator, roomChecker,
360 idGenerator));
361 }
362 }
363 catch (Exception exception)
364 {
365 throw new XmlParserException(exception);
366 }
367 return generators;
368 }
369
370
371
372
373
374
375
376
377 public static void parseSinks(final OTSRoadNetwork otsNetwork, final NETWORKDEMAND demand,
378 final OTSSimulatorInterface simulator) throws NetworkException
379 {
380 for (SINK sinkTag : demand.getSINK())
381 {
382 CrossSectionLink link = (CrossSectionLink) otsNetwork.getLink(sinkTag.getLINK());
383 Lane lane = (Lane) link.getCrossSectionElement(sinkTag.getLANE());
384 Length position = Transformer.parseLengthBeginEnd(sinkTag.getPOSITION(), lane.getLength());
385 new SinkSensor(lane, position, GTUDirectionality.valueOf(sinkTag.getDIRECTION()), simulator);
386 }
387 }
388
389
390
391
392
393
394
395
396
397
398
399
400 private static class HeadwayGenerator implements Generator<Duration>
401 {
402
403 private final Frequency demand;
404
405
406 private final StreamInterface stream;
407
408
409
410
411
412 HeadwayGenerator(final Frequency demand, final StreamInterface stream)
413 {
414 this.demand = demand;
415 this.stream = stream;
416 }
417
418
419 @Override
420 public Duration draw() throws ProbabilityException, ParameterException
421 {
422 return new Duration(-Math.log(this.stream.nextDouble()) / this.demand.si, DurationUnit.SI);
423 }
424
425 }
426 }