1 package org.opentrafficsim.road.gtu.lane.perception.mental;
2
3 import static org.opentrafficsim.base.parameters.constraint.NumericConstraint.POSITIVE;
4 import static org.opentrafficsim.base.parameters.constraint.NumericConstraint.POSITIVEZERO;
5
6 import java.util.LinkedHashMap;
7 import java.util.LinkedHashSet;
8 import java.util.Map;
9 import java.util.Set;
10
11 import org.djutils.exceptions.Throw;
12 import org.djutils.exceptions.Try;
13 import org.djutils.immutablecollections.Immutable;
14 import org.djutils.immutablecollections.ImmutableLinkedHashSet;
15 import org.djutils.immutablecollections.ImmutableSet;
16 import org.opentrafficsim.base.parameters.ParameterException;
17 import org.opentrafficsim.base.parameters.ParameterTypeDouble;
18 import org.opentrafficsim.base.parameters.Parameters;
19 import org.opentrafficsim.core.gtu.GtuException;
20 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
21 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
22 import org.opentrafficsim.road.gtu.lane.perception.mental.TaskManager.SummativeTaskManager;
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public class Fuller implements Mental
46 {
47
48
49
50
51 public static final ParameterTypeDouble TC = new ParameterTypeDouble("TC", "Task capability", 1.0, POSITIVE);
52
53
54 public static final ParameterTypeDouble TS_CRIT =
55 new ParameterTypeDouble("TScrit", "Critical task saturation", 0.8, POSITIVEZERO)
56 {
57
58 private static final long serialVersionUID = 20180403L;
59
60
61 @Override
62 public void check(final Double value, final Parameters params) throws ParameterException
63 {
64 Double tsMax = params.getParameterOrNull(TS_MAX);
65 Throw.when(tsMax != null && value > tsMax, ParameterException.class,
66 "Value for TS_CRIT should not be larger than TS_MAX.");
67 }
68 };
69
70
71 public static final ParameterTypeDouble TS_MAX =
72 new ParameterTypeDouble("TSmax", "Maximum task saturation", 2.0, POSITIVEZERO)
73 {
74
75 private static final long serialVersionUID = 20180403L;
76
77
78 @Override
79 public void check(final Double value, final Parameters params) throws ParameterException
80 {
81 Double tsCrit = params.getParameterOrNull(TS_CRIT);
82 Throw.when(tsCrit != null && value < tsCrit, ParameterException.class,
83 "Value for TS_MAX should not be smaller than TS_CRIT.");
84 }
85 };
86
87
88 public static final ParameterTypeDouble TS = new ParameterTypeDouble("TS", "Task saturation", 0.0, POSITIVEZERO);
89
90
91
92
93 private final Set<Task> tasks;
94
95
96 private final Set<BehavioralAdaptation> behavioralAdapatations;
97
98
99 private final TaskManager taskManager;
100
101
102 private Map<String, Double> anticipationReliances = new LinkedHashMap<>();
103
104
105 private Map<String, Double> taskDemands = new LinkedHashMap<>();
106
107
108
109
110
111
112 public Fuller(final Set<? extends Task> tasks, final Set<BehavioralAdaptation> behavioralAdapatations)
113 {
114 this(tasks, behavioralAdapatations, new SummativeTaskManager());
115 }
116
117
118
119
120
121
122
123 public Fuller(final Set<? extends Task> tasks, final Set<BehavioralAdaptation> behavioralAdapatations,
124 final TaskManager taskManager)
125 {
126 Throw.whenNull(tasks, "Tasks may not be null.");
127 Throw.whenNull(behavioralAdapatations, "Behavioral adaptations may not be null.");
128 this.tasks = new LinkedHashSet<>();
129 this.tasks.addAll(tasks);
130 this.behavioralAdapatations = behavioralAdapatations;
131 this.taskManager = taskManager;
132 }
133
134
135
136
137
138 public void addTask(final Task task)
139 {
140 this.tasks.add(task);
141 }
142
143
144
145
146
147 public void removeTask(final Task task)
148 {
149 this.tasks.remove(task);
150 }
151
152
153
154
155
156 public ImmutableSet<Task> getTasks()
157 {
158 return new ImmutableLinkedHashSet<>(this.tasks, Immutable.WRAP);
159 }
160
161
162 @Override
163 public void apply(final LanePerception perception) throws ParameterException, GtuException
164 {
165 LaneBasedGtu gtu = Try.assign(() -> perception.getGtu(), "Could not obtain GTU.");
166 Parameters parameters = gtu.getParameters();
167 double taskDemand = 0.0;
168
169
170 this.taskManager.manage(this.tasks, perception, gtu, parameters);
171 this.anticipationReliances.clear();
172 this.taskDemands.clear();
173 for (Task task : this.tasks)
174 {
175 double ar = task.getAnticipationReliance();
176 double td = task.getTaskDemand();
177 this.anticipationReliances.put(task.getId(), ar);
178 this.taskDemands.put(task.getId(), td);
179 taskDemand += (td - ar);
180 }
181 double taskSaturation = taskDemand / parameters.getParameter(TC);
182 parameters.setParameter(TS, taskSaturation);
183
184 for (BehavioralAdaptation behavioralAdapatation : this.behavioralAdapatations)
185 {
186 behavioralAdapatation.adapt(parameters, taskSaturation);
187 }
188
189
190
191 }
192
193
194
195
196
197
198 public double getAnticipationReliance(final String taskId)
199 {
200 return this.anticipationReliances.getOrDefault(taskId, Double.NaN);
201 }
202
203
204
205
206
207
208 public double getTaskDemand(final String taskId)
209 {
210 return this.taskDemands.getOrDefault(taskId, Double.NaN);
211 }
212
213
214 @Override
215 public String toString()
216 {
217 return "Fuller [tasks=" + this.tasks + ", behavioralAdapatations=" + this.behavioralAdapatations + "]";
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231 @FunctionalInterface
232 public interface BehavioralAdaptation
233 {
234
235
236
237
238
239
240 void adapt(Parameters parameters, double taskSaturation) throws ParameterException;
241 }
242
243 }