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