1 package org.opentrafficsim.road.gtu.tactical.lmrs;
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.Map.Entry;
9 import java.util.Optional;
10 import java.util.Set;
11 import java.util.function.BiFunction;
12 import java.util.function.Function;
13 import java.util.function.Supplier;
14 import java.util.stream.Collectors;
15 import java.util.stream.Stream;
16
17 import org.djunits.unit.SpeedUnit;
18 import org.djunits.value.vdouble.scalar.Duration;
19 import org.djunits.value.vdouble.scalar.Length;
20 import org.djunits.value.vdouble.scalar.Speed;
21 import org.djutils.exceptions.Throw;
22 import org.djutils.exceptions.Try;
23 import org.opentrafficsim.base.OtsRuntimeException;
24 import org.opentrafficsim.base.logger.Logger;
25 import org.opentrafficsim.base.parameters.ParameterException;
26 import org.opentrafficsim.base.parameters.ParameterSet;
27 import org.opentrafficsim.base.parameters.ParameterTypes;
28 import org.opentrafficsim.base.parameters.Parameters;
29 import org.opentrafficsim.core.definitions.DefaultsNl;
30 import org.opentrafficsim.core.gtu.GtuException;
31 import org.opentrafficsim.core.gtu.GtuType;
32 import org.opentrafficsim.core.gtu.Stateless;
33 import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
34 import org.opentrafficsim.core.parameters.ParameterFactoryOneShot;
35 import org.opentrafficsim.core.units.distributions.ContinuousDistSpeed;
36 import org.opentrafficsim.road.gtu.LaneBasedGtu;
37 import org.opentrafficsim.road.gtu.perception.CategoricalLanePerception;
38 import org.opentrafficsim.road.gtu.perception.LanePerception;
39 import org.opentrafficsim.road.gtu.perception.categories.AnticipationTrafficPerception;
40 import org.opentrafficsim.road.gtu.perception.categories.DirectInfrastructurePerception;
41 import org.opentrafficsim.road.gtu.perception.categories.DirectIntersectionPerception;
42 import org.opentrafficsim.road.gtu.perception.categories.neighbors.Anticipation;
43 import org.opentrafficsim.road.gtu.perception.categories.neighbors.DirectNeighborsPerception;
44 import org.opentrafficsim.road.gtu.perception.categories.neighbors.Estimation;
45 import org.opentrafficsim.road.gtu.perception.categories.neighbors.PerceivedGtuType;
46 import org.opentrafficsim.road.gtu.perception.categories.neighbors.PerceivedGtuType.AnticipationPerceivedGtuType;
47 import org.opentrafficsim.road.gtu.perception.mental.AdaptationHeadway;
48 import org.opentrafficsim.road.gtu.perception.mental.AdaptationLaneChangeDesire;
49 import org.opentrafficsim.road.gtu.perception.mental.AdaptationSituationalAwareness;
50 import org.opentrafficsim.road.gtu.perception.mental.AdaptationSpeed;
51 import org.opentrafficsim.road.gtu.perception.mental.BehavioralAdaptation;
52 import org.opentrafficsim.road.gtu.perception.mental.FactorEstimation;
53 import org.opentrafficsim.road.gtu.perception.mental.Fuller;
54 import org.opentrafficsim.road.gtu.perception.mental.Mental;
55 import org.opentrafficsim.road.gtu.perception.mental.SumFuller;
56 import org.opentrafficsim.road.gtu.perception.mental.ar.ArFuller;
57 import org.opentrafficsim.road.gtu.perception.mental.ar.ArTask;
58 import org.opentrafficsim.road.gtu.perception.mental.ar.ArTaskCarFollowing;
59 import org.opentrafficsim.road.gtu.perception.mental.ar.ArTaskCarFollowingExp;
60 import org.opentrafficsim.road.gtu.perception.mental.ar.ArTaskLaneChanging;
61 import org.opentrafficsim.road.gtu.perception.mental.ar.ArTaskLaneChangingD;
62 import org.opentrafficsim.road.gtu.perception.mental.ar.ArTaskRoadSideDistraction;
63 import org.opentrafficsim.road.gtu.perception.mental.channel.AdaptationSpeedChannel;
64 import org.opentrafficsim.road.gtu.perception.mental.channel.AdaptationUpdateTime;
65 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelFuller;
66 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelMental;
67 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTask;
68 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskAcceleration;
69 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskCarFollowing;
70 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskCooperation;
71 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskIntersection;
72 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskLaneChange;
73 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskRoadSideDistraction;
74 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskScan;
75 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskSignal;
76 import org.opentrafficsim.road.gtu.perception.mental.channel.ChannelTaskTrafficLight;
77 import org.opentrafficsim.road.gtu.perception.mental.channel.IntersectionPerceptionChannel;
78 import org.opentrafficsim.road.gtu.perception.mental.channel.NeighborsPerceptionChannel;
79 import org.opentrafficsim.road.gtu.tactical.LaneBasedTacticalPlannerFactory;
80 import org.opentrafficsim.road.gtu.tactical.following.AbstractIdm;
81 import org.opentrafficsim.road.gtu.tactical.following.CarFollowingModel;
82 import org.opentrafficsim.road.gtu.tactical.following.DesiredHeadwayModel;
83 import org.opentrafficsim.road.gtu.tactical.following.DesiredSpeedModel;
84 import org.opentrafficsim.road.gtu.tactical.following.Idm;
85 import org.opentrafficsim.road.gtu.tactical.following.IdmPlus;
86 import org.opentrafficsim.road.gtu.tactical.following.IdmPlusMulti;
87 import org.opentrafficsim.road.gtu.tactical.util.ConflictUtil;
88 import org.opentrafficsim.road.gtu.tactical.util.SpeedLimitUtil;
89 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Cooperation;
90 import org.opentrafficsim.road.gtu.tactical.util.lmrs.GapAcceptance;
91 import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsParameters;
92 import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsUtil;
93 import org.opentrafficsim.road.gtu.tactical.util.lmrs.MandatoryIncentive;
94 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Synchronization;
95 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Tailgating;
96 import org.opentrafficsim.road.gtu.tactical.util.lmrs.VoluntaryIncentive;
97 import org.opentrafficsim.road.network.speed.SpeedLimits;
98
99 import nl.tudelft.simulation.jstats.distributions.DistLogNormal;
100 import nl.tudelft.simulation.jstats.distributions.DistNormalTrunc;
101 import nl.tudelft.simulation.jstats.distributions.DistTriangular;
102 import nl.tudelft.simulation.jstats.streams.StreamInterface;
103 import picocli.CommandLine.ITypeConverter;
104 import picocli.CommandLine.Option;
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320 public class LmrsFactory<T extends AbstractIncentivesTacticalPlanner> extends ParameterFactoryOneShot
321 implements LaneBasedTacticalPlannerFactory<T>
322 {
323
324
325 private Map<Setting<?>, List<?>> state;
326
327
328 private StreamInterface stream;
329
330
331 private ContinuousDistSpeed vGainDist;
332
333
334 private DistTriangular sigmaDist;
335
336
337 private DistNormalTrunc fSpeedDist;
338
339
340 private DistNormalTrunc fSpeedGtuDist;
341
342
343 private final List<TacticalPlannerProvider<T>> lmrsProvider;
344
345
346 @Option(names = {"--gtuTypes"}, description = "GTU type IDs in order of multi-valued arguments",
347 defaultValue = "NL.CAR|NL.TRUCK", split = "\\|", splitSynopsisLabel = "|")
348 private final List<String> gtuTypes;
349
350
351 private Map<GtuType, CarFollowingModel> peekedCarFollowingModel = new LinkedHashMap<>();
352
353
354
355
356 @Option(names = {"--carFollowingModel"}, description = "Car-following model: IDM, IDM_PLUS or IDM_PLUS_MULTI",
357 defaultValue = "IDM_PLUS", split = "\\|", splitSynopsisLabel = "|", converter = CarFollowingModelConverter.class)
358 private List<BiFunction<DesiredHeadwayModel, DesiredSpeedModel, CarFollowingModel>> carFollowingModel =
359 listOf(IdmPlus::new);
360
361
362 @Option(names = {"--synchronization"},
363 description = "Lane change synchronization: PASSIVE, PASSIVE_MOVING, ALIGN_GAP or ACTIVE", defaultValue = "PASSIVE",
364 split = "\\|", splitSynopsisLabel = "|", converter = SynchronizationConverter.class)
365 private List<Synchronization> synchronization = listOf(Synchronization.PASSIVE);
366
367
368 @Option(names = {"--cooperation"}, description = "Lane change cooperation: PASSIVE, PASSIVE_MOVING or ACTIVE",
369 defaultValue = "PASSIVE", split = "\\|", splitSynopsisLabel = "|", converter = CooperationConverter.class)
370 private List<Cooperation> cooperation = listOf(Cooperation.PASSIVE);
371
372
373 @Option(names = {"--gapAcceptance"}, description = "Lane change gap-acceptance: INFORMED or EGO_HEADWAY",
374 defaultValue = "INFORMED", split = "\\|", splitSynopsisLabel = "|", converter = GapAcceptanceConverter.class)
375 private List<GapAcceptance> gapAcceptance = listOf(GapAcceptance.INFORMED);
376
377
378
379
380 @Option(names = {"--incentiveRoute"}, description = "Mandatory lane change incentive for route", defaultValue = "true",
381 split = "\\|", splitSynopsisLabel = "|", negatable = true)
382 private List<Boolean> incentiveRoute = listOf(true);
383
384
385 @Option(names = {"--incentiveGetInLane"},
386 description = "Mandatory lane change incentive to join slow traffic at split and not block other traffic",
387 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
388 private List<Boolean> incentiveGetInLane = listOf(false);
389
390
391 private List<Set<Supplier<MandatoryIncentive>>> customMandatoryIncentives = listOf(new LinkedHashSet<>());
392
393
394
395
396 @Option(names = {"--incentiveSpeedWithCourtesy"}, description = "Voluntary lane change incentive for speed with courtesy",
397 defaultValue = "true", split = "\\|", splitSynopsisLabel = "|", negatable = true)
398 private List<Boolean> incentiveSpeedWithCourtesy = listOf(true);
399
400
401 @Option(names = {"--incentiveCourtesy"}, description = "Voluntary lane change incentive for cooperative lane changes",
402 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
403 private List<Boolean> incentiveCourtesy = listOf(false);
404
405
406 @Option(names = {"--incentiveQueue"}, description = "Voluntary lane change incentive to join the shortest queue",
407 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
408 private List<Boolean> incentiveQueue = listOf(false);
409
410
411 @Option(names = {"--incentiveStayRight"},
412 description = "Voluntary lane change incentive for trucks to stay in rightmost two lanes", defaultValue = "false",
413 split = "\\|", splitSynopsisLabel = "|", negatable = true)
414 private List<Boolean> incentiveStayRight = listOf(false);
415
416
417 @Option(names = {"--incentiveKeep"}, description = "Voluntary lane change incentive to keep to the slow lane",
418 defaultValue = "true", split = "\\|", splitSynopsisLabel = "|", negatable = true)
419 private List<Boolean> incentiveKeep = listOf(true);
420
421
422 private List<Set<Supplier<VoluntaryIncentive>>> customVoluntaryIncentives = listOf(new LinkedHashSet<>());
423
424
425
426
427 @Option(names = {"--accelerationSpeedLimitTransition"},
428 description = "Acceleration incentive to slow down prior to a lower speed limit", defaultValue = "false",
429 split = "\\|", splitSynopsisLabel = "|", negatable = true)
430 private List<Boolean> accelerationSpeedLimitTransition = listOf(false);
431
432
433 @Option(names = {"--accelerationTrafficLights"}, description = "Acceleration incentive to approach traffic lights",
434 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
435 private List<Boolean> accelerationTrafficLights = listOf(false);
436
437
438 @Option(names = {"--accelerationConflicts"}, description = "Acceleration incentive to approach intersection conflicts",
439 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
440 private List<Boolean> accelerationConflicts = listOf(false);
441
442
443 @Option(names = {"--accelerationNoSlowLaneOvertake"},
444 description = "Acceleration incentive to not overtake traffic on the slow lane", defaultValue = "false",
445 split = "\\|", splitSynopsisLabel = "|", negatable = true)
446 private List<Boolean> accelerationNoSlowLaneOvertake = listOf(false);
447
448
449 private List<Set<Supplier<AccelerationIncentive>>> customAccelerationIncentives = listOf(new LinkedHashSet<>());
450
451
452
453
454 @Option(names = {"--fullerImplementation"},
455 description = "Implementation of Fuller: NONE, SUMMATIVE, ANTICIPATION_RELIANCE or ATTENTION_MATRIX",
456 defaultValue = "ATTENTION_MATRIX", split = "\\|", splitSynopsisLabel = "|")
457 private List<FullerImplementation> fullerImplementation = listOf(FullerImplementation.NONE);
458
459
460 @Option(names = {"--primaryTask"}, description = "ID of primary task under ANTICIPATION_RELIANCE",
461 defaultValue = "lane-changing", split = "\\|", splitSynopsisLabel = "|")
462 private List<String> primaryTask = listOf("lane-changing");
463
464
465 @Option(names = {"--anticipation"}, description = "Enables temporal constant-speed anticipation", defaultValue = "true",
466 split = "\\|", splitSynopsisLabel = "|", negatable = true)
467 private List<Boolean> temporalAnticipation = listOf(true);
468
469
470 @Option(names = {"--estimation"}, description = "Enables estimation of neighboring vehicles", defaultValue = "true",
471 split = "\\|", splitSynopsisLabel = "|", negatable = true)
472 private List<Boolean> neighborEstimation = listOf(true);
473
474
475 @Option(names = {"--fractionOverEstimation"}, description = "Fraction of drivers over-estimating speed and distance [0..1]",
476 defaultValue = "0.0", split = "\\|", splitSynopsisLabel = "|")
477 private List<Double> fractionOverEstimation = listOf(1.0);
478
479
480
481
482 @Option(names = {"--carFollowingTask"}, description = "Enables car-following task", defaultValue = "true", split = "\\|",
483 splitSynopsisLabel = "|", negatable = true)
484 private List<Boolean> carFollowingTask = listOf(true);
485
486
487 @Option(names = {"--alternateCarFollowingTask"}, description = "Enables alternate car-following task (exponential)",
488 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
489 private List<Boolean> alternateCarFollowingTask = listOf(false);
490
491
492 @Option(names = {"--freeAccelerationTask"},
493 description = "Enables free acceleration task, useful when updateTimeAdaptation is true", defaultValue = "false",
494 split = "\\|", splitSynopsisLabel = "|", negatable = true)
495 private List<Boolean> freeAccelerationTask = listOf(false);
496
497
498 @Option(names = {"--trafficLightsTask"}, description = "Enables traffic light task", defaultValue = "false", split = "\\|",
499 splitSynopsisLabel = "|", negatable = true)
500 private List<Boolean> trafficLightsTask = listOf(false);
501
502
503 @Option(names = {"--signalTask"}, description = "Enables signal task", defaultValue = "true", split = "\\|",
504 splitSynopsisLabel = "|", negatable = true)
505 private List<Boolean> signalTask = listOf(true);
506
507
508 @Option(names = {"--laneChangingTask"}, description = "Enables lane-change task", defaultValue = "true", split = "\\|",
509 splitSynopsisLabel = "|", negatable = true)
510 private List<Boolean> laneChangingTask = listOf(true);
511
512
513 @Option(names = {"--alternateLaneChangingTask"}, description = "Enables alternate lane-changing task (lane change desire)",
514 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
515 private List<Boolean> alternateLaneChangingTask = listOf(false);
516
517
518 @Option(names = {"--cooperationTask"}, description = "Enables cooperation task", defaultValue = "true", split = "\\|",
519 splitSynopsisLabel = "|", negatable = true)
520 private List<Boolean> cooperationTask = listOf(true);
521
522
523 @Option(names = {"--intersectionTask"}, description = "Enables intersection task", defaultValue = "false", split = "\\|",
524 splitSynopsisLabel = "|", negatable = true)
525 private List<Boolean> intersectionTask = listOf(false);
526
527
528 @Option(names = {"--roadSideDistractionTask"}, description = "Enables road-side distraction task", defaultValue = "false",
529 split = "\\|", splitSynopsisLabel = "|", negatable = true)
530 private List<Boolean> roadSideDistractionTask = listOf(false);
531
532
533
534
535 @Option(names = {"--speedAdaptation"}, description = "Enables behavioral speed adaptation", defaultValue = "true",
536 split = "\\|", splitSynopsisLabel = "|", negatable = true)
537 private List<Boolean> speedAdaptation = listOf(true);
538
539
540 @Option(names = {"--headwayAdaptation"}, description = "Enables behavioral headway adaptation", defaultValue = "true",
541 split = "\\|", splitSynopsisLabel = "|", negatable = true)
542 private List<Boolean> headwayAdaptation = listOf(true);
543
544
545 @Option(names = {"--laneChangeAdaptation"}, description = "Enables behavioral voluntary lane change adaptation",
546 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
547 private List<Boolean> laneChangeAdaptation = listOf(false);
548
549
550 @Option(names = {"--updateTimeAdaptation"}, description = "Enables behavioral update time adaptation",
551 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
552 private List<Boolean> updateTimeAdaptation = listOf(false);
553
554
555
556
557 @Option(names = {"--socialPressure"}, description = "Enables social pressure exerted to the (potential) leader",
558 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
559 private List<Boolean> socialPressure = listOf(false);
560
561
562 @Option(names = {"--tailgating"}, description = "Enables tailgating due to social pressure towards the leader",
563 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
564 private List<Boolean> tailgating = listOf(false);
565
566
567 @Option(names = {"--socioLaneChange"},
568 description = "Enables lane changes due to social pressure from the (potential) follower", defaultValue = "false",
569 split = "\\|", splitSynopsisLabel = "|", negatable = true)
570 private List<Boolean> socioLaneChange = listOf(false);
571
572
573 @Option(names = {"--socioSpeed"}, description = "Enables speed increase due to social pressure from the follower",
574 defaultValue = "false", split = "\\|", splitSynopsisLabel = "|", negatable = true)
575 private List<Boolean> socioSpeed = listOf(false);
576
577
578 private final Map<String, Set<GtuType>> noPressureWarningGiven = new LinkedHashMap<>();
579
580
581
582
583
584
585
586 @SafeVarargs
587 private static <V> List<V> listOf(final V... values)
588 {
589 return Stream.of(values).collect(Collectors.toCollection(ArrayList::new));
590 }
591
592
593
594
595
596
597 public LmrsFactory(final TacticalPlannerProvider<T> lmrsProvider)
598 {
599 this(List.of(DefaultsNl.CAR, DefaultsNl.TRUCK), lmrsProvider);
600 }
601
602
603
604
605
606
607
608 public LmrsFactory(final List<GtuType> gtuTypes, final TacticalPlannerProvider<T> lmrsProvider)
609 {
610 Throw.whenNull(gtuTypes, "gtuTypes");
611 Throw.whenNull(lmrsProvider, "lmrsProvider");
612 this.gtuTypes = gtuTypes.stream().map((g) -> g.getId()).collect(Collectors.toCollection(ArrayList::new));
613 this.lmrsProvider = listOf(lmrsProvider);
614 }
615
616
617
618
619
620
621
622
623
624 public LmrsFactory(final List<GtuType> gtuTypes, final List<TacticalPlannerProvider<T>> lmrsProviders)
625 {
626 Throw.whenNull(gtuTypes, "gtuTypes");
627 Throw.whenNull(lmrsProviders, "lmrsProviders");
628 Throw.when(gtuTypes.size() != lmrsProviders.size(), IllegalArgumentException.class,
629 "gtuTypes and lmrsProviders are not of equal size");
630 this.gtuTypes = gtuTypes.stream().map((g) -> g.getId()).collect(Collectors.toList());
631 this.lmrsProvider = new ArrayList<>(lmrsProviders);
632 }
633
634
635
636
637
638
639 @Override
640 public void setOneShotMode()
641 {
642 super.setOneShotMode();
643 this.state = new LinkedHashMap<>();
644 }
645
646
647
648
649
650 @SuppressWarnings("unchecked")
651 protected <V> void resetState()
652 {
653
654 if (this.state == null)
655 {
656 return;
657 }
658 for (Entry<Setting<?>, List<?>> entry : this.state.entrySet())
659 {
660 List<V> values = (List<V>) entry.getKey().getListFunction().apply(this);
661 values.clear();
662 values.addAll((List<V>) entry.getValue());
663 }
664 this.state = null;
665 }
666
667
668
669
670
671
672 @SuppressWarnings("hiddenfield")
673 public LmrsFactory<T> setStream(final StreamInterface stream)
674 {
675 this.stream = stream;
676 this.vGainDist = new ContinuousDistSpeed(new DistLogNormal(stream, 3.379, 0.4), SpeedUnit.KM_PER_HOUR);
677 this.sigmaDist = new DistTriangular(stream, 0.0, 0.25, 1.0);
678 this.fSpeedDist = new DistNormalTrunc(stream, 123.7 / 120.0, 0.1, 0.8, 50.0);
679 this.fSpeedGtuDist = new DistNormalTrunc(stream, 85.0 / 80.0, 2.5 / 80.0, 0.8, 50.0);
680 return this;
681 }
682
683
684
685
686
687
688
689
690 public <V> LmrsFactory<T> set(final Setting<V> setting, final V value)
691 {
692 Throw.whenNull(value, "value");
693 final List<V> values = setting.getListFunction().apply(this);
694 saveState(setting, values);
695 values.clear();
696 values.add(value);
697 return this;
698 }
699
700
701
702
703
704
705
706
707
708
709 public <V> LmrsFactory<T> set(final Setting<V> setting, final V value, final GtuType gtuType)
710 {
711 Throw.whenNull(value, "value");
712 Throw.whenNull(gtuType, "gtuType");
713
714 int gtuTypeIndex = this.gtuTypes.indexOf(gtuType.getId());
715 Throw.when(gtuTypeIndex < 0, IllegalArgumentException.class, "GTU type %s not defined.", gtuType.getId());
716
717 final List<V> values = setting.getListFunction().apply(this);
718 saveState(setting, values);
719
720
721
722
723
724
725
726 while (values.size() < this.gtuTypes.size())
727 {
728 values.add(null);
729 }
730 values.set(gtuTypeIndex, value);
731 return this;
732 }
733
734
735
736
737
738
739
740 protected <V> void saveState(final Setting<V> setting, final List<V> values)
741 {
742 if (this.state != null && !this.state.containsKey(setting))
743 {
744 this.state.put(setting, new ArrayList<>(values));
745 }
746 }
747
748
749
750
751
752
753
754
755
756 protected <V> V get(final Setting<V> setting, final GtuType gtuType)
757 {
758 return get(setting.getListFunction().apply(this), gtuType, gtuType);
759 }
760
761
762
763
764
765
766
767
768 protected <V> V get(final List<V> values, final GtuType gtuType)
769 {
770 return get(values, gtuType, gtuType);
771 }
772
773
774
775
776
777
778
779
780
781 private <V> V get(final List<V> values, final GtuType gtuType, final GtuType originalGtuType)
782 {
783 Throw.when(values.size() > 1 && this.gtuTypes.size() > values.size(), IllegalArgumentException.class,
784 "Argument has %s values %s but %s GTU types are defined.", values.size(), values, this.gtuTypes.size());
785 if (values.size() == 1)
786 {
787 return values.get(0);
788 }
789 int index = this.gtuTypes.indexOf(gtuType.getId());
790 if (index < 0 || values.get(index) == null)
791 {
792 return get(values,
793 gtuType.getParent().orElseThrow(() -> new IllegalArgumentException(
794 "Unable to obtain setting value for GTU type " + originalGtuType.getId() + " or any parent.")),
795 originalGtuType);
796 }
797 return values.get(index);
798 }
799
800
801
802
803
804
805 private CarFollowingModel peekCarFollowingModel(final GtuType gtuType)
806 {
807 return this.peekedCarFollowingModel.computeIfAbsent(gtuType, (gt) ->
808 {
809 DesiredSpeedModel desiredSpeedModel = get(this.socioSpeed, gtuType)
810 ? new SocioDesiredSpeed(AbstractIdm.DESIRED_SPEED) : AbstractIdm.DESIRED_SPEED;
811 return get(this.carFollowingModel, gtuType).apply(AbstractIdm.HEADWAY, desiredSpeedModel);
812 });
813 }
814
815 @Override
816 public Optional<Speed> peekDesiredSpeed(final GtuType gtuType, final SpeedLimits speedLimits, final Speed maxVehicleSpeed,
817 final Parameters parameters) throws GtuException
818 {
819 return Try.assign(
820 () -> Optional.of(peekCarFollowingModel(gtuType).desiredSpeed(parameters, speedLimits, maxVehicleSpeed)),
821 IllegalStateException.class, "Parameter for desired speed missing.");
822 }
823
824 @Override
825 public Optional<Length> peekDesiredHeadway(final GtuType gtuType, final Speed speed, final Parameters parameters)
826 throws GtuException
827 {
828 return Try.assign(() -> Optional.of(peekCarFollowingModel(gtuType).desiredHeadway(parameters, speed)),
829 IllegalStateException.class, "Parameter for desired headway missing.");
830 }
831
832 @Override
833 public Parameters getParameters(final GtuType gtuType) throws ParameterException
834 {
835 ParameterSet parameters = new ParameterSet();
836 parameters.setDefaultParameters(LmrsUtil.class);
837 parameters.setDefaultParameters(LmrsParameters.class);
838 parameters.setDefaultParameters(AbstractIdm.class);
839 parameters.setDefaultParameters(ConflictUtil.class);
840 parameters.setDefaultParameter(ParameterTypes.T0);
841 parameters.setDefaultParameter(ParameterTypes.LC_INFO);
842 parameters.setDefaultParameter(ParameterTypes.LOOKBACK);
843 parameters.setDefaultParameter(ParameterTypes.LOOKAHEAD);
844 parameters.setDefaultParameter(ParameterTypes.VCONG);
845 parameters.setDefaultParameter(ParameterTypes.LCDUR);
846 if (IdmPlusMultiFunction.SINGLETON.equals(get(this.carFollowingModel, gtuType)))
847 {
848 parameters.setDefaultParameter(IdmPlusMulti.NLEADERS);
849 }
850 if (get(this.accelerationSpeedLimitTransition, gtuType))
851 {
852 parameters.setDefaultParameter(SpeedLimitUtil.A_LAT);
853 }
854
855
856 if (!FullerImplementation.NONE.equals(get(this.fullerImplementation, gtuType)))
857 {
858 parameters.setParameter(ParameterTypes.TR, Duration.ZERO);
859 parameters.setDefaultParameter(AdaptationSituationalAwareness.TR_MAX);
860 parameters.setParameter(ChannelFuller.EST_FACTOR, 1.0);
861 parameters.setParameter(Fuller.OVER_EST,
862 this.stream.nextDouble() <= get(this.fractionOverEstimation, gtuType) ? 1.0 : -1.0);
863 parameters.setDefaultParameter(ChannelTaskScan.TDSCAN);
864 if (get(this.headwayAdaptation, gtuType))
865 {
866 parameters.setDefaultParameter(AdaptationHeadway.BETA_T);
867 }
868 if (get(this.speedAdaptation, gtuType))
869 {
870 parameters.setDefaultParameter(AdaptationSpeed.BETA_V0);
871 }
872
873 if (FullerImplementation.ATTENTION_MATRIX.equals(get(this.fullerImplementation, gtuType)))
874 {
875
876 parameters.setDefaultParameters(ChannelFuller.class);
877 parameters.setDefaultParameters(ChannelMental.class);
878 if (get(this.updateTimeAdaptation, gtuType))
879 {
880 parameters.setDefaultParameter(AdaptationUpdateTime.DT_MIN);
881 parameters.setDefaultParameter(AdaptationUpdateTime.DT_MAX);
882 }
883 if (get(this.carFollowingTask, gtuType))
884 {
885 parameters.setDefaultParameter(ArTaskCarFollowingExp.HEXP);
886 }
887 if (get(this.trafficLightsTask, gtuType) || get(this.intersectionTask, gtuType))
888 {
889 parameters.setDefaultParameter(ChannelTaskIntersection.TD_B);
890 parameters.setDefaultParameter(ChannelTaskIntersection.TD_C);
891 parameters.setDefaultParameter(ChannelTaskIntersection.BETA_YL);
892 parameters.setDefaultParameter(ChannelTaskIntersection.BETA_CON);
893 }
894 if (get(this.signalTask, gtuType))
895 {
896 parameters.setDefaultParameter(ChannelTaskSignal.TDSIGNAL);
897 }
898 }
899 else
900 {
901
902 parameters.setDefaultParameters(Fuller.class);
903 parameters.setDefaultParameters(SumFuller.class);
904 parameters.setDefaultParameter(AdaptationSituationalAwareness.SA);
905 parameters.setDefaultParameter(AdaptationSituationalAwareness.SA_MIN);
906 parameters.setDefaultParameter(AdaptationSituationalAwareness.SA_MAX);
907 if (FullerImplementation.ANTICIPATION_RELIANCE.equals(get(this.fullerImplementation, gtuType)))
908 {
909 parameters.setDefaultParameter(ArFuller.ALPHA);
910 parameters.setDefaultParameter(ArFuller.BETA);
911 }
912 if (get(this.alternateCarFollowingTask, gtuType))
913 {
914 parameters.setDefaultParameter(ArTaskCarFollowingExp.HEXP);
915 }
916 }
917
918 }
919
920
921 parameters.setDefaultParameter(Tailgating.RHO);
922
923 if (get(this.tailgating, gtuType))
924 {
925 if (!get(this.socialPressure, gtuType) && giveWarning("tailgating", gtuType))
926 {
927 Logger.ots().warn(
928 "Tailgating is enabled for {} but likely ineffective as social pressure is currently disabled.",
929 gtuType);
930 }
931 parameters.setDefaultParameter(Tailgating.DEV_RHO);
932 parameters.setParameter(ParameterTypes.TMAX, Duration.ofSI(1.6));
933 }
934 boolean socioLc = get(this.socioLaneChange, gtuType);
935 boolean socioV = get(this.socioSpeed, gtuType);
936 if (socioLc || socioV)
937 {
938 if (socioLc && !this.socialPressure.contains(true) && giveWarning("socioLc", gtuType))
939 {
940 Logger.ots().warn("SocioLaneChange is enabled for {} but likely ineffective as"
941 + " social pressure is currently disabled for all GTU types.", gtuType);
942 }
943 if (socioV && !this.socialPressure.contains(true) && giveWarning("socioV", gtuType))
944 {
945 Logger.ots().warn("SocioSpeed is enabled for {} but likely ineffective as"
946 + " social pressure is currently disabled for all GTU types.", gtuType);
947 }
948 parameters.setParameter(LmrsParameters.VGAIN, this.vGainDist.get());
949 parameters.setParameter(LmrsParameters.SOCIO, this.sigmaDist.draw());
950 }
951 parameters.setParameter(ParameterTypes.FSPEED, this.fSpeedDist.draw());
952 parameters.setParameter(ParameterTypes.FSPEED_GTU, this.fSpeedGtuDist.draw());
953 return parameters;
954 }
955
956 @Override
957 public T create(final LaneBasedGtu gtu) throws GtuException
958 {
959 GtuType gtuType = gtu.getType();
960
961
962 CarFollowingModel cfModel = peekCarFollowingModel(gtuType);
963 this.peekedCarFollowingModel.remove(gtuType);
964
965
966 LanePerception perception = getPerception(gtu);
967
968
969 Synchronization sync = get(this.synchronization, gtuType);
970 Cooperation coop = get(this.cooperation, gtuType);
971 GapAcceptance gapAccept = get(this.gapAcceptance, gtuType);
972 Tailgating tail = !get(this.socialPressure, gtuType) ? Tailgating.NONE
973 : (get(this.tailgating, gtuType) ? Tailgating.PRESSURE : Tailgating.RHO_ONLY);
974 T tacticalPlanner = get(this.lmrsProvider, gtuType).from(cfModel, gtu, perception, sync, coop, gapAccept, tail);
975
976
977 if (get(this.incentiveRoute, gtuType))
978 {
979 tacticalPlanner.addMandatoryIncentive(IncentiveRoute.SINGLETON);
980 }
981 if (get(this.incentiveGetInLane, gtuType))
982 {
983 tacticalPlanner.addMandatoryIncentive(IncentiveGetInLane.SINGLETON);
984 }
985 get(this.customMandatoryIncentives, gtuType).forEach((s) -> tacticalPlanner.addMandatoryIncentive(s.get()));
986
987
988 if (get(this.incentiveSpeedWithCourtesy, gtuType))
989 {
990 tacticalPlanner.addVoluntaryIncentive(IncentiveSpeedWithCourtesy.SINGLETON);
991 }
992 if (get(this.incentiveCourtesy, gtuType))
993 {
994 tacticalPlanner.addVoluntaryIncentive(IncentiveCourtesy.SINGLETON);
995 }
996 if (get(this.incentiveQueue, gtuType))
997 {
998 tacticalPlanner.addVoluntaryIncentive(IncentiveQueue.SINGLETON);
999 }
1000 if (get(this.incentiveStayRight, gtuType))
1001 {
1002 tacticalPlanner.addVoluntaryIncentive(IncentiveStayOnSlowLanes.SINGLETON);
1003 }
1004 if (get(this.incentiveKeep, gtuType))
1005 {
1006 tacticalPlanner.addVoluntaryIncentive(IncentiveKeep.SINGLETON);
1007 }
1008 if (get(this.socioLaneChange, gtuType))
1009 {
1010 tacticalPlanner.addVoluntaryIncentive(IncentiveSocioSpeed.SINGLETON);
1011 }
1012 get(this.customVoluntaryIncentives, gtuType).forEach((s) -> tacticalPlanner.addVoluntaryIncentive(s.get()));
1013
1014
1015 if (get(this.accelerationSpeedLimitTransition, gtuType))
1016 {
1017 tacticalPlanner.addAccelerationIncentive(AccelerationSpeedTransition.SINGLETON);
1018 }
1019 if (get(this.accelerationTrafficLights, gtuType))
1020 {
1021 tacticalPlanner.addAccelerationIncentive(AccelerationTrafficLights.SINGLETON);
1022 }
1023 if (get(this.accelerationConflicts, gtuType))
1024 {
1025 tacticalPlanner.addAccelerationIncentive(new AccelerationConflicts());
1026 }
1027 if (get(this.accelerationNoSlowLaneOvertake, gtuType))
1028 {
1029 tacticalPlanner.addAccelerationIncentive(
1030 new AccelerationNoSlowLaneOvertake(() -> tacticalPlanner.getLatestMandatoryDesire()));
1031 }
1032 get(this.customAccelerationIncentives, gtuType).forEach((s) -> tacticalPlanner.addAccelerationIncentive(s.get()));
1033
1034
1035 if (gtu.getBookkeeping().isEdge())
1036 {
1037 tacticalPlanner.addAccelerationIncentive(AccelerationLaneChangers.SINGLETON);
1038 }
1039
1040 resetState();
1041
1042 return tacticalPlanner;
1043 }
1044
1045
1046
1047
1048
1049
1050
1051 private boolean giveWarning(final String key, final GtuType gtuType)
1052 {
1053 return this.noPressureWarningGiven.computeIfAbsent(key, (k) -> new LinkedHashSet<>()).add(gtuType);
1054 }
1055
1056
1057
1058
1059
1060
1061 protected LanePerception getPerception(final LaneBasedGtu gtu)
1062 {
1063 GtuType gtuType = gtu.getType();
1064
1065 Mental mental;
1066 Estimation estimation;
1067 Anticipation anticipation;
1068
1069 if (FullerImplementation.ATTENTION_MATRIX.equals(get(this.fullerImplementation, gtuType)))
1070 {
1071
1072 LinkedHashSet<Function<LanePerception, Set<ChannelTask>>> taskSuppliers = new LinkedHashSet<>();
1073 addChannelTask(taskSuppliers, get(this.carFollowingTask, gtuType), ChannelTaskCarFollowing.SUPPLIER);
1074 addChannelTask(taskSuppliers, get(this.freeAccelerationTask, gtuType), ChannelTaskAcceleration.SUPPLIER);
1075 addChannelTask(taskSuppliers, get(this.trafficLightsTask, gtuType), ChannelTaskTrafficLight.SUPPLIER);
1076 addChannelTask(taskSuppliers, get(this.signalTask, gtuType), ChannelTaskSignal.SUPPLIER);
1077 addChannelTask(taskSuppliers, get(this.laneChangingTask, gtuType), ChannelTaskLaneChange.SUPPLIER);
1078 addChannelTask(taskSuppliers, get(this.cooperationTask, gtuType), ChannelTaskCooperation.SUPPLIER);
1079 addChannelTask(taskSuppliers, get(this.intersectionTask, gtuType), ChannelTaskIntersection.SUPPLIER);
1080 addChannelTask(taskSuppliers, get(this.roadSideDistractionTask, gtuType),
1081 new ChannelTaskRoadSideDistraction.Supplier(gtu));
1082 addChannelTask(taskSuppliers, true, ChannelTaskScan.SUPPLIER);
1083
1084
1085 Set<BehavioralAdaptation> behavioralAdapatations = new LinkedHashSet<>();
1086 if (get(this.speedAdaptation, gtuType))
1087 {
1088 behavioralAdapatations.add(new AdaptationSpeedChannel());
1089 }
1090 if (get(this.headwayAdaptation, gtuType))
1091 {
1092 behavioralAdapatations.add(new AdaptationHeadway());
1093 }
1094 if (get(this.laneChangeAdaptation, gtuType))
1095 {
1096 behavioralAdapatations.add(AdaptationLaneChangeDesire.SINGLETON);
1097 }
1098 if (get(this.updateTimeAdaptation, gtuType))
1099 {
1100 behavioralAdapatations.add(AdaptationUpdateTime.SINGLETON);
1101 }
1102
1103 mental = new ChannelFuller(taskSuppliers, behavioralAdapatations);
1104
1105 estimation = get(this.neighborEstimation, gtuType) ? FactorEstimation.SINGLETON : Estimation.NONE;
1106 anticipation = get(this.temporalAnticipation, gtuType) ? Anticipation.CONSTANT_SPEED : Anticipation.NONE;
1107 }
1108 else if (FullerImplementation.NONE.equals(get(this.fullerImplementation, gtuType)))
1109 {
1110 mental = null;
1111 estimation = Estimation.NONE;
1112 anticipation = Anticipation.NONE;
1113 }
1114 else
1115 {
1116
1117 Set<ArTask> tasks = new LinkedHashSet<>();
1118 FullerImplementation fullerImpl = get(this.fullerImplementation, gtuType);
1119
1120
1121 if (get(this.carFollowingTask, gtuType))
1122 {
1123 Throw.when(get(this.alternateCarFollowingTask, gtuType), IllegalStateException.class,
1124 "Both carFollowingTask and alternateCarFollowingTask are true");
1125 tasks.add(ArTaskCarFollowing.SINGLETON);
1126 }
1127 else if (get(this.alternateCarFollowingTask, gtuType))
1128 {
1129 tasks.add(ArTaskCarFollowingExp.SINGLETON);
1130 }
1131 if (get(this.laneChangingTask, gtuType))
1132 {
1133 Throw.when(get(this.alternateLaneChangingTask, gtuType), IllegalStateException.class,
1134 "Both laneChangingTask and alternateLaneChangingTask are true");
1135 tasks.add(ArTaskLaneChanging.SINGLETON);
1136 }
1137 else if (get(this.alternateLaneChangingTask, gtuType))
1138 {
1139 tasks.add(ArTaskLaneChangingD.SINGLETON);
1140 }
1141 if (get(this.roadSideDistractionTask, gtuType))
1142 {
1143 tasks.add(new ArTaskRoadSideDistraction(gtu));
1144 }
1145
1146
1147 Set<BehavioralAdaptation> behavioralAdapatations = new LinkedHashSet<>();
1148 if (get(this.speedAdaptation, gtuType))
1149 {
1150 behavioralAdapatations.add(new AdaptationSpeed());
1151 }
1152 if (get(this.headwayAdaptation, gtuType))
1153 {
1154 behavioralAdapatations.add(new AdaptationHeadway());
1155 }
1156 if (get(this.laneChangeAdaptation, gtuType))
1157 {
1158 behavioralAdapatations.add(AdaptationLaneChangeDesire.SINGLETON);
1159 }
1160 behavioralAdapatations.add(new AdaptationSituationalAwareness());
1161
1162
1163 if (FullerImplementation.SUMMATIVE.equals(fullerImpl))
1164 {
1165 mental = new SumFuller<>(tasks, behavioralAdapatations);
1166 }
1167 else if (FullerImplementation.ANTICIPATION_RELIANCE.equals(fullerImpl))
1168 {
1169 mental = new ArFuller(tasks, behavioralAdapatations, get(this.primaryTask, gtuType));
1170 }
1171 else
1172 {
1173 throw new IllegalArgumentException("Unable to load Fuller model from setting " + fullerImpl);
1174 }
1175
1176 estimation = get(this.neighborEstimation, gtuType) ? FactorEstimation.SINGLETON : Estimation.NONE;
1177 anticipation = get(this.temporalAnticipation, gtuType) ? Anticipation.CONSTANT_SPEED : Anticipation.NONE;
1178 }
1179
1180
1181 LanePerception perception = new CategoricalLanePerception(gtu, mental);
1182 perception.addPerceptionCategory(new DirectEgoPerception<>(perception));
1183 perception.addPerceptionCategory(new DirectInfrastructurePerception(perception));
1184 perception.addPerceptionCategory(new AnticipationTrafficPerception(perception));
1185 if (FullerImplementation.NONE.equals(get(this.fullerImplementation, gtuType)))
1186 {
1187 perception.addPerceptionCategory(new DirectNeighborsPerception(perception, PerceivedGtuType.WRAP));
1188 perception.addPerceptionCategory(new DirectIntersectionPerception(perception, PerceivedGtuType.WRAP));
1189 }
1190 else if (FullerImplementation.ATTENTION_MATRIX.equals(get(this.fullerImplementation, gtuType)))
1191 {
1192 perception.addPerceptionCategory(new NeighborsPerceptionChannel(perception, estimation, anticipation));
1193 perception.addPerceptionCategory(new IntersectionPerceptionChannel(perception, estimation, anticipation));
1194 }
1195 else
1196 {
1197 PerceivedGtuType headwayGtuType = new AnticipationPerceivedGtuType(estimation, anticipation, () ->
1198 {
1199 return gtu.getParameters().getOptionalParameter(ParameterTypes.TR)
1200 .orElseThrow(() -> new OtsRuntimeException("Unable to obtain reaction time parameter"));
1201 });
1202 perception.addPerceptionCategory(new DirectNeighborsPerception(perception, headwayGtuType));
1203 perception.addPerceptionCategory(new DirectIntersectionPerception(perception, headwayGtuType));
1204 }
1205 return perception;
1206 }
1207
1208
1209
1210
1211
1212
1213
1214 private void addChannelTask(final LinkedHashSet<Function<LanePerception, Set<ChannelTask>>> taskSuppliers,
1215 final boolean task, final Function<LanePerception, Set<ChannelTask>> supplier)
1216 {
1217 if (task)
1218 {
1219 taskSuppliers.add(supplier);
1220 }
1221 }
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231 public interface TacticalPlannerProvider<P extends AbstractIncentivesTacticalPlanner>
1232 {
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244 P from(CarFollowingModel carFollowingModel, LaneBasedGtu gtu, LanePerception lanePerception,
1245 Synchronization synchronization, Cooperation cooperation, GapAcceptance gapAcceptance, Tailgating tailgating);
1246 }
1247
1248
1249
1250
1251
1252 public static final class Setting<V>
1253 {
1254
1255
1256
1257 public static final Setting<BiFunction<DesiredHeadwayModel, DesiredSpeedModel, CarFollowingModel>> CAR_FOLLOWING_MODEL =
1258 new Setting<>((factory) -> factory.carFollowingModel);
1259
1260
1261 public static final Setting<Synchronization> SYNCHRONIZATION = new Setting<>((factory) -> factory.synchronization);
1262
1263
1264 public static final Setting<Cooperation> COOPERATION = new Setting<>((factory) -> factory.cooperation);
1265
1266
1267 public static final Setting<GapAcceptance> GAP_ACCEPTANCE = new Setting<>((factory) -> factory.gapAcceptance);
1268
1269
1270
1271
1272 public static final Setting<Boolean> INCENTIVE_ROUTE = new Setting<>((factory) -> factory.incentiveRoute);
1273
1274
1275 public static final Setting<Boolean> INCENTIVE_GET_IN_LANE = new Setting<>((factory) -> factory.incentiveGetInLane);
1276
1277
1278 public static final Setting<Set<Supplier<MandatoryIncentive>>> CUSTOM_MANDATORY_INCENTIVES =
1279 new Setting<>((factory) -> factory.customMandatoryIncentives);
1280
1281
1282
1283
1284 public static final Setting<Boolean> INCENTIVE_SPEED_WITH_COURTESY =
1285 new Setting<>((factory) -> factory.incentiveSpeedWithCourtesy);
1286
1287
1288 public static final Setting<Boolean> INCENTIVE_COURTESY = new Setting<>((factory) -> factory.incentiveCourtesy);
1289
1290
1291 public static final Setting<Boolean> INCENTIVE_QUEUE = new Setting<>((factory) -> factory.incentiveQueue);
1292
1293
1294 public static final Setting<Boolean> INCENTIVE_STAY_ON_SLOW_LANES =
1295 new Setting<>((factory) -> factory.incentiveStayRight);
1296
1297
1298 public static final Setting<Boolean> INCENTIVE_KEEP = new Setting<>((factory) -> factory.incentiveKeep);
1299
1300
1301 public static final Setting<Set<Supplier<VoluntaryIncentive>>> CUSTOM_VOLUNTARY_INCENTIVES =
1302 new Setting<>((factory) -> factory.customVoluntaryIncentives);
1303
1304
1305
1306
1307 public static final Setting<Boolean> ACCELERATION_SPEED_LIMIT_TRANSITION =
1308 new Setting<>((factory) -> factory.accelerationSpeedLimitTransition);
1309
1310
1311 public static final Setting<Boolean> ACCELERATION_TRAFFIC_LIGHTS =
1312 new Setting<>((factory) -> factory.accelerationTrafficLights);
1313
1314
1315 public static final Setting<Boolean> ACCELERATION_CONFLICTS = new Setting<>((factory) -> factory.accelerationConflicts);
1316
1317
1318 public static final Setting<Boolean> ACCELERATION_NO_SLOW_LANE_OVERTAKE =
1319 new Setting<>((factory) -> factory.accelerationNoSlowLaneOvertake);
1320
1321
1322 public static final Setting<Set<Supplier<AccelerationIncentive>>> CUSTOM_ACCELERATION_INCENTIVES =
1323 new Setting<>((factory) -> factory.customAccelerationIncentives);
1324
1325
1326
1327
1328 public static final Setting<FullerImplementation> FULLER_IMPLEMENTATION =
1329 new Setting<>((factory) -> factory.fullerImplementation);
1330
1331
1332 public static final Setting<String> PRIMARY_TASK = new Setting<>((factory) -> factory.primaryTask);
1333
1334
1335 public static final Setting<Boolean> TEMPORAL_ANTICIPATION = new Setting<>((factory) -> factory.temporalAnticipation);
1336
1337
1338 public static final Setting<Boolean> ESTIMATION = new Setting<>((factory) -> factory.neighborEstimation);
1339
1340
1341 public static final Setting<Double> FRACTION_OVERESTIMATION =
1342 new Setting<>((factory) -> factory.fractionOverEstimation);
1343
1344
1345
1346
1347 public static final Setting<Boolean> TASK_CAR_FOLLOWING = new Setting<>((factory) -> factory.carFollowingTask);
1348
1349
1350 public static final Setting<Boolean> TASK_CAR_FOLLOWING_ALTERNATE =
1351 new Setting<>((factory) -> factory.alternateCarFollowingTask);
1352
1353
1354 public static final Setting<Boolean> TASK_FREE_ACCELERATION = new Setting<>((factory) -> factory.freeAccelerationTask);
1355
1356
1357 public static final Setting<Boolean> TASK_TRAFFIC_LIGHTS = new Setting<>((factory) -> factory.trafficLightsTask);
1358
1359
1360 public static final Setting<Boolean> TASK_SIGNAL = new Setting<>((factory) -> factory.signalTask);
1361
1362
1363 public static final Setting<Boolean> TASK_LANE_CHANGE = new Setting<>((factory) -> factory.laneChangingTask);
1364
1365
1366 public static final Setting<Boolean> TASK_LANE_CHANGE_ALTERNATE =
1367 new Setting<>((factory) -> factory.alternateLaneChangingTask);
1368
1369
1370 public static final Setting<Boolean> TASK_COOPERATION = new Setting<>((factory) -> factory.cooperationTask);
1371
1372
1373 public static final Setting<Boolean> TASK_INTERSECTION = new Setting<>((factory) -> factory.intersectionTask);
1374
1375
1376 public static final Setting<Boolean> TASK_ROADSIDE_DISTRACTION =
1377 new Setting<>((factory) -> factory.roadSideDistractionTask);
1378
1379
1380
1381
1382 public static final Setting<Boolean> ADAPTATION_SPEED = new Setting<>((factory) -> factory.speedAdaptation);
1383
1384
1385 public static final Setting<Boolean> ADAPTATION_HEADWAY = new Setting<>((factory) -> factory.headwayAdaptation);
1386
1387
1388 public static final Setting<Boolean> ADAPTATION_LANE_CHANGE = new Setting<>((factory) -> factory.laneChangeAdaptation);
1389
1390
1391 public static final Setting<Boolean> ADAPTATION_UPDATE_TIME = new Setting<>((factory) -> factory.updateTimeAdaptation);
1392
1393
1394
1395
1396 public static final Setting<Boolean> SOCIO_PRESSURE = new Setting<>((factory) -> factory.socialPressure);
1397
1398
1399 public static final Setting<Boolean> SOCIO_TAILGATING = new Setting<>((factory) -> factory.tailgating);
1400
1401
1402 public static final Setting<Boolean> SOCIO_LANE_CHANGE = new Setting<>((factory) -> factory.socioLaneChange);
1403
1404
1405 public static final Setting<Boolean> SOCIO_SPEED = new Setting<>((factory) -> factory.socioSpeed);
1406
1407
1408 private final Function<LmrsFactory<?>, List<V>> listFunction;
1409
1410
1411
1412
1413
1414 private Setting(final Function<LmrsFactory<?>, List<V>> listFunction)
1415 {
1416 this.listFunction = listFunction;
1417 }
1418
1419
1420
1421
1422
1423 public Function<LmrsFactory<?>, List<V>> getListFunction()
1424 {
1425 return this.listFunction;
1426 }
1427 }
1428
1429
1430
1431
1432 public enum FullerImplementation
1433 {
1434
1435 NONE,
1436
1437
1438 SUMMATIVE,
1439
1440
1441
1442
1443
1444 ANTICIPATION_RELIANCE,
1445
1446
1447 ATTENTION_MATRIX;
1448 }
1449
1450
1451
1452
1453 public static class CarFollowingModelConverter
1454 implements ITypeConverter<BiFunction<DesiredHeadwayModel, DesiredSpeedModel, CarFollowingModel>>
1455 {
1456
1457
1458
1459 public CarFollowingModelConverter()
1460 {
1461
1462 }
1463
1464 @Override
1465 public BiFunction<DesiredHeadwayModel, DesiredSpeedModel, CarFollowingModel> convert(final String value)
1466 throws Exception
1467 {
1468 return switch (value.toLowerCase())
1469 {
1470 case "idm" -> Idm::new;
1471 case "idm_plus" -> IdmPlus::new;
1472 case "idm_plus_multi" -> IdmPlusMultiFunction.SINGLETON;
1473 default -> throw new IllegalArgumentException(
1474 "Unable to parse car following model " + value + ". Use any of IDM, IDM_PLUS or IDM_PLUS_MULTI.");
1475 };
1476 }
1477 }
1478
1479
1480
1481
1482 public static final class IdmPlusMultiFunction
1483 implements BiFunction<DesiredHeadwayModel, DesiredSpeedModel, CarFollowingModel>, Stateless<IdmPlusMultiFunction>
1484 {
1485
1486 public static final IdmPlusMultiFunction SINGLETON = new IdmPlusMultiFunction();
1487
1488 @Override
1489 public CarFollowingModel apply(final DesiredHeadwayModel t, final DesiredSpeedModel u)
1490 {
1491 return new IdmPlusMulti(t, u);
1492 }
1493
1494 @Override
1495 public IdmPlusMultiFunction get()
1496 {
1497 return SINGLETON;
1498 }
1499 }
1500
1501
1502
1503
1504 public static class SynchronizationConverter implements ITypeConverter<Synchronization>
1505 {
1506
1507
1508
1509 public SynchronizationConverter()
1510 {
1511
1512 }
1513
1514 @Override
1515 public Synchronization convert(final String value) throws Exception
1516 {
1517 switch (value.toLowerCase())
1518 {
1519 case "passive":
1520 return Synchronization.PASSIVE;
1521 case "passive_moving":
1522 return Synchronization.PASSIVE_MOVING;
1523 case "align_gap":
1524 return Synchronization.ALIGN_GAP;
1525 case "active":
1526 return Synchronization.ACTIVE;
1527 default:
1528 throw new IllegalArgumentException("Unable to parse synchronization " + value
1529 + ". Use any of PASSIVE, PASSIVE_MOVING, ALIGN_GAP or ACTIVE.");
1530 }
1531 }
1532 }
1533
1534
1535
1536
1537 public static class CooperationConverter implements ITypeConverter<Cooperation>
1538 {
1539
1540
1541
1542 public CooperationConverter()
1543 {
1544
1545 }
1546
1547 @Override
1548 public Cooperation convert(final String value) throws Exception
1549 {
1550 switch (value.toLowerCase())
1551 {
1552 case "passive":
1553 return Cooperation.PASSIVE;
1554 case "passive_moving":
1555 return Cooperation.PASSIVE_MOVING;
1556 case "active":
1557 return Cooperation.ACTIVE;
1558 default:
1559 throw new IllegalArgumentException(
1560 "Unable to parse cooperation " + value + ". Use any of PASSIVE, PASSIVE_MOVING or ACTIVE.");
1561 }
1562 }
1563 }
1564
1565
1566
1567
1568 public static class GapAcceptanceConverter implements ITypeConverter<GapAcceptance>
1569 {
1570
1571
1572
1573 public GapAcceptanceConverter()
1574 {
1575
1576 }
1577
1578 @Override
1579 public GapAcceptance convert(final String value) throws Exception
1580 {
1581 switch (value.toLowerCase())
1582 {
1583 case "informed":
1584 return GapAcceptance.INFORMED;
1585 case "ego_headway":
1586 return GapAcceptance.EGO_HEADWAY;
1587 default:
1588 throw new IllegalArgumentException(
1589 "Unable to parse gap-acceptance " + value + ". Use any of INFORMED or EGO_HEADWAY.");
1590 }
1591 }
1592 }
1593
1594 }