1 package org.opentrafficsim.road.network.factory.xml.parser;
2
3 import java.io.Serializable;
4 import java.lang.reflect.Constructor;
5 import java.lang.reflect.InvocationTargetException;
6 import java.util.ArrayList;
7 import java.util.LinkedHashMap;
8 import java.util.LinkedHashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Map.Entry;
12 import java.util.Set;
13 import java.util.function.BiFunction;
14
15 import org.djunits.unit.Unit;
16 import org.djunits.value.vdouble.scalar.Acceleration;
17 import org.djunits.value.vdouble.scalar.Frequency;
18 import org.djunits.value.vdouble.scalar.Length;
19 import org.djunits.value.vdouble.scalar.LinearDensity;
20 import org.djunits.value.vdouble.scalar.Speed;
21 import org.djunits.value.vdouble.scalar.base.AbstractDoubleScalarRel;
22 import org.djutils.reflection.ClassUtil;
23 import org.opentrafficsim.base.parameters.ParameterException;
24 import org.opentrafficsim.base.parameters.ParameterSet;
25 import org.opentrafficsim.base.parameters.ParameterType;
26 import org.opentrafficsim.base.parameters.ParameterTypeDouble;
27 import org.opentrafficsim.base.parameters.ParameterTypeNumeric;
28 import org.opentrafficsim.base.parameters.Parameters;
29 import org.opentrafficsim.core.distributions.Generator;
30 import org.opentrafficsim.core.distributions.ProbabilityException;
31 import org.opentrafficsim.core.gtu.GTUException;
32 import org.opentrafficsim.core.gtu.GTUType;
33 import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
34 import org.opentrafficsim.core.gtu.perception.Perception;
35 import org.opentrafficsim.core.gtu.perception.PerceptionCategory;
36 import org.opentrafficsim.core.parameters.InputParameters;
37 import org.opentrafficsim.core.parameters.ParameterFactory;
38 import org.opentrafficsim.core.parameters.ParameterFactoryByType;
39 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
40 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
41 import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
42 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
43 import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
44 import org.opentrafficsim.road.gtu.lane.perception.categories.AnticipationTrafficPerception;
45 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectBusStopPerception;
46 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
47 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectIntersectionPerception;
48 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Anticipation;
49 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.DirectNeighborsPerception;
50 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Estimation;
51 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType;
52 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType.PerceivedHeadwayGtuType;
53 import org.opentrafficsim.road.gtu.lane.perception.mental.AdaptationHeadway;
54 import org.opentrafficsim.road.gtu.lane.perception.mental.AdaptationSituationalAwareness;
55 import org.opentrafficsim.road.gtu.lane.perception.mental.AdaptationSpeed;
56 import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller;
57 import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller.BehavioralAdaptation;
58 import org.opentrafficsim.road.gtu.lane.perception.mental.Mental;
59 import org.opentrafficsim.road.gtu.lane.perception.mental.Task;
60 import org.opentrafficsim.road.gtu.lane.perception.mental.TaskManager;
61 import org.opentrafficsim.road.gtu.lane.perception.mental.TaskManager.SummativeTaskManager;
62 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
63 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
64 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
65 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
66 import org.opentrafficsim.road.gtu.lane.tactical.following.DesiredHeadwayModel;
67 import org.opentrafficsim.road.gtu.lane.tactical.following.DesiredSpeedModel;
68 import org.opentrafficsim.road.gtu.lane.tactical.following.IDM;
69 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
70 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
71 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationBusStop;
72 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationConflicts;
73 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationIncentive;
74 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationNoRightOvertake;
75 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationSpeedLimitTransition;
76 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationTrafficLights;
77 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
78 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveBusStop;
79 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveCourtesy;
80 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveDummy;
81 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveGetInLane;
82 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
83 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
84 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSocioSpeed;
85 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
86 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveStayRight;
87 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
88 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.SocioDesiredSpeed;
89 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
90 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
91 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
92 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
93 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
94 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
95 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
96 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
97 import org.opentrafficsim.road.network.OTSRoadNetwork;
98 import org.opentrafficsim.road.network.factory.xml.XmlParserException;
99 import org.opentrafficsim.road.network.factory.xml.utils.ParseDistribution;
100 import org.opentrafficsim.road.network.factory.xml.utils.StreamInformation;
101 import org.opentrafficsim.xml.generated.CARFOLLOWINGMODELHEADWAYSPEEDTYPE;
102 import org.opentrafficsim.xml.generated.CARFOLLOWINGMODELHEADWAYSPEEDTYPE.DESIREDHEADWAYMODEL;
103 import org.opentrafficsim.xml.generated.CARFOLLOWINGMODELTYPE;
104 import org.opentrafficsim.xml.generated.DESIREDSPEEDMODELTYPE;
105 import org.opentrafficsim.xml.generated.MODELTYPE;
106 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.ACCELERATION;
107 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.ACCELERATIONDIST;
108 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.BOOLEAN;
109 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.CLASS;
110 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.DOUBLE;
111 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.DOUBLEDIST;
112 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.FRACTION;
113 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.FREQUENCY;
114 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.FREQUENCYDIST;
115 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.INTEGER;
116 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.INTEGERDIST;
117 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.LENGTH;
118 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.LENGTHDIST;
119 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.LINEARDENSITY;
120 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.LINEARDENSITYDIST;
121 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.SPEED;
122 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.SPEEDDIST;
123 import org.opentrafficsim.xml.generated.MODELTYPE.MODELPARAMETERS.STRING;
124 import org.opentrafficsim.xml.generated.MODELTYPE.TACTICALPLANNER.LMRS;
125 import org.opentrafficsim.xml.generated.MODELTYPE.TACTICALPLANNER.LMRS.ACCELERATIONINCENTIVES;
126 import org.opentrafficsim.xml.generated.MODELTYPE.TACTICALPLANNER.LMRS.MANDATORYINCENTIVES;
127 import org.opentrafficsim.xml.generated.MODELTYPE.TACTICALPLANNER.LMRS.VOLUNTARYINCENTIVES;
128 import org.opentrafficsim.xml.generated.PERCEPTIONTYPE;
129 import org.opentrafficsim.xml.generated.PERCEPTIONTYPE.CATEGORY;
130 import org.opentrafficsim.xml.generated.PERCEPTIONTYPE.HEADWAYGTUTYPE.PERCEIVED;
131 import org.opentrafficsim.xml.generated.PERCEPTIONTYPE.MENTAL.FULLER;
132 import org.opentrafficsim.xml.generated.PERCEPTIONTYPE.MENTAL.FULLER.BEHAVIORALADAPTATION;
133
134 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameter;
135 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
136 import nl.tudelft.simulation.jstats.distributions.DistDiscrete;
137
138
139
140
141
142
143
144
145
146
147
148
149 public class ModelParser
150 {
151
152 private ModelParser()
153 {
154
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 @SuppressWarnings("unchecked")
171 public static <U extends Unit<U>, T extends AbstractDoubleScalarRel<U, T>, K> Map<String, ParameterFactory> parseParameters(
172 final OTSRoadNetwork otsNetwork, final List<MODELTYPE> models, final InputParameters inputParameters,
173 final Map<String, ParameterType<?>> parameterTypes, final Map<String, StreamInformation> streamMap)
174 throws XmlParserException
175 {
176 Map<String, ParameterFactory> map = new LinkedHashMap<>();
177 for (MODELTYPE model : models)
178 {
179
180 ParameterFactoryByType paramFactory = new ParameterFactoryByType();
181 map.put(model.getID(), paramFactory);
182
183 if (model.getMODELPARAMETERS() != null)
184 {
185 for (Serializable parameter : model.getMODELPARAMETERS().getSTRINGOrACCELERATIONOrACCELERATIONDIST())
186 {
187 if (parameter instanceof STRING)
188 {
189 STRING p = (STRING) parameter;
190 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
191 (ParameterType<String>) parameterTypes.get(p.getID()), p.getValue());
192 }
193 else if (parameter instanceof ACCELERATION)
194 {
195 ACCELERATION p = (ACCELERATION) parameter;
196 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
197 (ParameterTypeNumeric<Acceleration>) parameterTypes.get(p.getID()), p.getValue());
198 }
199 else if (parameter instanceof ACCELERATIONDIST)
200 {
201 ACCELERATIONDIST p = (ACCELERATIONDIST) parameter;
202 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
203 (ParameterTypeNumeric<Acceleration>) parameterTypes.get(p.getID()),
204 ParseDistribution.parseAccelerationDist(streamMap, p));
205 }
206 else if (parameter instanceof BOOLEAN)
207 {
208 BOOLEAN p = (BOOLEAN) parameter;
209 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
210 (ParameterType<Boolean>) parameterTypes.get(p.getID()), p.isValue());
211 }
212 else if (parameter instanceof CLASS)
213 {
214 CLASS p = (CLASS) parameter;
215 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
216 (ParameterType<Class<?>>) parameterTypes.get(p.getID()), p.getValue());
217 }
218 else if (parameter instanceof DOUBLE)
219 {
220 DOUBLE p = (DOUBLE) parameter;
221 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
222 (ParameterType<Double>) parameterTypes.get(p.getID()), p.getValue());
223 }
224 else if (parameter instanceof DOUBLEDIST)
225 {
226 DOUBLEDIST p = (DOUBLEDIST) parameter;
227 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
228 (ParameterType<Double>) parameterTypes.get(p.getID()),
229 ParseDistribution.makeDistContinuous(streamMap, p));
230 }
231 else if (parameter instanceof FRACTION)
232 {
233 FRACTION p = (FRACTION) parameter;
234 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
235 (ParameterType<Double>) parameterTypes.get(p.getID()), p.getValue());
236 }
237 else if (parameter instanceof FREQUENCY)
238 {
239 FREQUENCY p = (FREQUENCY) parameter;
240 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
241 (ParameterTypeNumeric<Frequency>) parameterTypes.get(p.getID()), p.getValue());
242 }
243 else if (parameter instanceof FREQUENCYDIST)
244 {
245 FREQUENCYDIST p = (FREQUENCYDIST) parameter;
246 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
247 (ParameterTypeNumeric<Frequency>) parameterTypes.get(p.getID()),
248 ParseDistribution.parseFrequencyDist(streamMap, p));
249 }
250 else if (parameter instanceof INTEGER)
251 {
252 INTEGER p = (INTEGER) parameter;
253 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
254 (ParameterType<Integer>) parameterTypes.get(p.getID()), p.getValue());
255 }
256 else if (parameter instanceof INTEGERDIST)
257 {
258 INTEGERDIST p = (INTEGERDIST) parameter;
259 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
260 (ParameterType<Integer>) parameterTypes.get(p.getID()),
261 ParseDistribution.makeDistDiscrete(streamMap, p));
262 }
263 else if (parameter instanceof LENGTH)
264 {
265 LENGTH p = (LENGTH) parameter;
266 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
267 (ParameterType<Length>) parameterTypes.get(p.getID()), p.getValue());
268 }
269 else if (parameter instanceof LENGTHDIST)
270 {
271 LENGTHDIST p = (LENGTHDIST) parameter;
272 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
273 (ParameterTypeNumeric<Length>) parameterTypes.get(p.getID()),
274 ParseDistribution.parseLengthDist(streamMap, p));
275 }
276 else if (parameter instanceof LINEARDENSITY)
277 {
278 LINEARDENSITY p = (LINEARDENSITY) parameter;
279 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
280 (ParameterType<LinearDensity>) parameterTypes.get(p.getID()), p.getValue());
281 }
282 else if (parameter instanceof LINEARDENSITYDIST)
283 {
284 LINEARDENSITYDIST p = (LINEARDENSITYDIST) parameter;
285 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
286 (ParameterTypeNumeric<LinearDensity>) parameterTypes.get(p.getID()),
287 ParseDistribution.parseLinearDensityDist(streamMap, p));
288 }
289 else if (parameter instanceof SPEED)
290 {
291 SPEED p = (SPEED) parameter;
292 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
293 (ParameterType<Speed>) parameterTypes.get(p.getID()), p.getValue());
294 }
295 else if (parameter instanceof SPEEDDIST)
296 {
297 SPEEDDIST p = (SPEEDDIST) parameter;
298 paramFactory.addParameter(getGtuType(p.getGTUTYPE(), otsNetwork),
299 (ParameterTypeNumeric<Speed>) parameterTypes.get(p.getID()),
300 ParseDistribution.parseSpeedDist(streamMap, p));
301 }
302 }
303 }
304
305 for (GTUType gtuType : inputParameters.getObjects(GTUType.class))
306 {
307 for (Entry<String, InputParameter<?, ?>> entry : inputParameters.getInputParameters(gtuType).entrySet())
308 {
309 if (parameterTypes.containsKey(entry.getKey()))
310 {
311 ParameterType<?> parameterType = parameterTypes.get(entry.getKey());
312 InputParameter<?, ?> inputParameter = entry.getValue();
313 if (inputParameter.getValue() instanceof DistContinuous)
314 {
315 if (parameterType instanceof ParameterTypeDouble)
316 {
317 paramFactory.addParameter((ParameterTypeDouble) parameterType,
318 (DistContinuous) inputParameter.getValue());
319 }
320 else
321 {
322 paramFactory.addParameter((ParameterTypeNumeric<T>) parameterType,
323 (ContinuousDistDoubleScalar.Rel<T, U>) inputParameter.getValue());
324 }
325 }
326 else if (inputParameter.getValue() instanceof DistDiscrete)
327 {
328 paramFactory.addParameter(gtuType, (ParameterType<Integer>) parameterType,
329 (DistDiscrete) inputParameter.getValue());
330 }
331 else
332 {
333 paramFactory.addParameter(gtuType, (ParameterType<K>) parameterType, (K) inputParameter.getValue());
334 }
335 }
336 }
337 }
338 }
339 return map;
340 }
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356 public static <U extends Unit<U>, T extends AbstractDoubleScalarRel<U, T>,
357 K> Map<String, LaneBasedStrategicalPlannerFactory<?>> parseModel(final OTSRoadNetwork otsNetwork,
358 final List<MODELTYPE> models, final InputParameters inputParameters,
359 final Map<String, ParameterType<?>> parameterTypes, final Map<String, StreamInformation> streamMap,
360 final Map<String, ParameterFactory> parameterFactories) throws XmlParserException
361 {
362 Map<String, LaneBasedStrategicalPlannerFactory<?>> factories = new LinkedHashMap<>();
363 for (MODELTYPE model : models)
364 {
365
366 ParameterFactory paramFactory = parameterFactories.get(model.getID());
367
368
369 LaneBasedTacticalPlannerFactory<?> tacticalPlannerFactory;
370 if (model.getTACTICALPLANNER() != null)
371 {
372 if (model.getTACTICALPLANNER().getLMRS() != null)
373 {
374 tacticalPlannerFactory = parseLmrs(model.getTACTICALPLANNER().getLMRS());
375 }
376 else
377 {
378 throw new XmlParserException("Tactical planner has unsupported value.");
379 }
380 }
381 else
382 {
383
384 try
385 {
386 tacticalPlannerFactory = new LMRSFactory(new IDMPlusFactory(streamMap.get("generation").getStream()),
387 new DefaultLMRSPerceptionFactory());
388 }
389 catch (GTUException exception)
390 {
391 throw new XmlParserException(exception);
392 }
393 }
394
395 LaneBasedStrategicalPlannerFactory<?> strategicalPlannerFactory;
396 if (model.getSTRATEGICALPLANNER() == null || model.getSTRATEGICALPLANNER().getROUTE() != null)
397 {
398
399 strategicalPlannerFactory = new LaneBasedStrategicalRoutePlannerFactory(tacticalPlannerFactory, paramFactory);
400 }
401 else
402 {
403 throw new XmlParserException("Strategical planner has unsupported value.");
404 }
405
406 factories.put(model.getID(), strategicalPlannerFactory);
407 }
408 return factories;
409 }
410
411 @SuppressWarnings("unchecked")
412 private static <T> ParameterType<T> getParameterType(final String field, final Class<T> type)
413 {
414 int dot = field.lastIndexOf(".");
415 String className = field.substring(0, dot);
416 String fieldName = field.substring(dot + 1);
417 try
418 {
419 return (ParameterType<T>) ClassUtil.resolveField(Class.forName(className), fieldName).get(null);
420 }
421 catch (NoSuchFieldException | ClassCastException | IllegalArgumentException | IllegalAccessException
422 | ClassNotFoundException exception)
423 {
424 throw new RuntimeException(
425 "Unable to find parameter " + field + ", it may not be accessible or it is not a parameter of type " + type,
426 exception);
427 }
428 }
429
430
431
432
433
434
435
436 @SuppressWarnings("unchecked")
437 private static <T extends Number> ParameterTypeNumeric<T> getParameterTypeNumeric(final String field, final Class<T> type)
438 {
439 int dot = field.lastIndexOf(".");
440 String className = field.substring(0, dot);
441 String fieldName = field.substring(dot + 1);
442 try
443 {
444 return (ParameterTypeNumeric<T>) ClassUtil.resolveField(Class.forName(className), fieldName).get(null);
445 }
446 catch (NoSuchFieldException | ClassCastException | IllegalArgumentException | IllegalAccessException
447 | ClassNotFoundException exception)
448 {
449 throw new RuntimeException(
450 "Unable to find parameter " + field + ", it may not be accessible or it is not a parameter of type " + type,
451 exception);
452 }
453 }
454
455
456
457
458
459
460 private static GTUType getGtuType(final String gtuTypeId, final OTSRoadNetwork network)
461 {
462 if (gtuTypeId == null)
463 {
464 return null;
465 }
466 return network.getGtuType(gtuTypeId);
467 }
468
469
470
471
472
473
474
475 @SuppressWarnings("unchecked")
476 private static LaneBasedTacticalPlannerFactory<org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS> parseLmrs(
477 final LMRS lmrs) throws XmlParserException
478 {
479
480 Synchronization synchronization;
481 switch (lmrs.getSYNCHRONIZATION() != null ? lmrs.getSYNCHRONIZATION() : "PASSIVE")
482 {
483 case "DEADEND":
484 synchronization = Synchronization.DEADEND;
485 break;
486 case "PASSIVE":
487 synchronization = Synchronization.PASSIVE;
488 break;
489 case "PASSIVEMOVING":
490 synchronization = Synchronization.PASSIVE_MOVING;
491 break;
492 case "ALIGNGAP":
493 synchronization = Synchronization.ALIGN_GAP;
494 break;
495 case "ACTIVE":
496 synchronization = Synchronization.ACTIVE;
497 break;
498 default:
499 throw new XmlParserException("Synchronization " + lmrs.getSYNCHRONIZATION() + " is unknown.");
500 }
501
502
503 Cooperation cooperation;
504 switch (lmrs.getCOOPERATION() != null ? lmrs.getCOOPERATION() : "PASSIVE")
505 {
506 case "PASSIVE":
507 cooperation = Cooperation.PASSIVE;
508 break;
509 case "PASSIVEMOVING":
510 cooperation = Cooperation.PASSIVE_MOVING;
511 break;
512 case "ACTIVE":
513 cooperation = Cooperation.ACTIVE;
514 break;
515 default:
516 throw new XmlParserException("Cooperation " + lmrs.getCOOPERATION() + " is unknown.");
517 }
518
519
520 GapAcceptance gapAcceptance;
521 switch (lmrs.getGAPACCEPTANCE() != null ? lmrs.getGAPACCEPTANCE() : "INFORMED")
522 {
523 case "INFORMED":
524 gapAcceptance = GapAcceptance.INFORMED;
525 break;
526 case "EGOHEADWAY":
527 gapAcceptance = GapAcceptance.EGO_HEADWAY;
528 break;
529 default:
530 throw new XmlParserException("GapAcceptance " + lmrs.getGAPACCEPTANCE() + " is unknown.");
531 }
532
533
534 Tailgating tailgating;
535 switch (lmrs.getTAILGATING() != null ? lmrs.getTAILGATING() : "NONE")
536 {
537 case "NONE":
538 tailgating = Tailgating.NONE;
539 break;
540 case "RHOONLY":
541 tailgating = Tailgating.RHO_ONLY;
542 break;
543 case "PRESSURE":
544 tailgating = Tailgating.PRESSURE;
545 break;
546 default:
547 throw new XmlParserException("Tailgating " + lmrs.getTAILGATING() + " is unknown.");
548 }
549
550
551 Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
552 for (MANDATORYINCENTIVES.INCENTIVE incentive : lmrs.getMANDATORYINCENTIVES().getINCENTIVE())
553 {
554 switch (incentive.getValue())
555 {
556 case "ROUTE":
557 mandatoryIncentives.add(new IncentiveRoute());
558 break;
559 case "GETINLANE":
560 mandatoryIncentives.add(new IncentiveGetInLane());
561 break;
562 case "BUSSTOP":
563 mandatoryIncentives.add(new IncentiveBusStop());
564 break;
565 case "CLASS":
566 try
567 {
568 mandatoryIncentives.add((MandatoryIncentive) ClassUtil
569 .resolveConstructor(incentive.getCLASS(), new Class<?>[0]).newInstance());
570 }
571 catch (InstantiationException | IllegalAccessException | IllegalArgumentException
572 | InvocationTargetException | NoSuchMethodException | ClassCastException exception)
573 {
574 throw new XmlParserException("Class " + incentive.getCLASS()
575 + " does not have a valid empty contructor, or is not a MandatoryIncentive.");
576 }
577 break;
578 default:
579 throw new XmlParserException("MandatoryIncentive " + incentive.getValue() + " is unknown.");
580 }
581 }
582 if (mandatoryIncentives.isEmpty())
583 {
584 mandatoryIncentives.add(new IncentiveDummy());
585 }
586
587
588 Set<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
589 for (VOLUNTARYINCENTIVES.INCENTIVE incentive : lmrs.getVOLUNTARYINCENTIVES().getINCENTIVE())
590 {
591 switch (incentive.getValue())
592 {
593 case "KEEP":
594 voluntaryIncentives.add(new IncentiveKeep());
595 break;
596 case "SPEEDWITHCOURTESY":
597 voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
598 break;
599 case "COURTESY":
600 voluntaryIncentives.add(new IncentiveCourtesy());
601 break;
602 case "SOCIOSPEED":
603 voluntaryIncentives.add(new IncentiveSocioSpeed());
604 break;
605 case "STAYRIGHT":
606 voluntaryIncentives.add(new IncentiveStayRight());
607 break;
608 case "CLASS":
609 try
610 {
611 voluntaryIncentives.add((VoluntaryIncentive) ClassUtil
612 .resolveConstructor(incentive.getCLASS(), new Class<?>[0]).newInstance());
613 }
614 catch (InstantiationException | IllegalAccessException | IllegalArgumentException
615 | InvocationTargetException | NoSuchMethodException | ClassCastException exception)
616 {
617 throw new XmlParserException("Class " + incentive.getCLASS()
618 + " does not have a valid empty contructor, or is not a VoluntaryIncentive.");
619 }
620 break;
621 default:
622 throw new XmlParserException("VoluntaryIncentive " + incentive.getValue() + " is unknown.");
623 }
624 }
625
626
627 Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
628 for (ACCELERATIONINCENTIVES.INCENTIVE incentive : lmrs.getACCELERATIONINCENTIVES().getINCENTIVE())
629 {
630 switch (incentive.getValue())
631 {
632 case "BUSSTOP":
633 accelerationIncentives.add(new AccelerationBusStop());
634 break;
635 case "CONFLICTS":
636 accelerationIncentives.add(new AccelerationConflicts());
637 break;
638 case "SPEEDLIMITTRANSITION":
639 accelerationIncentives.add(new AccelerationSpeedLimitTransition());
640 break;
641 case "TRAFFICLIGHTS":
642 accelerationIncentives.add(new AccelerationTrafficLights());
643 break;
644 case "NORIGHTOVERTAKE":
645 accelerationIncentives.add(new AccelerationNoRightOvertake());
646 break;
647 case "CLASS":
648 try
649 {
650 accelerationIncentives.add((AccelerationIncentive) ClassUtil
651 .resolveConstructor(incentive.getCLASS(), new Class<?>[0]).newInstance());
652 }
653 catch (InstantiationException | IllegalAccessException | IllegalArgumentException
654 | InvocationTargetException | NoSuchMethodException | ClassCastException exception)
655 {
656 throw new XmlParserException("Class " + incentive.getCLASS()
657 + " does not have a valid empty contructor, or is not a AccelerationIncentive.");
658 }
659 break;
660 default:
661 throw new XmlParserException("AccelerationIncentive " + incentive.getValue() + " is unknown.");
662 }
663 }
664
665
666 PerceptionFactory perceptionFactory = parsePerception(lmrs.getPERCEPTION());
667
668
669
670 CarFollowingModelFactory<? extends CarFollowingModel> carFollowingModelFactory =
671 parseCarFollowingModel(lmrs.getCARFOLLOWINGMODEL());
672
673
674 return new LMRSFactory(carFollowingModelFactory, perceptionFactory, synchronization, cooperation, gapAcceptance,
675 tailgating, mandatoryIncentives, voluntaryIncentives, accelerationIncentives);
676 }
677
678
679
680
681
682
683
684 private static CarFollowingModelFactory<? extends CarFollowingModel> parseCarFollowingModel(
685 final CARFOLLOWINGMODELTYPE carFollowingModel) throws XmlParserException
686 {
687 CarFollowingModelFactory<? extends CarFollowingModel> carFollowingModelFactory;
688 if (carFollowingModel.getIDM() != null)
689 {
690 carFollowingModelFactory =
691 parseCarFollowingModelHeadwaySpeed(carFollowingModel.getIDM(), (headway, speed) -> new IDM(headway, speed));
692 }
693 else if (carFollowingModel.getIDMPLUS() != null)
694 {
695 carFollowingModelFactory = parseCarFollowingModelHeadwaySpeed(carFollowingModel.getIDMPLUS(),
696 (headway, speed) -> new IDMPlus(headway, speed));
697 }
698 else
699 {
700 throw new XmlParserException("Car-following model has unsupported value.");
701 }
702 return carFollowingModelFactory;
703 }
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720 private static <T extends CarFollowingModel> CarFollowingModelFactory<T> parseCarFollowingModelHeadwaySpeed(
721 final CARFOLLOWINGMODELHEADWAYSPEEDTYPE carFollowingModelHeadwaySpeed,
722 final BiFunction<DesiredHeadwayModel, DesiredSpeedModel, T> function) throws XmlParserException
723 {
724 Generator<DesiredHeadwayModel> generatorDesiredHeadwayModel =
725 parseDesiredHeadwayModel(carFollowingModelHeadwaySpeed.getDESIREDHEADWAYMODEL());
726 Generator<DesiredSpeedModel> generatorDesiredSpeedModel =
727 parseDesiredSpeedModel(carFollowingModelHeadwaySpeed.getDESIREDSPEEDMODEL());
728 return new CarFollowingModelFactory<T>()
729 {
730
731 @Override
732 public Parameters getParameters() throws ParameterException
733 {
734
735 return new ParameterSet();
736 }
737
738
739 @Override
740 public T generateCarFollowingModel()
741 {
742 try
743 {
744 return function.apply(generatorDesiredHeadwayModel.draw(), generatorDesiredSpeedModel.draw());
745 }
746 catch (ProbabilityException | ParameterException exception)
747 {
748 throw new RuntimeException("Exception while drawing desired headway or speed model.");
749 }
750 }
751 };
752 }
753
754
755
756
757
758
759
760 @SuppressWarnings("unchecked")
761 private static Generator<DesiredHeadwayModel> parseDesiredHeadwayModel(final DESIREDHEADWAYMODEL desiredHeadwayModel)
762 throws XmlParserException
763 {
764 if (desiredHeadwayModel.getIDM() != null)
765 {
766 return new Generator<DesiredHeadwayModel>()
767 {
768
769 @Override
770 public DesiredHeadwayModel draw() throws ProbabilityException, ParameterException
771 {
772 return AbstractIDM.HEADWAY;
773 }
774 };
775 }
776 else if (desiredHeadwayModel.getCLASS() != null)
777 {
778 Constructor<? extends DesiredHeadwayModel> constructor;
779 try
780 {
781 constructor = ClassUtil.resolveConstructor(desiredHeadwayModel.getCLASS(), new Object[0]);
782 }
783 catch (NoSuchMethodException exception)
784 {
785 throw new XmlParserException(
786 "Class " + desiredHeadwayModel.getCLASS() + " does not have a valid empty constructor.", exception);
787 }
788 return new Generator<DesiredHeadwayModel>()
789 {
790
791
792 @Override
793 public DesiredHeadwayModel draw() throws ProbabilityException, ParameterException
794 {
795 try
796 {
797 return constructor.newInstance();
798 }
799 catch (InstantiationException | IllegalAccessException | IllegalArgumentException
800 | InvocationTargetException exception)
801 {
802 throw new RuntimeException("Exception while instantiating a desired headway model of class "
803 + desiredHeadwayModel.getCLASS(), exception);
804 }
805 }
806
807 };
808 }
809 else
810 {
811 throw new XmlParserException("Desired headway model has unsupported value.");
812 }
813 }
814
815
816
817
818
819
820
821 @SuppressWarnings("unchecked")
822 private static Generator<DesiredSpeedModel> parseDesiredSpeedModel(final DESIREDSPEEDMODELTYPE desiredSpeedModel)
823 throws XmlParserException
824 {
825 if (desiredSpeedModel.getIDM() != null)
826 {
827 return new Generator<DesiredSpeedModel>()
828 {
829
830 @Override
831 public DesiredSpeedModel draw() throws ProbabilityException, ParameterException
832 {
833 return AbstractIDM.DESIRED_SPEED;
834 }
835 };
836 }
837 else if (desiredSpeedModel.getSOCIO() != null)
838 {
839
840 Generator<DesiredSpeedModel> wrappedGenerator = parseDesiredSpeedModel(desiredSpeedModel.getSOCIO());
841 return new Generator<DesiredSpeedModel>()
842 {
843
844
845 @Override
846 public DesiredSpeedModel draw() throws ProbabilityException, ParameterException
847 {
848 return new SocioDesiredSpeed(wrappedGenerator.draw());
849 }
850 };
851 }
852 else if (desiredSpeedModel.getCLASS() != null)
853 {
854 Constructor<? extends DesiredSpeedModel> constructor;
855 try
856 {
857 constructor = ClassUtil.resolveConstructor(desiredSpeedModel.getCLASS(), new Object[0]);
858 }
859 catch (NoSuchMethodException exception)
860 {
861 throw new XmlParserException(
862 "Class " + desiredSpeedModel.getCLASS() + " does not have a valid empty constructor.", exception);
863 }
864 return new Generator<DesiredSpeedModel>()
865 {
866
867 @Override
868 public DesiredSpeedModel draw() throws ProbabilityException, ParameterException
869 {
870 try
871 {
872 return constructor.newInstance();
873 }
874 catch (InstantiationException | IllegalAccessException | IllegalArgumentException
875 | InvocationTargetException exception)
876 {
877 throw new RuntimeException(
878 "Exception while instantiating a desired speed model of class " + desiredSpeedModel.getCLASS(),
879 exception);
880 }
881 }
882 };
883 }
884 else
885 {
886 throw new XmlParserException("Desired speed model has unsupported value.");
887 }
888 }
889
890
891
892
893
894
895
896 @SuppressWarnings("unchecked")
897 private static PerceptionFactory parsePerception(final PERCEPTIONTYPE perception) throws XmlParserException
898 {
899
900 HeadwayGtuType headwayGtuType;
901 if (perception.getHEADWAYGTUTYPE().getWRAP() != null)
902 {
903 headwayGtuType = HeadwayGtuType.WRAP;
904 }
905 else if (perception.getHEADWAYGTUTYPE().getPERCEIVED() != null)
906 {
907 PERCEIVED perceived = perception.getHEADWAYGTUTYPE().getPERCEIVED();
908
909 Estimation estimation;
910 switch (perceived.getESTIMATION())
911 {
912 case "NONE":
913 estimation = Estimation.NONE;
914 break;
915 case "UNDERESTIMATION":
916 estimation = Estimation.UNDERESTIMATION;
917 break;
918 case "OVERESTIMATION":
919 estimation = Estimation.OVERESTIMATION;
920 break;
921 default:
922 throw new XmlParserException("Estimation " + perceived.getESTIMATION() + " is unknown.");
923 }
924
925 Anticipation anticipation;
926 switch (perceived.getANTICIPATION())
927 {
928 case "NONE":
929 anticipation = Anticipation.NONE;
930 break;
931 case "CONSTANTSPEED":
932 anticipation = Anticipation.CONSTANT_SPEED;
933 break;
934 case "CONSTANTACCELERATON":
935 anticipation = Anticipation.CONSTANT_ACCELERATION;
936 break;
937 default:
938 throw new XmlParserException("Anticipation " + perceived.getANTICIPATION() + " is unknown.");
939 }
940 headwayGtuType = new PerceivedHeadwayGtuType(estimation, anticipation);
941 }
942 else
943 {
944 throw new XmlParserException("HeadwayGtuType is unknown.");
945 }
946
947
948 List<Constructor<? extends PerceptionCategory>> categoryConstructorsPerception = new ArrayList<>();
949 List<Constructor<? extends PerceptionCategory>> categoryConstructorsPerceptionHeadway = new ArrayList<>();
950 Class<?>[] perceptionConstructor = new Class[] {LanePerception.class};
951 Class<?>[] perceptionHeadwayConstructor = new Class[] {LanePerception.class, HeadwayGtuType.class};
952 for (CATEGORY category : perception.getCATEGORY())
953 {
954 try
955 {
956 switch (category.getValue())
957 {
958 case "EGO":
959 Constructor<DirectEgoPerception> c =
960 ClassUtil.resolveConstructor(DirectEgoPerception.class, new Class[] {Perception.class});
961 categoryConstructorsPerception.add(c);
962 break;
963 case "BUSSTOP":
964 categoryConstructorsPerception
965 .add(ClassUtil.resolveConstructor(DirectBusStopPerception.class, perceptionConstructor));
966 break;
967 case "INFRASTRUCTURE":
968 categoryConstructorsPerception
969 .add(ClassUtil.resolveConstructor(DirectInfrastructurePerception.class, perceptionConstructor));
970 break;
971 case "INTERSECTION":
972 categoryConstructorsPerceptionHeadway.add(
973 ClassUtil.resolveConstructor(DirectIntersectionPerception.class, perceptionHeadwayConstructor));
974 break;
975 case "NEIGHBORS":
976 categoryConstructorsPerceptionHeadway.add(
977 ClassUtil.resolveConstructor(DirectNeighborsPerception.class, perceptionHeadwayConstructor));
978 break;
979 case "TRAFFIC":
980 categoryConstructorsPerception
981 .add(ClassUtil.resolveConstructor(AnticipationTrafficPerception.class, perceptionConstructor));
982 break;
983 case "CLASS":
984 Constructor<? extends PerceptionCategory<?, ?>> constructor;
985 try
986 {
987 constructor = ClassUtil.resolveConstructor(category.getCLASS(), perceptionHeadwayConstructor);
988 categoryConstructorsPerceptionHeadway.add(constructor);
989 }
990 catch (NoSuchMethodException exception)
991 {
992 constructor = ClassUtil.resolveConstructor(category.getCLASS(), perceptionConstructor);
993 categoryConstructorsPerception.add(constructor);
994 }
995 catch (NullPointerException exception)
996 {
997 throw new XmlParserException(
998 "Perception category defined with value CLASS but no class is specified.", exception);
999 }
1000 break;
1001 default:
1002 throw new XmlParserException("Perception category " + category.getValue() + " is unknown.");
1003 }
1004 }
1005 catch (NoSuchMethodException | ClassCastException exception)
1006 {
1007 throw new XmlParserException(
1008 "Unexpected problem while resolving constructor for perception category " + category.getValue());
1009 }
1010 }
1011
1012
1013 Mental mental;
1014 if (perception.getMENTAL().getFULLER() != null)
1015 {
1016 FULLER fuller = perception.getMENTAL().getFULLER();
1017
1018
1019 Set<Task> tasks = new LinkedHashSet<>();
1020 for (Class<?> taskClass : fuller.getTASK())
1021 {
1022 try
1023 {
1024 tasks.add((Task) ClassUtil.resolveConstructor(taskClass, new Class<?>[0]).newInstance());
1025 }
1026 catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
1027 | NoSuchMethodException exception)
1028 {
1029 throw new XmlParserException(
1030 "Could not instantiate task of class " + taskClass + " through an empty constructor.", exception);
1031 }
1032 }
1033
1034
1035 Set<BehavioralAdaptation> behavioralAdapatations = new LinkedHashSet<>();
1036 for (BEHAVIORALADAPTATION behavioralAdaptation : fuller.getBEHAVIORALADAPTATION())
1037 {
1038 switch (behavioralAdaptation.getValue())
1039 {
1040 case "SITUATIONALAWARENESS":
1041 behavioralAdapatations.add(new AdaptationSituationalAwareness());
1042 break;
1043 case "HEADWAY":
1044 behavioralAdapatations.add(new AdaptationHeadway());
1045 break;
1046 case "SPEED":
1047 behavioralAdapatations.add(new AdaptationSpeed());
1048 break;
1049 case "CLASS":
1050 try
1051 {
1052 behavioralAdapatations.add((BehavioralAdaptation) ClassUtil
1053 .resolveConstructor(behavioralAdaptation.getCLASS(), new Object[0]).newInstance());
1054 }
1055 catch (NullPointerException exception)
1056 {
1057 throw new XmlParserException(
1058 "Behavioral adpatation defined with value CLASS but no class is specified.", exception);
1059 }
1060 catch (InstantiationException | IllegalAccessException | IllegalArgumentException
1061 | InvocationTargetException | NoSuchMethodException exception)
1062 {
1063 throw new XmlParserException("Unable to instantiate class " + behavioralAdaptation.getCLASS()
1064 + " through an empty constructor.", exception);
1065 }
1066 break;
1067 default:
1068 throw new XmlParserException(
1069 "Behavioral adapatation " + behavioralAdaptation.getValue() + " is unknown.");
1070 }
1071 }
1072
1073
1074 TaskManager taskManager;
1075 if (fuller.getTASKMANAGER() == null)
1076 {
1077 taskManager = null;
1078 }
1079 else
1080 {
1081 switch (fuller.getTASKMANAGER())
1082 {
1083 case "SUMMATIVE":
1084 taskManager = new SummativeTaskManager();
1085 break;
1086 case "ANTICIPATIONRELIANCE":
1087
1088 throw new XmlParserException("Task manager ANTICIPATIONRELIANCE is not yet supported.");
1089 default:
1090 throw new XmlParserException("Task manager " + fuller.getTASKMANAGER() + " is unknown.");
1091 }
1092 }
1093
1094
1095 mental = new Fuller(tasks, behavioralAdapatations, taskManager);
1096 }
1097 else
1098 {
1099 mental = null;
1100 }
1101
1102
1103 return new PerceptionFactory()
1104 {
1105
1106 @Override
1107 public Parameters getParameters() throws ParameterException
1108 {
1109
1110 return new ParameterSet();
1111 }
1112
1113
1114 @Override
1115 public LanePerception generatePerception(final LaneBasedGTU gtu)
1116 {
1117 CategoricalLanePerception lanePerception = new CategoricalLanePerception(gtu, mental);
1118 try
1119 {
1120 for (Constructor<? extends PerceptionCategory> constructor : categoryConstructorsPerception)
1121 {
1122 lanePerception.addPerceptionCategory(constructor.newInstance(lanePerception));
1123 }
1124 for (Constructor<? extends PerceptionCategory> constructor : categoryConstructorsPerceptionHeadway)
1125 {
1126 lanePerception.addPerceptionCategory(constructor.newInstance(lanePerception, headwayGtuType));
1127 }
1128 }
1129 catch (InvocationTargetException | InstantiationException | IllegalAccessException
1130 | IllegalArgumentException exception)
1131 {
1132 throw new RuntimeException("Exception while creating new instance of perception category.", exception);
1133 }
1134 return lanePerception;
1135 }
1136 };
1137 }
1138 }